mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-28 20:16:52 -06:00
fix(pdf): prevent overflow in EPS integer arithmetic
Use checked division and remainder for EPS integer operators so i64::MIN with a divisor truncating to -1 cannot panic. Preserve the existing zero-divisor fallback and normal truncation behavior. Add public EPS parse regressions covering extreme, fractional and ordinary operands. PR #1223
This commit is contained in:
+4
-14
@@ -700,20 +700,10 @@ impl Interp {
|
||||
a / b
|
||||
}
|
||||
}
|
||||
"idiv" => {
|
||||
if b as i64 == 0 {
|
||||
0.0
|
||||
} else {
|
||||
((a as i64) / (b as i64)) as f64
|
||||
}
|
||||
}
|
||||
"mod" => {
|
||||
if b as i64 == 0 {
|
||||
0.0
|
||||
} else {
|
||||
((a as i64) % (b as i64)) as f64
|
||||
}
|
||||
}
|
||||
// `checked_*` give 0 both for a zero divisor and for the one overflowing
|
||||
// case, `i64::MIN / -1` (`/` and `%` panic on it in every build).
|
||||
"idiv" => (a as i64).checked_div(b as i64).unwrap_or(0) as f64,
|
||||
"mod" => (a as i64).checked_rem(b as i64).unwrap_or(0) as f64,
|
||||
"atan" => a.atan2(b).to_degrees().rem_euclid(360.0),
|
||||
"exp" => a.powf(b),
|
||||
"max" => a.max(b),
|
||||
|
||||
@@ -376,3 +376,25 @@ fn postscript_radix_numbers_outside_2_to_36_are_not_numbers() {
|
||||
let _ = parse(src.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postscript_idiv_and_mod_of_i64_min_by_minus_one_give_zero() {
|
||||
// `i64::MIN / -1` and `i64::MIN % -1` overflow, and `/` and `%` panic on them in debug and
|
||||
// release builds. `as i64` turns any dividend at or below -2^63 into `i64::MIN` and turns
|
||||
// a divisor of -1.5 into -1.
|
||||
for (prog, want) in [
|
||||
("-9223372036854775808 -1 idiv", 0),
|
||||
("-9223372036854775808 -1 mod", 0),
|
||||
("-99999999999999999999 -1.5 idiv", 0),
|
||||
("2 63 exp neg -1 mod", 0),
|
||||
// The result is 0 for a divisor that truncates to 0. Other quotients are truncated
|
||||
// toward zero, and a remainder has the sign of the dividend.
|
||||
("7 0 idiv", 0),
|
||||
("7 0.5 mod", 0),
|
||||
("-7 2 idiv", -3),
|
||||
("-7 2 mod", -1),
|
||||
] {
|
||||
let doc = eps(format!("{prog} {want} eq {{ 0 0 10 10 rectfill }} if\n").as_bytes());
|
||||
assert_eq!(shape_names(&doc).len(), 1, "{prog}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user