diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-11-25 23:27:33 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-25 23:27:33 -0500 |
commit | 74bf0ce5c2e993eab0e34aa00a9449e612e5a6d9 (patch) | |
tree | f9be87961ff560ee523c165ff3041a64b34ed3dc /components/script/dom/bindings/codegen | |
parent | f1aa5d8dbdc32f6f474b09234558652b9bead686 (diff) | |
parent | 38a666742fbfcd5b392d8644622af890c0ff25cd (diff) | |
download | servo-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.py | 13 |
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 = (); |