I have this little snippet here:
static int32_t s_pow(int32_t base, int32_t exponent)
{
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
base *= base; /* <- this line */
}
return result;
}
Small and neat and just the one I need. But GCC 7.5.0 (and other newer versions that support the checks) complained:
gcc -I./ -Wall -Wsign-compare -Wextra -Wshadow -fsanitize=undefined\
-fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero\
-Wdeclaration-after-statement -Wbad-function-cast -Wcast-align -Wstrict-prototypes\
-Wpointer-arith -Wsystem-headers -O3 -funroll-loops -fomit-frame-pointer -flto -m64\
test.o -o test
test.c:25:12: runtime error: signed integer overflow: 65536 * 65536 cannot be represented in type 'int'
Yes, GCC, that is correct, 65536 * 65536 is a bit much for a 31 bit data type even in a 64 bit environment, admitted. But the input comes from a small table and is carefully chosen in such a way that the result result
cannot exceed 2^20
and therefor none of the intermediate results can. I cannot change the sanitizing itself only my code. Yes, I checked all possible results.
Any ideas? Or is it my code?
As I see runtime error: signed integer overflow
is happened in runtime. It means that you send an input leading to UB. You say that result cannot exceed 2^20
. As I guess you mean that you have a case where you make base *= base
action after you already got a result, and don't care about base
anymore.
If I understand you right, you can just change code to something like this I guess?
It will give you a fix for s_pow(60000, 1)
call for example, and won't affect performance, due optimization is quite easy for compiler here.
static int32_t s_pow(int32_t base, int32_t exponent) {
int32_t result = 1;
while (exponent != 0) {
if ((exponent % 2) == 1) {
result *= base;
}
exponent /= 2;
if (exponent == 0) {
break;
}
base *= base; /* <- this line */
}
return result;
}
Basically it is important to understand what you want here, if you want to remove annoying warning, here it is a way. If warning still appears, probably you send too big numbers.