Merge 'Fix compute_shl negate with overflow' from Krishna Vishal

Fixes #1156
- Changed `compute_shl` implementation to handle negation with overflow.
- Added TCL tests.

Closes #1171
This commit is contained in:
Pekka Enberg
2025-03-26 16:08:59 +02:00
2 changed files with 88 additions and 9 deletions

View File

@@ -975,7 +975,27 @@ pub fn exec_shift_left(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue
}
fn compute_shl(lhs: i64, rhs: i64) -> i64 {
compute_shr(lhs, -rhs)
if rhs == 0 {
lhs
} else if rhs > 0 {
// for positive shifts, if it's too large return 0
if rhs >= 64 {
0
} else {
lhs << rhs
}
} else {
// for negative shifts, check if it's i64::MIN to avoid overflow on negation
if rhs == i64::MIN || rhs <= -64 {
if lhs < 0 {
-1
} else {
0
}
} else {
lhs >> (-rhs)
}
}
}
pub fn exec_shift_right(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValue {
@@ -1013,15 +1033,24 @@ pub fn exec_shift_right(mut lhs: &OwnedValue, mut rhs: &OwnedValue) -> OwnedValu
fn compute_shr(lhs: i64, rhs: i64) -> i64 {
if rhs == 0 {
lhs
} else if rhs >= 64 && lhs >= 0 || rhs <= -64 {
0
} else if rhs >= 64 && lhs < 0 {
-1
} else if rhs < 0 {
// if negative do left shift
lhs << (-rhs)
} else if rhs > 0 {
// for positive right shifts
if rhs >= 64 {
if lhs < 0 {
-1
} else {
0
}
} else {
lhs >> rhs
}
} else {
lhs >> rhs
// for negative right shifts, check if it's i64::MIN to avoid overflow
if rhs == i64::MIN || -rhs >= 64 {
0
} else {
lhs << (-rhs)
}
}
}

View File

@@ -165,3 +165,53 @@ do_execsql_test select-not-like-expression {
do_execsql_test select-like-expression {
select 2 % 0.5
} {}
do_execsql_test select_shl_large_negative_float {
SELECT 1 << -1e19;
SELECT 1 << -9223372036854775808; -- i64::MIN
SELECT 1 << 9223372036854775807; -- i64::MAX
} {0 0 0}
do_execsql_test select_shl_basic {
SELECT 1 << 0, 1 << 1, 1 << 2, 1 << 3;
SELECT 2 << 0, 2 << 1, 2 << 2, 2 << 3;
} {1|2|4|8
2|4|8|16}
do_execsql_test select_shl_negative_numbers {
SELECT -1 << 0, -1 << 1, -1 << 2, -1 << 3;
SELECT -2 << 0, -2 << 1, -2 << 2, -2 << 3;
} {-1|-2|-4|-8
-2|-4|-8|-16}
do_execsql_test select_shl_negative_shifts {
SELECT 8 << -1, 8 << -2, 8 << -3, 8 << -4;
SELECT -8 << -1, -8 << -2, -8 << -3, -8 << -4;
} {4|2|1|0
-4|-2|-1|-1}
do_execsql_test select_shl_large_shifts {
SELECT 1 << 62, 1 << 63, 1 << 64;
SELECT -1 << 62, -1 << 63, -1 << 64;
} {4611686018427387904|-9223372036854775808|0
-4611686018427387904|-9223372036854775808|0}
do_execsql_test select_shl_text_conversion {
SELECT '1' << '2';
SELECT '8' << '-2';
SELECT '-4' << '2';
} {4 2 -16}
do_execsql_test select_shl_chained {
SELECT (1 << 2) << 3;
SELECT (2 << 1) << (1 << 1);
} {32 16}
do_execsql_test select_shl_numeric_types {
SELECT CAST(1 AS INTEGER) << 2;
SELECT 1.0 << 2;
SELECT 1.5 << 2;
} {4 4 4}
do_execsql_test select_fuzz_failure_case {
SELECT (-9 << ((-6) << (9)) >> ((5)) % -10 - + - (-9));
} {-16}