RESOLVED FIXED 128840
ASSERT(isValidAllocation(bytes)) when ObjC API creates custom errors
https://bugs.webkit.org/show_bug.cgi?id=128840
Summary ASSERT(isValidAllocation(bytes)) when ObjC API creates custom errors
Joseph Pecoraro
Reported 2014-02-14 13:46:55 PST
* TEST: JSContext *context = [[[JSContext alloc] init] autorelease]; [[JSValue valueWithInt32:42 inContext:context] toDictionary]; * ASSERT ASSERTION FAILED: isValidAllocation(bytes) /Volumes/Data/Code/safari/OpenSource/Source/JavaScriptCore/heap/Heap.h(467) : void *JSC::Heap::allocateWithoutDestructor(size_t) 1 0x10a94ce50 WTFCrash 2 0x10a1ce54b JSC::Heap::allocateWithoutDestructor(unsigned long) 3 0x10a4ea107 void* JSC::allocateCell<JSC::ErrorInstance>(JSC::Heap&, unsigned long) 4 0x10a4e986f void* JSC::allocateCell<JSC::ErrorInstance>(JSC::Heap&) 5 0x10a4e8ffb JSC::ErrorInstance::create(JSC::VM&, JSC::Structure*, WTF::String const&, WTF::Vector<JSC::StackFrame, 0ul, WTF::CrashOnOverflow>) 6 0x10a4e88f7 JSC::createTypeError(JSC::JSGlobalObject*, WTF::String const&) 7 0x10a4e8b35 JSC::createTypeError(JSC::ExecState*, WTF::String const&) 8 0x10a6d5af5 valueToDictionary(OpaqueJSContext*, OpaqueJSValue const*, OpaqueJSValue const**) 9 0x10a6d5921 -[JSValue toDictionary] 10 0x10a1b5f04 main 11 0x7fff8cbbf5f1 start Specifically, vm->identifierTable != wtfThreadData().currentIdentifierTable. My guess is that the ObjC API has to grab the APIEntryShim before it calls into JSC (via JSC::createTypeError). Most of the ObjC API uses the C API which already does this implicitly.
Attachments
Patch (2.67 KB, patch)
2014-02-14 14:09 PST, Mark Hahnenberg
joepeck: review+
Joseph Pecoraro
Comment 1 2014-02-14 13:48:01 PST
There are a number of create calls throughout the ObjC API. They will all need to be audited: shell> ack 'create.*?Error' API/*.mm API/JSValue.mm 784: *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSArray")); 800: *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSDictionary")); API/ObjCCallbackFunction.mm 132: *exception = toRef(JSC::createTypeError(toJS(contextRef), "Argument does not match Objective-C Class")); 456: // (2) We're calling some JSC internals that require us to be on the 'inside' - e.g. createTypeError. 499: *exception = toRef(JSC::createTypeError(toJS(contextRef), "Objective-C blocks called as constructors must return an object.")); 565: *exception = toRef(JSC::createTypeError(toJS(contextRef), "self type check failed for Objective-C instance method")); 575: *exception = toRef(JSC::createTypeError(toJS(contextRef), "self type check failed for Objective-C instance method"));
Geoffrey Garen
Comment 2 2014-02-14 14:06:19 PST
> My guess is that the ObjC API has to grab the APIEntryShim before it calls into JSC (via JSC::createTypeError). Right.
Mark Hahnenberg
Comment 3 2014-02-14 14:09:12 PST
Mark Hahnenberg
Comment 4 2014-02-14 14:09:52 PST
(In reply to comment #1) > There are a number of create calls throughout the ObjC API. They will all need to be audited: > > shell> ack 'create.*?Error' API/*.mm > API/JSValue.mm > 784: *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSArray")); > 800: *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSDictionary")); > > API/ObjCCallbackFunction.mm > 132: *exception = toRef(JSC::createTypeError(toJS(contextRef), "Argument does not match Objective-C Class")); > 456: // (2) We're calling some JSC internals that require us to be on the 'inside' - e.g. createTypeError. > 499: *exception = toRef(JSC::createTypeError(toJS(contextRef), "Objective-C blocks called as constructors must return an object.")); > 565: *exception = toRef(JSC::createTypeError(toJS(contextRef), "self type check failed for Objective-C instance method")); > 575: *exception = toRef(JSC::createTypeError(toJS(contextRef), "self type check failed for Objective-C instance method")); I audited the other call sites and other than these two they are all in places where we already hold the API lock.
Joseph Pecoraro
Comment 5 2014-02-14 14:23:44 PST
Comment on attachment 224250 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=224250&action=review r=me > Source/JavaScriptCore/API/JSValue.mm:785 > *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSArray")); Nit: You could ASCIILiteral(...) the string being passed to createTypeError, since it is a string literal turning into a WTF::String. Is the lock needed by the "tryUnwrapObjcObject" call at the top of these functions? Otherwise this is identical to the local fix I had.
Mark Hahnenberg
Comment 6 2014-02-14 14:28:18 PST
(In reply to comment #5) > (From update of attachment 224250 [details]) > View in context: https://bugs.webkit.org/attachment.cgi?id=224250&action=review > > r=me > > > Source/JavaScriptCore/API/JSValue.mm:785 > > *exception = toRef(JSC::createTypeError(toJS(context), "Cannot convert primitive to NSArray")); > > Nit: You could ASCIILiteral(...) the string being passed to createTypeError, since it is a string literal turning into a WTF::String. > Will do. > Is the lock needed by the "tryUnwrapObjcObject" call at the top of these functions? > I don't think so. We don't create any objects in it, and the object is always reachable from the stack. If I missed something and we do need to take the shim for things that happen inside tryUnwrapObjcObject then the shim should probably go in there instead of out here.
Mark Hahnenberg
Comment 7 2014-02-14 14:39:49 PST
Note You need to log in before you can comment on or make changes to this bug.