aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-11-25 23:27:33 -0500
committerGitHub <noreply@github.com>2019-11-25 23:27:33 -0500
commit74bf0ce5c2e993eab0e34aa00a9449e612e5a6d9 (patch)
treef9be87961ff560ee523c165ff3041a64b34ed3dc /components/script/dom/bindings/codegen
parentf1aa5d8dbdc32f6f474b09234558652b9bead686 (diff)
parent38a666742fbfcd5b392d8644622af890c0ff25cd (diff)
downloadservo-74bf0ce5c2e993eab0e34aa00a9449e612e5a6d9.tar.gz
servo-74bf0ce5c2e993eab0e34aa00a9449e612e5a6d9.zip
Auto merge of #24866 - Manishearth:iterator-invalidation, r=jdm
Fix iterator invalidation in our forEach implementation. Currently we iterate over iterables in forEach based on the length they report when we start iterating, however the inner callback is able to change this. ```js let params = new URLSearchParams("foo=bar&baz=qux"); params.forEach((p) => { console.log(p); params.delete("baz"); }) ``` This causes us to panic [here](https://github.com/servo/servo/blob/f1aa5d8dbdc32f6f474b09234558652b9bead686/components/script/dom/bindings/codegen/CodegenRust.py#L7412) over an attempt to access out of bounds. Relevant spec: https://heycam.github.io/webidl/#es-forEach r? @jdm
Diffstat (limited to 'components/script/dom/bindings/codegen')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py13
1 files changed, 12 insertions, 1 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index fe3398417b2..39e8bfa275d 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -7408,7 +7408,16 @@ class CGIterableMethodGenerator(CGGeneric):
rooted!(in(*cx) let mut call_arg2 = UndefinedValue());
let mut call_args = vec![UndefinedValue(), UndefinedValue(), ObjectValue(*_obj)];
rooted!(in(*cx) let mut ignoredReturnVal = UndefinedValue());
- for i in 0..(*this).get_iterable_length() {
+
+ // This has to be a while loop since get_iterable_length() may change during
+ // the callback, and we need to avoid iterator invalidation.
+ //
+ // It is possible for this to loop infinitely, but that matches the spec
+ // and other browsers.
+ //
+ // https://heycam.github.io/webidl/#es-forEach
+ let mut i = 0;
+ while i < (*this).get_iterable_length() {
(*this).get_value_at_index(i).to_jsval(*cx, call_arg1.handle_mut());
(*this).get_key_at_index(i).to_jsval(*cx, call_arg2.handle_mut());
call_args[0] = call_arg1.handle().get();
@@ -7418,6 +7427,8 @@ class CGIterableMethodGenerator(CGGeneric):
ignoredReturnVal.handle_mut()) {
return false;
}
+
+ i += 1;
}
let result = ();