chakra-core / ChakraCore

ChakraCore is an open source Javascript engine with a C API.
MIT License
9.13k stars 1.2k forks source link

Assertion failure in OutputPropertyValue<T>::impl #6539

Open sunlili opened 3 years ago

sunlili commented 3 years ago

Hello, executing following code in ch 1.11.24(debug), an assertion will be thrown.

'use strict';
function func(arr) {
    var a = new Promise(function() {});
    arr.__proto__.__proto__ = a;
}

for (var i = 0; i < 2; i++) {
    var arr = [
    ,
    {}
    ];
    Object.prototype.toString.call(Array());
    func(arr);
}

output:

ASSERTION 14228: (c:\users\sunlili\documents\workspace\jsenginesfordebug\chakracore-1.11.24\lib\runtime\language\inlinecache.h, line 471) *propertyValue == slowPathValue || (RootObjectBase::Is(propertyObject) && *propertyValue == rootObjectValue) || (slowPathValue == requestContext->GetLibrary()->GetNull() && requestContext->GetThreadContext()->IsDisableImplicitCall() && propertyObject->GetType()->IsExternal())
 Failure: (*propertyValue == slowPathValue || (RootObjectBase::Is(propertyObject) && *propertyValue == rootObjectValue) || (slowPathValue == requestContext->GetLibrary()->GetNull() && requestContext->GetThreadContext()->IsDisableImplicitCall() && propertyObject->GetType()->IsExternal()))
FATAL ERROR: ch.exe failed due to exception code c0000420
tmp

The assertion is triggered when the second time executing Object.prototype.toString.call(Array()). According to [http://www.ecma-international.org/ecma-262/#sec-object.prototype.tostring], toString should get @@toStringTag. https://github.com/microsoft/ChakraCore/blob/7d4bdd821d452d6b91a21936257d7e352ea7dc4b/lib/Runtime/Library/JavascriptObject.cpp#L444-L445 Since Array does not contain @@toStringTag, undefined is fetched for the first time, and the value is stored in inline cache. After calling func(arr), Array contains @@toStringTag, which is inherited by the Promise object. However, the value in inline cache is not invalid. When Object.prototype.toString.call(Array()) is executed again, the assertion is triggered and the old value undefined is fetched.

ISec Lab. 2020.12.16

rhuanjl commented 3 years ago

This is slightly different in master but the assert still triggers.

AND we get [Object Array] printed twice when it should be [Object Array] the first time and [Object Promise] the second. The inline cache should be being invalidated and it isn't this is a slightly concerning bug.