Skip to content

Commit

Permalink
sql: Fix overflow when negating min ints (MaterializeInc#14306)
Browse files Browse the repository at this point in the history
This commit fixes a panic when trying to negate the minimum value of
some integer type. Integer types are not symmetric with respect to
their positive and negative ranges. There is one more negative number
than positive numbers. Therefore, negating the minimum value of an
integer type will fail.

Fixes #14291
  • Loading branch information
jkosh44 authored Aug 19, 2022
1 parent 699109f commit 72cac94
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
8 changes: 4 additions & 4 deletions src/expr/src/scalar/func/impls/int16.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use crate::EvalError;

sqlfunc!(
#[sqlname = "-"]
fn neg_int16(a: i16) -> i16 {
-a
fn neg_int16(a: i16) -> Result<i16, EvalError> {
a.checked_neg().ok_or(EvalError::Int16OutOfRange)
}
);

Expand All @@ -34,8 +34,8 @@ sqlfunc!(

sqlfunc!(
#[sqlname = "abs"]
fn abs_int16(a: i16) -> i16 {
a.abs()
fn abs_int16(a: i16) -> Result<i16, EvalError> {
a.checked_abs().ok_or(EvalError::Int16OutOfRange)
}
);

Expand Down
8 changes: 4 additions & 4 deletions src/expr/src/scalar/func/impls/int32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use crate::EvalError;

sqlfunc!(
#[sqlname = "-"]
fn neg_int32(a: i32) -> i32 {
-a
fn neg_int32(a: i32) -> Result<i32, EvalError> {
a.checked_neg().ok_or(EvalError::Int32OutOfRange)
}
);

Expand All @@ -35,8 +35,8 @@ sqlfunc!(

sqlfunc!(
#[sqlname = "abs"]
fn abs_int32(a: i32) -> i32 {
a.abs()
fn abs_int32(a: i32) -> Result<i32, EvalError> {
a.checked_abs().ok_or(EvalError::Int32OutOfRange)
}
);

Expand Down
8 changes: 4 additions & 4 deletions src/expr/src/scalar/func/impls/int64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use crate::EvalError;
sqlfunc!(
#[sqlname = "-"]
#[preserves_uniqueness = true]
fn neg_int64(a: i64) -> i64 {
-a
fn neg_int64(a: i64) -> Result<i64, EvalError> {
a.checked_neg().ok_or(EvalError::Int64OutOfRange)
}
);

Expand All @@ -37,8 +37,8 @@ sqlfunc!(

sqlfunc!(
#[sqlname = "abs"]
fn abs_int64(a: i64) -> i64 {
a.abs()
fn abs_int64(a: i64) -> Result<i64, EvalError> {
a.checked_abs().ok_or(EvalError::Int64OutOfRange)
}
);

Expand Down
20 changes: 20 additions & 0 deletions test/sqllogictest/arithmetic.slt
Original file line number Diff line number Diff line change
Expand Up @@ -1130,3 +1130,23 @@ SELECT
~1 - 2 as def_sub, ~(1 - 2) as l_prec_sub, (~1) - 2 as h_prec_sub
----
-3 -3 -1 0 0 -4

# overflow for negating minimum integers

query error smallint out of range
SELECT - '-32768'::int2

query error smallint out of range
SELECT ABS('-32768'::int2)

query error integer out of range
SELECT - '-2147483648'::int4

query error integer out of range
SELECT ABS('-2147483648'::int4)

query error bigint out of range
SELECT - '-9223372036854775808'::int8

query error bigint out of range
SELECT ABS('-9223372036854775808'::int8)

0 comments on commit 72cac94

Please sign in to comment.