JavaScript: the script a realm runs does not count against the re-entry limit

Limits::reentry bounds runs inside an operation (getters, setters, conversions, indirect eval). The top-level script took one of those slots, so a limit of 0 refused every script and a limit of 1 left no room for a getter. Only indirect eval now counts when it starts a global run.
This commit is contained in:
dotCooCoo
2026-11-07 15:29:40 -08:00
parent 5ebf32e973
commit 0b936bf60e
2 changed files with 17 additions and 3 deletions
+6 -3
View File
@@ -1810,7 +1810,10 @@ impl Interp {
/// Indirect eval and scripts: runs `code` in the global environment and returns its
/// completion value.
pub(crate) fn run_global(&mut self, code: Rc<Code>, is_eval: bool) -> JsResult<Value> {
if self.reentry >= self.limits.reentry {
// Indirect eval runs inside an operation and counts against the re-entry limit; the
// script a realm runs does not.
let nested = usize::from(is_eval);
if is_eval && self.reentry >= self.limits.reentry {
return Err(Abrupt::Limit(LimitKind::Reentry));
}
self.charge_code(&code, declaration_bytes(&code).saturating_add(ENV_BYTES))?;
@@ -1823,9 +1826,9 @@ impl Interp {
};
self.instantiate_global(&code, var_env, is_eval)?;
self.push_code_frame(code, env, var_env, Value::Object(global), true)?;
self.reentry += 1;
self.reentry += nested;
let r = self.execute();
self.reentry -= 1;
self.reentry -= nested;
r
}
+11
View File
@@ -515,6 +515,17 @@ fn reentry_through_getters_ends_with_the_reentry_limit() {
}
}
#[test]
fn the_script_itself_does_not_count_against_the_reentry_limit() {
let mut realm = small(Limits { reentry: 0, ..Limits::default() });
assert_eq!(realm.run("1 + 1"), Ok(JsValue::Number(2.0)));
assert_eq!(limit(&mut realm, "var o = { get x() { return 1; } }; o.x"), LimitKind::Reentry);
realm.set_limits(Limits { reentry: 1, ..Limits::default() });
assert_eq!(realm.run("o.x"), Ok(JsValue::Number(1.0)));
assert_eq!(realm.run("(0, eval)('2 + 2')"), Ok(JsValue::Number(4.0)));
assert_eq!(limit(&mut realm, "var p = { get x() { return o.x; } }; p.x"), LimitKind::Reentry);
}
#[test]
fn memory_bombs_end_with_the_heap_limit() {
let limits = Limits { heap_bytes: 4 << 20, ..Limits::default() };