Skip to content

Commit

Permalink
fix(linter): invalid binary expression with overflow (#4647)
Browse files Browse the repository at this point in the history
Closes #4628

Also fixes an identical bug in `<<`
  • Loading branch information
DonIsaac committed Aug 5, 2024
1 parent 0fba738 commit 06aec77
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions crates/oxc_linter/src/utils/tree_shaking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,11 @@ pub fn calculate_binary_operation(op: BinaryOperator, left: Value, right: Value)

BinaryOperator::ShiftRightZeroFill => match (left, right) {
(Value::Number(a), Value::Number(b)) => {
Value::Number(f64::from((a as u32) >> (b as u32)))
if b >= a {
Value::Number(0.0)
} else {
Value::Number(f64::from((a as u32) >> (b as u32)))
}
}
_ => Value::Unknown,
},
Expand All @@ -447,7 +451,12 @@ pub fn calculate_binary_operation(op: BinaryOperator, left: Value, right: Value)
},
BinaryOperator::ShiftLeft => match (left, right) {
(Value::Number(a), Value::Number(b)) => {
Value::Number(f64::from((a as i32) << (b as i32)))
// NOTE: could overflow, in which case node produces `a`
if b >= 32.0 {
Value::Number(a)
} else {
Value::Number(f64::from((a as i32) << (b as i32)))
}
}
_ => Value::Unknown,
},
Expand Down Expand Up @@ -589,15 +598,22 @@ fn test_calculate_binary_operation() {

// "<<",
let op = BinaryOperator::ShiftLeft;
assert_eq!(fun(op, Value::Number(1.0), Value::Number(0.0),), Value::Number(1.0));
assert_eq!(fun(op, Value::Number(1.0), Value::Number(2.0),), Value::Number(4.0));
assert_eq!(fun(op, Value::Number(1.0), Value::Number(31.0),), Value::Number(-2_147_483_648.0));
assert_eq!(fun(op, Value::Number(1.0), Value::Number(f64::MAX),), Value::Number(1.0));

// ">>",
let op = BinaryOperator::ShiftRight;
assert_eq!(fun(op, Value::Number(4.0), Value::Number(2.0),), Value::Number(1.0));

// ">>>",
let op = BinaryOperator::ShiftRightZeroFill;
assert_eq!(fun(op, Value::Number(0.0), Value::Number(0.0),), Value::Number(0.0));
assert_eq!(fun(op, Value::Number(1.0), Value::Number(0.0),), Value::Number(1.0));
assert_eq!(fun(op, Value::Number(4.0), Value::Number(2.0),), Value::Number(1.0));
assert_eq!(fun(op, Value::Number(2.0), Value::Number(4.0),), Value::Number(0.0));
assert_eq!(fun(op, Value::Number(4096.0), Value::Number(4096.0)), Value::Number(0.0));

// "%",
let op = BinaryOperator::Remainder;
Expand Down

0 comments on commit 06aec77

Please sign in to comment.