RESOLVED FIXED 23085
[jsfunfuzz] Over released ScopeChainNode
https://bugs.webkit.org/show_bug.cgi?id=23085
Summary [jsfunfuzz] Over released ScopeChainNode
Oliver Hunt
Reported 2009-01-02 21:26:50 PST
(function(){ try{ with({}) throw this(function(){}) } catch(x) { } })() gc()
Attachments
Remove use of ScopeChain for the scope chain unwinding (4.27 KB, patch)
2009-01-06 12:25 PST, Oliver Hunt
zwarich: review+
Oliver Hunt
Comment 1 2009-01-02 23:27:16 PST
erk, it turns out this test case doesn't reproduce with all of jsfunfuzz included before it, however i've found another reduction like thing that produces the same crash
Oliver Hunt
Comment 2 2009-01-02 23:41:51 PST
Okay, here we go: function tryRunning(f){ try{ f() }catch(r){ } } function tryItOut(){ function f() { try { throw ""; } catch(y) { this(function(){}) } finally { } }; v = tryRunning(f) } tryItOut(); gc();
Gavin Barraclough
Comment 3 2009-01-02 23:49:36 PST
function f() { try { throw ""; } catch(y) { this(function(){}) } finally { } }; try { f() } catch(r) { } gc();
Gavin Barraclough
Comment 4 2009-01-03 00:24:40 PST
^^ release builds only :-(
Gavin Barraclough
Comment 5 2009-01-03 00:24:46 PST
try{ (function() { try { throw ""; } catch(y) { throw (function(){}); } finally { } })() }catch(r){ } (function(){})() gc();
Oliver Hunt
Comment 6 2009-01-03 02:20:27 PST
The problem is that a scope node is being deleted prematurely, i believe the scope node being removed in the most recent reduction is the activation for the first function. I honestly can't work out how/why the ref counting scheme we use for scopechainnodes works, but i blame it for the badness.
Cameron Zwarich (cpst)
Comment 7 2009-01-03 02:26:39 PST
I'll take a look at this. This one hurts.
Oliver Hunt
Comment 8 2009-01-05 15:18:41 PST
Oliver Hunt
Comment 9 2009-01-06 08:54:42 PST
Okay, so the issue is that the finally block is derefing the activation incorrectly
Oliver Hunt
Comment 10 2009-01-06 10:05:11 PST
Scope chain unwinding creates a ScopeChain to wrap the ScopeChainNode, when the ScopeChain is destroyed it does a full deref of the top node, but it has not necessarily ref'd that node. Basically this is the path to badness * Scope chain is represented as {scope object, ref count} -> next scopechainnode * ScopeChainNode* scopeChain = {someScope, 1}->{activation, 1}->not relevant * ScopeChain sc(scopeChain) => {someScope, 2}->{activation, 1}->not relevant * sc.pop() => {activation, 1}->not relevant * sc.~ScopeChain => {activation, 0}->not relevant So we end up leaking the top of stack, and over releasing whateer is the ToS at the end
Oliver Hunt
Comment 11 2009-01-06 10:08:09 PST
Ah, whooops, not actually correct, the problem is that ScopeChain refs() the origin ToS, and then derefs() the final ToS. but pop() and deref() have different behaviour -- deref() on a node that was not explicitly ref'd is basically wrong
Oliver Hunt
Comment 12 2009-01-06 12:25:48 PST
Created attachment 26465 [details] Remove use of ScopeChain for the scope chain unwinding Fixeration
Cameron Zwarich (cpst)
Comment 13 2009-01-06 12:28:03 PST
Comment on attachment 26465 [details] Remove use of ScopeChain for the scope chain unwinding r=me
Oliver Hunt
Comment 14 2009-01-06 12:34:20 PST
Committing to http://svn.webkit.org/repository/webkit/trunk ... M JavaScriptCore/ChangeLog M JavaScriptCore/interpreter/Interpreter.cpp M LayoutTests/ChangeLog M LayoutTests/fast/js/exception-try-finally-scope-error-expected.txt M LayoutTests/fast/js/resources/exception-try-finally-scope-error.js Committed r39660
Note You need to log in before you can comment on or make changes to this bug.