Since -LONG_MIN results in LONG_MIN again, the operation itself is
a signed integer overflow.
This can be observed with the following calls (best if compiled
with -ftrapv or -fsanitize=undefined):
$ numfmt --padding=-
9223372036854775808
$ seq 1e-
9223372036854775808
Technically, the change in seq "reduces" the precision, but a double
or long double that small would be represented as 0 anyway.
* src/numfmt.c: Explicitly disallow --padding=LONG_MIN.
* src/seq.c: Treat 1e$LONG_MIN as 1e-$LONG_MAX.
* tests/misc/numfmt.pl: Add a test case.
* tests/misc/seq-precision.sh: Likewise.
Fixes https://bugs.gnu.org/41850
case PADDING_OPTION:
if (xstrtol (optarg, NULL, 10, &padding_width, "") != LONGINT_OK
- || padding_width == 0)
+ || padding_width == 0 || padding_width < -LONG_MAX)
die (EXIT_FAILURE, 0, _("invalid padding value %s"),
quote (optarg));
if (padding_width < 0)
e = strchr (arg, 'E');
if (e)
{
- long exponent = strtol (e + 1, NULL, 10);
+ long exponent = MAX (strtol (e + 1, NULL, 10), -LONG_MAX);
ret.precision += exponent < 0 ? -exponent
: - MIN (ret.precision, exponent);
/* Don't account for e.... in the width since this is not output. */
['pad-3.1', '--padding=0 5',
{ERR => "$prog: invalid padding value '0'\n"},
{EXIT => '1'}],
+ ['pad-3.2', "--padding=$limits->{LONG_MIN} 0",
+ {ERR => "$prog: invalid padding value '$limits->{LONG_MIN}'\n"},
+ {EXIT => '1'}],
['pad-4', '--padding=10 --to=si 50000', {OUT=>' 50K'}],
['pad-5', '--padding=-10 --to=si 50000', {OUT=>'50K '}],
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
print_ver_ seq
+getlimits_
# Integer only. Before v8.24 these would switch output format
printf "%s\n" 110000 > exp || framework_failure_
compare exp out || fail=1
+# Ensure no undefined behavior which failed with <= 8.32
+# This test would fail with: -fsanitize=undefined
+seq 1e$LONG_MIN 2> err || fail=1
+compare /dev/null err || fail=1
+
Exit $fail