diff --git a/src/config/config_type.rs b/src/config/config_type.rs index f559cc0d620..6611a387814 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -435,14 +435,14 @@ macro_rules! create_config { /// arms within a declarative macro. #[allow(unreachable_pub)] pub fn reduce_max_width(&mut self, delta: usize) { - self.adjust_max_width(-(delta as isize)); + self.adjust_max_width(-(delta.min(isize::MAX as usize) as isize)); } /// Increases the maximum width of the configuration. /// /// This method is intended to be used when creating a forked /// configuration for a particular formatting context in which the - /// total available width needs to be reduced. This increases the + /// total available width needs to be increased. This increases the /// size of max_width, and all other properties affected by small /// heuristics, without treating those adjustments as overrides. /// @@ -450,7 +450,7 @@ macro_rules! create_config { /// arms within a declarative macro. #[allow(unreachable_pub)] pub fn increase_max_width(&mut self, delta: usize) { - self.adjust_max_width(delta as isize); + self.adjust_max_width(delta.min(isize::MAX as usize) as isize); } /// Adjusts the maximum width of the configuration. @@ -464,7 +464,9 @@ macro_rules! create_config { /// As an example use case, this method is used when formatting /// arms within a declarative macro. fn adjust_max_width(&mut self, delta: isize) { - let adjust = |value: usize| (value as isize + delta) as usize; + // NB: we need to either saturate or report an error (or some kind of testable + // warning). I picked to saturate here. + let adjust = |value: usize| value.saturating_add_signed(delta); self.array_width.2 = adjust(self.array_width.2); self.attr_fn_like_width.2 = adjust(self.attr_fn_like_width.2); diff --git a/src/config/mod.rs b/src/config/mod.rs index 780402d21fe..141933cd7cf 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -698,6 +698,23 @@ mod test { assert_eq!(config.verbose(), Verbosity::Normal); } + #[test] + fn test_adjust_max_width() { + // Regression tests for #7147, where we didn't handle overflows / integral cast outside of + // range properly. + + // Reduce with huge amount saturates to zero instead of wraparound. + let mut config = Config::default(); + config.reduce_max_width(usize::MAX); + assert_eq!(config.max_width(), 0); + + // Increase with huge amount saturates instead of wraparound. + let mut config = Config::default(); + config.set().max_width(usize::MAX - 1); + config.increase_max_width(2); + assert_eq!(config.max_width(), usize::MAX); + } + #[test] fn test_config_used_to_toml() { let config = Config::default();