WebKit Bugzilla
Attachment 371184 Details for
Bug 198477
: [JSC] JSObject::attemptToInterceptPutByIndexOnHole should use getPrototype instead of getPrototypeDirect
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-198477-20190603025939.patch (text/plain), 11.54 KB, created by
Yusuke Suzuki
on 2019-06-03 02:59:42 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2019-06-03 02:59:42 PDT
Size:
11.54 KB
patch
obsolete
>Subversion Revision: 246024 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 25a5e395b767924300436dbec9e1fea6732c4a28..9c65668d0f2c3a37d2b63f86ffdf77b3fc402ab6 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,22 @@ >+2019-06-03 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] JSObject::attemptToInterceptPutByIndexOnHole should use getPrototype instead of getPrototypeDirect >+ https://bugs.webkit.org/show_bug.cgi?id=198477 >+ <rdar://problem/51299504> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ JSObject::attemptToInterceptPutByIndexOnHole uses getPrototypeDirect, but it should use getPrototype to >+ handle getPrototype methods in derived JSObject classes correctly. >+ >+ * runtime/JSArrayInlines.h: >+ (JSC::JSArray::pushInline): >+ * runtime/JSObject.cpp: >+ (JSC::JSObject::putByIndex): >+ (JSC::JSObject::attemptToInterceptPutByIndexOnHoleForPrototype): >+ (JSC::JSObject::attemptToInterceptPutByIndexOnHole): >+ (JSC::JSObject::putByIndexBeyondVectorLength): >+ > 2019-06-02 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Crash explicitly if StructureIDs are exhausted >diff --git a/Source/JavaScriptCore/runtime/JSArrayInlines.h b/Source/JavaScriptCore/runtime/JSArrayInlines.h >index af718dc2ff5894a68a4a659cc666484f819c39de..dbe1a4ea4d10027384e2847467cab99c74635a24 100644 >--- a/Source/JavaScriptCore/runtime/JSArrayInlines.h >+++ b/Source/JavaScriptCore/runtime/JSArrayInlines.h >@@ -212,8 +212,10 @@ ALWAYS_INLINE void JSArray::pushInline(ExecState* exec, JSValue value) > case ArrayWithSlowPutArrayStorage: { > unsigned oldLength = length(); > bool putResult = false; >- if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) { >- if (!scope.exception() && oldLength < 0xFFFFFFFFu) { >+ bool result = attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult); >+ RETURN_IF_EXCEPTION(scope, void()); >+ if (result) { >+ if (oldLength < 0xFFFFFFFFu) { > scope.release(); > setLength(exec, oldLength + 1, true); > } >diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp >index a0c0b20291eddf23e525b1deeaee38ac8a58ee61..1cb7ee0e09e4b9cb0487d75cb93bd94ea55e210a 100644 >--- a/Source/JavaScriptCore/runtime/JSObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSObject.cpp >@@ -943,18 +943,24 @@ bool JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, > > WriteBarrier<Unknown>& valueSlot = storage->m_vector[propertyName]; > unsigned length = storage->length(); >+ >+ auto scope = DECLARE_THROW_SCOPE(vm); > > // Update length & m_numValuesInVector as necessary. > if (propertyName >= length) { > bool putResult = false; >- if (thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow, putResult)) >+ bool result = thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow, putResult); >+ RETURN_IF_EXCEPTION(scope, false); >+ if (result) > return putResult; > length = propertyName + 1; > storage->setLength(length); > ++storage->m_numValuesInVector; > } else if (!valueSlot) { > bool putResult = false; >- if (thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow, putResult)) >+ bool result = thisObject->attemptToInterceptPutByIndexOnHole(exec, propertyName, value, shouldThrow, putResult); >+ RETURN_IF_EXCEPTION(scope, false); >+ if (result) > return putResult; > ++storage->m_numValuesInVector; > } >@@ -2716,6 +2722,8 @@ void JSObject::deallocateSparseIndexMap() > bool JSObject::attemptToInterceptPutByIndexOnHoleForPrototype(ExecState* exec, JSValue thisValue, unsigned i, JSValue value, bool shouldThrow, bool& putResult) > { > VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ > for (JSObject* current = this; ;) { > // This has the same behavior with respect to prototypes as JSObject::put(). It only > // allows a prototype to intercept a put if (a) the prototype declares the property >@@ -2726,18 +2734,21 @@ bool JSObject::attemptToInterceptPutByIndexOnHoleForPrototype(ExecState* exec, J > if (storage && storage->m_sparseMap) { > SparseArrayValueMap::iterator iter = storage->m_sparseMap->find(i); > if (iter != storage->m_sparseMap->notFound() && (iter->value.attributes() & (PropertyAttribute::Accessor | PropertyAttribute::ReadOnly))) { >+ scope.release(); > putResult = iter->value.put(exec, thisValue, storage->m_sparseMap.get(), value, shouldThrow); > return true; > } > } > > if (current->type() == ProxyObjectType) { >+ scope.release(); > ProxyObject* proxy = jsCast<ProxyObject*>(current); > putResult = proxy->putByIndexCommon(exec, thisValue, i, value, shouldThrow); > return true; > } > >- JSValue prototypeValue = current->getPrototypeDirect(vm); >+ JSValue prototypeValue = current->getPrototype(vm, exec); >+ RETURN_IF_EXCEPTION(scope, false); > if (prototypeValue.isNull()) > return false; > >@@ -2747,11 +2758,15 @@ bool JSObject::attemptToInterceptPutByIndexOnHoleForPrototype(ExecState* exec, J > > bool JSObject::attemptToInterceptPutByIndexOnHole(ExecState* exec, unsigned i, JSValue value, bool shouldThrow, bool& putResult) > { >- JSValue prototypeValue = getPrototypeDirect(exec->vm()); >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSValue prototypeValue = getPrototype(vm, exec); >+ RETURN_IF_EXCEPTION(scope, false); > if (prototypeValue.isNull()) > return false; > >- return asObject(prototypeValue)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, this, i, value, shouldThrow, putResult); >+ RELEASE_AND_RETURN(scope, asObject(prototypeValue)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, this, i, value, shouldThrow, putResult)); > } > > template<IndexingType indexingShape> >@@ -2937,10 +2952,16 @@ bool JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue > case NonArrayWithSlowPutArrayStorage: > case ArrayWithSlowPutArrayStorage: { > // No own property present in the vector, but there might be in the sparse map! >+ auto scope = DECLARE_THROW_SCOPE(vm); > SparseArrayValueMap* map = arrayStorage()->m_sparseMap.get(); > bool putResult = false; >- if (!(map && map->contains(i)) && attemptToInterceptPutByIndexOnHole(exec, i, value, shouldThrow, putResult)) >- return putResult; >+ if (!(map && map->contains(i))) { >+ bool result = attemptToInterceptPutByIndexOnHole(exec, i, value, shouldThrow, putResult); >+ RETURN_IF_EXCEPTION(scope, false); >+ if (result) >+ return putResult; >+ } >+ scope.release(); > FALLTHROUGH; > } > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 37571481a2c8831e1c5569019d635d7cfd1b3285..72c9221a1421c89ac987510428b70f3cb8c51078 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,17 @@ >+2019-06-03 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] JSObject::attemptToInterceptPutByIndexOnHole should use getPrototype instead of getPrototypeDirect >+ https://bugs.webkit.org/show_bug.cgi?id=198477 >+ <rdar://problem/51299504> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Ensure that JSWindow::getPrototype is used. >+ >+ * http/tests/security/cross-frame-access-object-getPrototypeOf-in-put-expected.txt: Added. >+ * http/tests/security/cross-frame-access-object-getPrototypeOf-in-put.html: Added. >+ * http/tests/security/resources/cross-frame-iframe-for-object-getPrototypeOf-in-put-test.html: Added. >+ > 2019-06-01 Simon Fraser <simon.fraser@apple.com> > > [Async overflow scroll] Flashing content when scrolling async overflow with a negative z-index child >diff --git a/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put-expected.txt b/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..6d5bca1cf3a32e28caac02b3a5f7cfc180354acb >--- /dev/null >+++ b/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put-expected.txt >@@ -0,0 +1,6 @@ >+This tests that you can't get the prototype of the window during [[Put]] operation. >+ >+PASS: successfullyParsed should be 'true' and is. >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put.html b/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1dfe135460d2bf6c9b67a2e1373a40e3b1c76353 >--- /dev/null >+++ b/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-in-put.html >@@ -0,0 +1,42 @@ >+<html> >+<head> >+ <script src="/js-test-resources/js-test-pre.js"></script> >+ <script src="resources/cross-frame-access.js"></script> >+ <script> >+ jsTestIsAsync = true; >+ >+ // Set up listener for message from iframe >+ addEventListener('message', function(event) { >+ if (event.data == "finishedLoad") >+ doTest(); >+ }, false); >+ >+ >+ doTest = function() >+ { >+ targetWindow = document.getElementById("target").contentWindow; >+ var array = []; >+ array.__proto__.__proto__ = targetWindow; >+ array[0] = 11.11; >+ array[2] = 22.22; >+ array[10101010] = { >+ toString() { >+ testFailed("toString is called by 10101010 setter"); >+ } >+ }; >+ array["cocoa"] = { >+ toString() { >+ testFailed("toString is called by cocoa setter"); >+ } >+ }; >+ finishJSTest(); >+ } >+ </script> >+</head> >+<body> >+ <div>This tests that you can't get the prototype of the window during [[Put]] operation.</div> >+ <iframe id="target" src="http://localhost:8000/security/resources/cross-frame-iframe-for-object-getPrototypeOf-in-put-test.html"></iframe> >+ <pre id="console"></pre> >+ <script src="/js-test-resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-getPrototypeOf-in-put-test.html b/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-getPrototypeOf-in-put-test.html >new file mode 100644 >index 0000000000000000000000000000000000000000..1d6f8217d22083f80dcc2f8cacfbc156215a2b35 >--- /dev/null >+++ b/LayoutTests/http/tests/security/resources/cross-frame-iframe-for-object-getPrototypeOf-in-put-test.html >@@ -0,0 +1,23 @@ >+<html> >+<head> >+ <script> >+ onload = function() >+ { >+ Object.defineProperty(Object.prototype, 10101010, { >+ set: function (v) { >+ return 'a' + v; >+ } >+ }); >+ Object.defineProperty(Object.prototype, "cocoa", { >+ set: function (v) { >+ return 'a' + v; >+ } >+ }); >+ parent.postMessage("finishedLoad", "*"); >+ } >+ </script> >+</head> >+<body> >+ Body >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 198477
: 371184