2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

compel: fix GCC 12 failure (out of bounds)

This is a confusing change as it seems the original code was just wrong.
GCC 12 complains with:

In function ‘__conv_val’,
    inlined from ‘std_strtoul’ at compel/plugins/std/string.c:202:7:
compel/plugins/std/string.c:154:24: error: array subscript 97 is above array bounds of ‘const char[37]’ [-Werror=array-bounds]
  154 |                 return &conv_tab[__tolower(c)] - conv_tab;
      |                        ^~~~~~~~~~~~~~~~~~~~~~~
compel/plugins/std/string.c: In function ‘std_strtoul’:
compel/plugins/std/string.c:10:19: note: while referencing ‘conv_tab’
   10 | static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
      |                   ^~~~~~~~
cc1: all warnings being treated as errors

Which sounds correct. The array conv_tab has just 37 elements.

If I understand the code correctly we are trying to convert anything
that is character between a-z and A-Z to a number for cases where
the base is larger than 10. For a base 11 conversion b|B should return 11.
For a base 35 conversion z|Z should return 35. This is all for a strtoul()
implementation.

The original code was:

  static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";

  return &conv_tab[__tolower(c)] - conv_tab;

and that seems wrong. If conv_tab would have been some kind of hash it could
have worked, but '__tolower()' will always return something larger than
97 ('a') which will always overflow the array.

But maybe I just don't get that part of the code.

I replaced it with

  return __tolower(c) - 'a' + 10;

which does the right thing: 'A' = 10, 'B' = 11 ... 'Z' = 35

Signed-off-by: Adrian Reber <areber@redhat.com>
This commit is contained in:
Adrian Reber
2022-01-18 16:49:40 +00:00
committed by Andrei Vagin
parent 6be10a232d
commit bf6975c3e5

View File

@@ -151,7 +151,12 @@ static unsigned int __conv_val(unsigned char c)
if (__isdigit(c))
return c - '0';
else if (__isalpha(c))
return &conv_tab[__tolower(c)] - conv_tab;
/**
* If we want the value of something which __isalpha() == true
* it has to be base > 10. 'A' = 10, 'B' = 11 ... 'Z' = 35
*/
return __tolower(c) - 'a' + 10;
return -1u;
}