Ignore:
Timestamp:
May 28, 2010, 11:16:25 PM (15 years ago)
Author:
[email protected]
Message:

2010-05-28 Jedrzej Nowacki <[email protected]>

Reviewed by Geoffrey Garen.

Fix the JSObjectSetPrototype function.

A cycle in a prototype chain can cause an application hang or
even crash.
A check for a prototype chain cycles was added to
the JSObjectSetPrototype.

JSObjectSetPrototype doesn't check for cycle in prototype chain.
https://bugs.webkit.org/show_bug.cgi?id=39360

  • API/JSObjectRef.cpp: (JSObjectSetPrototype):
  • API/tests/testapi.c: (assertTrue): (checkForCycleInPrototypeChain): (main):
  • runtime/JSObject.cpp: (JSC::JSObject::put):
  • runtime/JSObject.h: (JSC::JSObject::setPrototypeWithCycleCheck):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/API/tests/testapi.c

    r56318 r60390  
    765765}
    766766
     767static bool assertTrue(bool value, const char* message)
     768{
     769    if (!value) {
     770        if (message)
     771            fprintf(stderr, "assertTrue failed: '%s'\n", message);
     772        else
     773            fprintf(stderr, "assertTrue failed.\n");
     774        failed = 1;
     775    }
     776    return value;
     777}
     778
     779static bool checkForCycleInPrototypeChain()
     780{
     781    bool result = true;
     782    JSGlobalContextRef context = JSGlobalContextCreate(0);
     783    JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
     784    JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
     785    JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
     786
     787    JSObjectSetPrototype(context, object1, JSValueMakeNull(context));
     788    ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1)));
     789
     790    // object1 -> object1
     791    JSObjectSetPrototype(context, object1, object1);
     792    result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype");
     793
     794    // object1 -> object2 -> object1
     795    JSObjectSetPrototype(context, object2, object1);
     796    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1));
     797    JSObjectSetPrototype(context, object1, object2);
     798    result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle");
     799
     800    // object1 -> object2 -> object3 -> object1
     801    JSObjectSetPrototype(context, object2, object3);
     802    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3));
     803    JSObjectSetPrototype(context, object1, object2);
     804    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2));
     805    JSObjectSetPrototype(context, object3, object1);
     806    result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle");
     807
     808    JSValueRef exception;
     809    JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
     810    JSStringRef file = JSStringCreateWithUTF8CString("");
     811    result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception)
     812                         , "An exception should be thrown");
     813
     814    JSStringRelease(code);
     815    JSStringRelease(file);
     816    JSGlobalContextRelease(context);
     817    return result;
     818}
     819
    767820int main(int argc, char* argv[])
    768821{
     
    13471400    printf("PASS: Infinite prototype chain does not occur.\n");
    13481401
     1402    if (checkForCycleInPrototypeChain())
     1403        printf("PASS: A cycle in a prototype chain can't be created.\n");
     1404    else {
     1405        printf("FAIL: A cycle in a prototype chain can be created.\n");
     1406        failed = true;
     1407    }
     1408
    13491409    if (failed) {
    13501410        printf("FAIL: Some tests failed.\n");
Note: See TracChangeset for help on using the changeset viewer.