diff --git a/crates/eps/src/import/interp.rs b/crates/eps/src/import/interp.rs index f4c210b9c..75f7c7d13 100644 --- a/crates/eps/src/import/interp.rs +++ b/crates/eps/src/import/interp.rs @@ -816,7 +816,7 @@ impl<'a> Interp<'a> { }, Bitshift => { let (s, v) = (self.pop_int()?, self.pop_int()?); - let r = if s >= 0 { v.checked_shl(s.min(63) as u32) } else { v.checked_shr((-s).min(63) as u32) }; + let r = if s >= 0 { v.checked_shl(s.min(63) as u32) } else { v.checked_shr(s.saturating_neg().min(63) as u32) }; self.push(Obj::Int(r.unwrap_or(0)))?; } True => self.push(Obj::Bool(true))?, diff --git a/crates/eps/src/import/tests.rs b/crates/eps/src/import/tests.rs index 8f9cb5581..86fa8e35d 100644 --- a/crates/eps/src/import/tests.rs +++ b/crates/eps/src/import/tests.rs @@ -1400,3 +1400,10 @@ fn stored_graphics_states_use_up_the_memory_budget() { assert!(r.warnings.iter().any(|w| w.contains("uses too much memory")), "{body}: {:?}", r.warnings); } } + +/// `bitshift` by the most negative integer shifts right by everything, not a negation overflow. +#[test] +fn bitshift_by_the_most_negative_integer_does_not_panic() { + let r = read("0 0 10 10 rectfill 1 -9223372036854775808 bitshift pop -1 -9223372036854775808 bitshift pop"); + assert_eq!(objects(&r.document).len(), 1, "{:?}", r.warnings); +}