RESOLVED FIXED 176317
typeCheckHoistingPhase may emit a CheckStructure on the empty value which leads to a dereference of zero on 64 bit platforms
https://bugs.webkit.org/show_bug.cgi?id=176317
Summary typeCheckHoistingPhase may emit a CheckStructure on the empty value which lea...
Saam Barati
Reported 2017-09-03 13:01:27 PDT
Instead, we should emit a new variant of CheckStructure that allows the empty value to flow through. That way, we don't crash, and we don't repeatedly exit.
Attachments
WIP (17.94 KB, patch)
2017-09-03 13:35 PDT, Saam Barati
no flags
WIP (17.76 KB, patch)
2017-09-03 13:49 PDT, Saam Barati
buildbot: commit-queue-
Archive of layout-test-results from ews105 for mac-elcapitan-wk2 (1.57 MB, application/zip)
2017-09-03 15:20 PDT, Build Bot
no flags
Archive of layout-test-results from ews121 for ios-simulator-wk2 (1.39 MB, application/zip)
2017-09-03 15:43 PDT, Build Bot
no flags
WIP (18.13 KB, patch)
2017-09-03 16:56 PDT, Saam Barati
no flags
patch (22.57 KB, patch)
2017-09-04 14:33 PDT, Saam Barati
keith_miller: review+
patch for landing (22.43 KB, patch)
2017-09-04 20:35 PDT, Saam Barati
no flags
Saam Barati
Comment 1 2017-09-03 13:35:22 PDT
Saam Barati
Comment 2 2017-09-03 13:49:20 PDT
Build Bot
Comment 3 2017-09-03 14:41:39 PDT
Comment on attachment 319801 [details] WIP Attachment 319801 [details] did not pass jsc-ews (mac): Output: http://webkit-queues.webkit.org/results/4443676 New failing tests: v8-v6/v8-earley-boyer.js.dfg-eager airjs-tests.yaml/stress-test.js.default v8-v6/v8-earley-boyer.js.ftl-eager-no-cjit-b3o1 stress/v8-earley-boyer-strict.js.ftl-eager stress/v8-earley-boyer-strict.js.ftl-eager-no-cjit airjs-tests.yaml/stress-test.js.no-ftl airjs-tests.yaml/stress-test.js.ftl-no-cjit stress/v8-earley-boyer-strict.js.ftl-eager-no-cjit-b3o1 v8-v6/v8-earley-boyer.js.dfg-eager-no-cjit-validate ChakraCore.yaml/ChakraCore/test/Lib/construct.js.default v8-v6/v8-earley-boyer.js.ftl-eager-no-cjit v8-v6/v8-earley-boyer.js.ftl-eager stress/v8-earley-boyer-strict.js.dfg-eager-no-cjit-validate stress/v8-earley-boyer-strict.js.dfg-eager
Build Bot
Comment 4 2017-09-03 15:20:52 PDT
Comment on attachment 319801 [details] WIP Attachment 319801 [details] did not pass mac-wk2-ews (mac-wk2): Output: http://webkit-queues.webkit.org/results/4443783 New failing tests: imported/w3c/web-platform-tests/html/dom/reflection-embedded.html
Build Bot
Comment 5 2017-09-03 15:20:53 PDT
Created attachment 319808 [details] Archive of layout-test-results from ews105 for mac-elcapitan-wk2 The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews. Bot: ews105 Port: mac-elcapitan-wk2 Platform: Mac OS X 10.11.6
Build Bot
Comment 6 2017-09-03 15:43:35 PDT
Comment on attachment 319801 [details] WIP Attachment 319801 [details] did not pass ios-sim-ews (ios-simulator-wk2): Output: http://webkit-queues.webkit.org/results/4443810 New failing tests: imported/w3c/web-platform-tests/html/dom/reflection-embedded.html
Build Bot
Comment 7 2017-09-03 15:43:37 PDT
Created attachment 319813 [details] Archive of layout-test-results from ews121 for ios-simulator-wk2 The attached test failures were seen while running run-webkit-tests on the ios-sim-ews. Bot: ews121 Port: ios-simulator-wk2 Platform: Mac OS X 10.12.5
Saam Barati
Comment 8 2017-09-03 16:56:49 PDT
Saam Barati
Comment 9 2017-09-04 14:33:45 PDT
Keith Miller
Comment 10 2017-09-04 20:13:20 PDT
Comment on attachment 319861 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=319861&action=review r=me with some comments. > Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:2370 > + // We rely on constant folding to CheckStructure to do the heavy lifting Typo: "We rely on constant folding to CheckStructure" => "We rely on (the?) constant folding of CheckStructure" Also, what's the reason to not do the conversion to CheckStructure here?
Saam Barati
Comment 11 2017-09-04 20:29:23 PDT
Comment on attachment 319861 [details] patch View in context: https://bugs.webkit.org/attachment.cgi?id=319861&action=review >> Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:2370 >> + // We rely on constant folding to CheckStructure to do the heavy lifting > > Typo: "We rely on constant folding to CheckStructure" => "We rely on (the?) constant folding of CheckStructure" > > Also, what's the reason to not do the conversion to CheckStructure here? Because AI is ran outside of constant folding.
Saam Barati
Comment 12 2017-09-04 20:35:15 PDT
Created attachment 319870 [details] patch for landing
WebKit Commit Bot
Comment 13 2017-09-04 21:10:56 PDT
Comment on attachment 319870 [details] patch for landing Clearing flags on attachment: 319870 Committed r221607: <http://trac.webkit.org/changeset/221607>
WebKit Commit Bot
Comment 14 2017-09-04 21:10:58 PDT
All reviewed patches have been landed. Closing bug.
Geoffrey Garen
Comment 15 2017-09-05 09:23:35 PDT
Comment on attachment 319870 [details] patch for landing This feels sketchy to me. JSValue() is not a value that we should encounter during normal execution. Usually JSValue() means that you've read garbage memory that isn't always guaranteed to be JSValue(). For this reason, most of JSC is not JSValue()-safe. There have been exceptions to this general rule in the past. For example, the lazy arguments object, which no longer exists, used a strategy of treating JSValue() as a special marker value. Still, even that behavior never read JSValue() into normal program control flow. TDZ is another exception. We use JSValue() to demarcate a TDZ read. But what causes the TDZ value to enter normal program control flow? I don't think that behavior is correct, and I think it might break lots of stuff. Instead, I think TDZ needs to throw immediately upon being read.
Saam Barati
Comment 16 2017-09-05 11:39:02 PDT
(In reply to Geoffrey Garen from comment #15) > Comment on attachment 319870 [details] > patch for landing > > This feels sketchy to me. > > JSValue() is not a value that we should encounter during normal execution. > Usually JSValue() means that you've read garbage memory that isn't always > guaranteed to be JSValue(). For this reason, most of JSC is not > JSValue()-safe. I don't agree with this assertion. I've never taken reading JSValue() to mean the program likely read garbage memory. We use this in places where it'd be wrong if the value weren't JSValue() under certain circumstances. > > There have been exceptions to this general rule in the past. For example, > the lazy arguments object, which no longer exists, used a strategy of > treating JSValue() as a special marker value. Still, even that behavior > never read JSValue() into normal program control flow. > > TDZ is another exception. We use JSValue() to demarcate a TDZ read. But what > causes the TDZ value to enter normal program control flow? I don't think > that behavior is correct, and I think it might break lots of stuff. Instead, > I think TDZ needs to throw immediately upon being read. Because the TDZ marker is JSValue(), I don't see how we can guarantee that it can't be part of the normal program control flow. I think things become cleaner once we are OK with this. For example, bytecode locals may be JSValue() because they're TDZ. We can't emit a TDZ check before we do any mov of a bytecode local. I agree that almost all of our bytecode operations would crash if TDZ flowed into them. It's the bytecode generator's job to ensure that this doesn't happen. It already does this by emitting TDZ checks. The DFG must respect this property of bytecode. Many DFG nodes would also crash if JSValue() flowed into them. However, the way we emit bytecode ensures that only a handful of DFG nodes will see JSValue(). It would be wrong for the DFG to do code motion in such a way that it moves code around or inserts code that may see the empty value but can't handle it. This is what the type check hoisting phase was doing. It was doing code motion by hoisting structure checks to right before a SetLocal. Conservatively, we must assume any given local can be JSValue() (AI and other analyses can prove something stronger as needed). From this perspective, this is the DFG's error. It hoisted code to a place that saw the empty value but couldn't handle it. For similar reasons, I didn't change other CheckStructure's that we emit elsewhere to be CheckStructureOrEmpty, such as in bytecode parser or fixup phase. We emit those CheckStructures in such a way that they're guaranteed to see the empty value.
Radar WebKit Bug Importer
Comment 17 2017-09-05 12:03:15 PDT
Note You need to log in before you can comment on or make changes to this bug.