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.