https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124442

            Bug ID: 124442
           Summary: -O3 assumes impossible worst case. Gives false
                    positive warning
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: malekwryyy at gmail dot com
  Target Milestone: ---

```
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

static const unsigned long long ten_pows_ull[] = {
    1ull,
    10ull,
    100ull,
    1000ull,
    10000ull,
    100000ull,
    1000000ull,
    10000000ull,
    100000000ull,
    1000000000ull,
    10000000000ull,
    100000000000ull,
    1000000000000ull,
    10000000000000ull,
    100000000000000ull,
    1000000000000000ull,
    10000000000000000ull,
    100000000000000000ull,
    1000000000000000000ull,
    10000000000000000000ull,
};

static inline unsigned int numstr_len(unsigned long long num)
{
    unsigned int len = 1;
    for(unsigned int i = 1 ; i < (sizeof(ten_pows_ull) /
sizeof((ten_pows_ull)[0])) && num >= ten_pows_ull[i] ; len++)
        i++;
    return len;
}

char *ushort_tostr(unsigned short num)
{
    unsigned int chars_to_copy = numstr_len(num);
    char tmp_buf[8] = {0};
    for (unsigned int i = 0; i < chars_to_copy ; i++)
    { unsigned char rem = (unsigned char)(num % 10);
        num = num / 10;
        tmp_buf[chars_to_copy - (i + 1)] = (char)(rem + '0');
    }
    return strdup(tmp_buf);
}
```

When using -O3, the following warning is generated:
```
<source>:45:42: warning: writing 1 byte into a region of size 0
[-Wstringop-overflow=]
   45 |         tmp_buf[chars_to_copy - (i + 1)] = (char)(rem + '0');
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
<source>:41:10: note: at offset 19 into destination object 'tmp_buf' of size 8
   41 |     char tmp_buf[8] = {0};
      |    
```

It seems that gcc treats `numstr_len` as returning 20, which is the highest
number it can return if passed a `unsigned long long`.

But that isn't possible to be returned here, since I'm casting from an
`unsigned short`. The maximum possible return is 5, for USHRT_MAX.

Reply via email to