Subject: [PATCH] maint: Avoid signed integer overflows

From: Tobias Stoeckmann <[email-masked]>
Date: Sun, 14 Jun 2020 14:47:11 +0200

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 | 2 +-
 src/seq.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/numfmt.c b/src/numfmt.c
index 8869791b0..8871a8c01 100644
--- a/src/numfmt.c
+++ b/src/numfmt.c
@@ -1496,7 +1496,7 @@ main (int argc, char **argv)
 
         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)
diff --git a/src/seq.c b/src/seq.c
index ddb63b642..2ca1e4f7b 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -197,7 +197,7 @@ scan_arg (const char *arg)
         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.  */
-- 
2.27.0