New issue
Advanced search Search tips

Issue 728547 link

Starred by 1 user

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

Scoping problems in arrow functions with destructured parameters

Project Member Reported by ClusterFuzz, Jun 1 2017

Issue description

Detailed report: https://clusterfuzz.com/testcase?key=5625401752944640

Fuzzer: inferno_js_fuzzer
Job Type: linux_ubsan_vptr_d8
Platform Id: linux

Crash Type: CHECK failure
Crash Address: 
Crash State:
  fixed_size_above_fp + (stack_slots * kPointerSize) - CommonFrameConstants::kFixe
  
Sanitizer: undefined (UBSAN)

Regressed: https://clusterfuzz.com/revisions?job=linux_ubsan_vptr_d8&range=462021:462035

Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=5625401752944640


Issue filed automatically.

See https://dev.chromium.org/Home/chromium-security/bugs/reproducing-clusterfuzz-bugs for more information.
 
Cc: adamk@chromium.org marja@chromium.org
Owner: ca...@igalia.com
Status: Assigned (was: Untriaged)
Reproduces in d8, and bisects to 5f782db9541eca72dc6cbe3c6f5e8dc52ff7c16f.

Comment 2 by marja@chromium.org, Jun 7 2017

Indeed, reproes with --no-turbo and --no-lazy.

So, we're deoptimizing an eagerly parsed arrow function which has ({ x } = { x: 1 }) as a param list.

