From 6ed53f13bc39d9a0252549e98a2a59441fb2351f Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 27 Apr 2016 12:10:54 -0700 Subject: [PATCH] xstrtol: prohibit monstrosities like "1bB" Problem reported by Young Mo Kang in: http://bugs.gnu.org/23388 * lib/xstrtol.c (__xstrtol): Allow trailing second suffixes like "B" only if the first suffix needs a base. * tests/test-xstrtol.sh: Test this. --- ChangeLog | 8 ++++++++ lib/xstrtol.c | 35 +++++++++++++++++++++-------------- tests/test-xstrtol.sh | 4 ++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2589371d21..09c302cb9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2016-04-27 Paul Eggert + + xstrtol: prohibit monstrosities like "1bB" + Problem reported by Young Mo Kang in: http://bugs.gnu.org/23388 + * lib/xstrtol.c (__xstrtol): Allow trailing second suffixes like + "B" only if the first suffix needs a base. + * tests/test-xstrtol.sh: Test this. + 2016-04-21 Pádraig Brady xstrtod: reinstate setting of *result upon ERANGE diff --git a/lib/xstrtol.c b/lib/xstrtol.c index 5a3afb545e..c5b16922c3 100644 --- a/lib/xstrtol.c +++ b/lib/xstrtol.c @@ -148,8 +148,11 @@ __xstrtol (const char *s, char **ptr, int strtol_base, return err | LONGINT_INVALID_SUFFIX_CHAR; } - if (strchr (valid_suffixes, '0')) + switch (**p) { + case 'E': case 'G': case 'g': case 'k': case 'K': case 'M': case 'm': + case 'P': case 'T': case 't': case 'Y': case 'Z': + /* The "valid suffix" '0' is a special flag meaning that an optional second suffix is allowed, which can change the base. A suffix "B" (e.g. "100MB") stands for a power @@ -157,19 +160,20 @@ __xstrtol (const char *s, char **ptr, int strtol_base, a power of 1024. If no suffix (e.g. "100M"), assume power-of-1024. */ - switch (p[0][1]) - { - case 'i': - if (p[0][2] == 'B') - suffixes += 2; - break; - - case 'B': - case 'D': /* 'D' is obsolescent */ - base = 1000; - suffixes++; - break; - } + if (strchr (valid_suffixes, '0')) + switch (p[0][1]) + { + case 'i': + if (p[0][2] == 'B') + suffixes += 2; + break; + + case 'B': + case 'D': /* 'D' is obsolescent */ + base = 1000; + suffixes++; + break; + } } switch (**p) @@ -179,6 +183,9 @@ __xstrtol (const char *s, char **ptr, int strtol_base, break; case 'B': + /* This obsolescent first suffix is distinct from the 'B' + second suffix above. E.g., 'tar -L 1000B' means change + the tape after writing 1000 KiB of data. */ overflow = bkm_scale (&tmp, 1024); break; diff --git a/tests/test-xstrtol.sh b/tests/test-xstrtol.sh index f718d8f779..5425bc79dc 100755 --- a/tests/test-xstrtol.sh +++ b/tests/test-xstrtol.sh @@ -16,6 +16,7 @@ test-xstrtol 9x >> out 2>&1 && result=1 test-xstrtol 010 >> out 2>&1 || result=1 # suffix without integer is valid test-xstrtol MiB >> out 2>&1 || result=1 +test-xstrtol 1bB >> out 2>&1 && result=1 # test xstrtoul test-xstrtoul 1 >> out 2>&1 || result=1 @@ -27,6 +28,7 @@ test-xstrtoul x >> out 2>&1 && result=1 test-xstrtoul 9x >> out 2>&1 && result=1 test-xstrtoul 010 >> out 2>&1 || result=1 test-xstrtoul MiB >> out 2>&1 || result=1 +test-xstrtoul 1bB >> out 2>&1 && result=1 # Find out how to remove carriage returns from output. Solaris /usr/ucb/tr # does not understand '\r'. @@ -51,6 +53,7 @@ invalid X argument 'x' invalid suffix in X argument '9x' 010->8 () MiB->1048576 () +invalid suffix in X argument '1bB' 1->1 () invalid X argument '-1' 1k->1024 () @@ -60,6 +63,7 @@ invalid X argument 'x' invalid suffix in X argument '9x' 010->8 () MiB->1048576 () +invalid suffix in X argument '1bB' EOF compare expected out || result=1 -- 2.39.5