Fix UBSan error with overflowing exponent operator (#1727)

This commit is contained in:
Rangi
2025-07-07 19:08:26 -04:00
committed by GitHub
parent c9765ec158
commit 1a77667409
5 changed files with 27 additions and 11 deletions

View File

@@ -21,20 +21,17 @@ int32_t op_modulo(int32_t dividend, int32_t divisor) {
} }
int32_t op_exponent(int32_t base, uint32_t power) { int32_t op_exponent(int32_t base, uint32_t power) {
int32_t result = 1; uint32_t result = 1;
for (;;) { for (uint32_t ubase = base; power; power /= 2) {
if (power % 2) { if (power % 2) {
result *= base; result = static_cast<uint64_t>(result) * ubase;
} }
power /= 2; ubase = static_cast<uint64_t>(ubase) * ubase;
if (!power) {
break;
}
base *= base;
} }
return result; // Avoid arithmetic overflow runtime error
return result <= INT32_MAX ? result : -static_cast<int32_t>(~result) - 1;
} }
int32_t op_shift_left(int32_t value, int32_t amount) { int32_t op_shift_left(int32_t value, int32_t amount) {

11
test/asm/exponent.asm Normal file
View File

@@ -0,0 +1,11 @@
def n = 30
for x, -n, n
for p, n
def v1 = x ** p
def v2 = 1
for i, p
def v2 *= x
endr
assert v1 == v2, "{d:x}**{d:p} = {d:v1} or {d:v2}?"
endr
endr

View File

@@ -34,6 +34,12 @@ def x = x << 1
dl -1 << 1 dl -1 << 1
print_x print_x
def x = 2 ** 31
print_x
def x = 5 ** 29
print_x
def x = 4294967295 def x = 4294967295
def x = 4294967296 def x = 4294967296

View File

@@ -2,7 +2,7 @@ warning: overflow.asm(23): [-Wdiv]
Division of -2147483648 by -1 yields -2147483648 Division of -2147483648 by -1 yields -2147483648
warning: overflow.asm(24): [-Wdiv] warning: overflow.asm(24): [-Wdiv]
Division of -2147483648 by -1 yields -2147483648 Division of -2147483648 by -1 yields -2147483648
warning: overflow.asm(38): [-Wlarge-constant] warning: overflow.asm(44): [-Wlarge-constant]
Integer constant is too large Integer constant is too large
warning: overflow.asm(41): [-Wlarge-constant] warning: overflow.asm(47): [-Wlarge-constant]
Graphics constant is too long, only first 8 pixels considered Graphics constant is too long, only first 8 pixels considered

View File

@@ -4,3 +4,5 @@ $80000000
$80000000 $80000000
$0 $0
$FFFFFFFE $FFFFFFFE
$80000000
$6B90BE55