No idea what goes wrong though... :(

Comment 3 by marja@chromium.org, Jun 7 2017

Even though this is related to deoptimization happening and --no-turbo, maybe there's some other code path even with turbo that uncovers the same problem.

A guess: The problem is related to the fact that when eager parsing an arrow function in DoParseFunction (*), the non-simple parameter handling is fundamentally different from when the arrow function was parsed the first time. Maybe that creates some inconsistency which then bites us during deopt time.

(*) This happens during deoptimization when --no-turbo


Comment 4 by caitp@chromium.org, Jun 7 2017

Cc: caitp@chromium.org
(so I can see the reproduction and spend some time on this)

Comment 5 by caitp@chromium.org, Jun 7 2017

I've discussed this with Marja.

I think the best solution we have for this right now is to always re-parse arrow functions before they're run. The AST produced the first time around is unreliable, and
it seems very tricky to make it reliable.

`({ x } = { x: 1 })` may or may not be a destructuring assignment, it's unknown until `=>` is seen. However, `({ x } = { y } = { x: 1, y: 2 })` is always at least 1 destructuring assignment, possibly 2, depending on if the `=>` token is seen after. There is a scheme in the parser to remove queued up destructuring assignments (there is a queue of rewritable expressions which are lazily turned into proper AST nodes depending on what they turn out to need to do, and in some cases, the ones queued up for arrow functions are removed from the queue to avoid a crash). This strategy is not sound, because the destructuring assignments which need to be removed is not all-or-nothing, and needs to happen for non-lazy functions as well (as seen by this bug).

at any rate, the result of all of this is, the eagerly parsed arrow function has a different frame-size from the reparsed-for-OSR arrow function, because the reparsed version does not include a duplicate TEMPORARY local variable, while the eagerly parsed version does.

Long-term, we will fare a lot better with a backtracking parser that eliminates the need for the AST node rewriting. Short term, always reparsing is the simple fix, but I think there's a slightly more complicated (but less costly) fix, I'll give that a try.

Comment 6 by ca...@igalia.com, Jun 7 2017

Also, I believe this doesn't cause problems for TurboFan because when the arrow function is recompiled for OSR, it isn't re-parsed (at least since AstGraphBuilder is gone).

But, I think with lazily parsed arrow functions, a similar situation could happen with turbofan enabled. I don't know exactly how to write that regression test, but I'd be happy to add it to my CL to ensure that that case is fixed as well.

Comment 7 by ca...@igalia.com, Jun 8 2017

Cc: bmeu...@chromium.org
My vote is to WONTFIX this as it doesn't hurt turbofan (provided it turbofan never requires a re-parsed AST/scope for optimization), and rolling out crankshaft seems to already be in progress.

Benedikt, how important is it to fix --no-turbo for these corner cases that most likely don't occur on the web anywhere at this point?

The fixes I proposed don't quite work. To fix the remaining problems, the parameter destructuring in PatternRewriter would need more information to be able to rewrite destructuring assignments within its binding pattern, or queue up those destructuring assignments for later rewriting. Specifically, it would lack the correct scope to evaluate the assignment parts within (not the scope passed to PatternRewriter), as far as I can tell. To fix this, RewritableExpression could have an associated scope member which would provide this information, but I think this complicates other things.

It's fixable, I'm just not sure it's worth it, when instead a focus can be on removing CS or implementing backtracking to eliminate all of these complicated interactions between different AST-rewriting systems.

Comment 8 by marja@chromium.org, Jun 8 2017

Thanks for investigating, Caitlin.

Afaics, with I + TF we're never in a situation where we eager-parse a previously eager-parsed function and do OSR. (Can somebody confirm?)

We do reparse previously parsed functions since we sometimes throw away the byte code (not sure when it happens exactly, just observed it in the tests). But when doing that reparsing, we're not in the middle of executing that function.

In the CL you said it maybe can happen for lazy funcs too, but I don't suppose so, since for them we already need to eager parse before executing and the frame size should come from that eager parse.
Cc: mstarzinger@chromium.org
Michi is clearly the expert here.
Project Member

Comment 10 by ClusterFuzz, Jun 10 2017

ClusterFuzz has detected this issue as fixed in range 478310:478323.

Detailed report: https://clusterfuzz.com/testcase?key=5625401752944640

Fuzzer: inferno_js_fuzzer
Job Type: linux_ubsan_vptr_d8
Platform Id: linux

Crash Type: CHECK failure
Crash Address: 
Crash State:
  fixed_size_above_fp + (stack_slots * kPointerSize) - CommonFrameConstants::kFixe
  
Sanitizer: undefined (UBSAN)

Regressed: https://clusterfuzz.com/revisions?job=linux_ubsan_vptr_d8&range=462021:462035
Fixed: https://clusterfuzz.com/revisions?job=linux_ubsan_vptr_d8&range=478310:478323

Reproducer Testcase: https://clusterfuzz.com/download?testcase_id=5625401752944640


See https://dev.chromium.org/Home/chromium-security/bugs/reproducing-clusterfuzz-bugs for more information.

If you suspect that the result above is incorrect, try re-doing that job on the test case report page.
Project Member

Comment 11 by ClusterFuzz, Jun 10 2017

Labels: ClusterFuzz-Verified
Status: Verified (was: Assigned)
ClusterFuzz testcase 5625401752944640 is verified as fixed, so closing issue.

If this is incorrect, please add ClusterFuzz-Wrong label and re-open the issue.
Status: Assigned (was: Verified)
Keeping this open; the Crankshaft-removing commit seems to have "fixed" this, but really, it's still a problem.

Comment 13 by ca...@igalia.com, Oct 2 2017

I don't think this is properly fixed without supporting re-parsing these cover grammars. Without that, it's very likely for the built scope info to be incorrect in some way, and attempts to fix it by moving stuff around in the scopes seems to show this in some cases.

But, as far as this particular bug is concerned, I think this should be counted as fixed, with a new bug opened for fine-tuning the parsing issue. I'm only commenting on this because it's still open, and I'm going through my open issues.

Marja, wdyt?
Owner: adamk@chromium.org
Agreed that this is not properly fixed. But let's reuse this bug for properly fixing it - I'm re-assigning this to Adam (who's the most likely person to work on fixing it).
Components: -Blink>JavaScript Blink>JavaScript>Parser
I'm ok with using this for tracking purposes, but perhaps it should be retitled? Marja, can you choose a title that you think matches the specific issue here?

Comment 16 by adamk@chromium.org, Dec 15 2017

Cc: -bmeu...@chromium.org -mstarzinger@chromium.org
Labels: -OS-Linux -Pri-1 Pri-3
Summary: Scoping problems in arrow functions with destructured parameters (was: CHECK failure: fixed_size_above_fp + (stack_slots * kPointerSize) - CommonFrameConstants::kFixe)
Cc: leszeks@chromium.org
Owner: verwa...@chromium.org
Revisiting this, I doubt it's something I'd fix anytime soon. Passing over to verwaest, in case his fresh eyes see something easy. I recommend talking to marja@ in person to get an overview of this bug, it's rather tricky to derive the root problem from reading the thread.

Sign in to add a comment