Closed Bug 604196 Opened 14 years ago Closed 14 years ago

jsval return types in xpidl are broken (non-quickstubs)

Categories

(Core :: XPConnect, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
Tracking Status
blocking2.0 --- betaN+

People

(Reporter: vlad, Assigned: vlad)

References

Details

Attachments

(2 files)

Using a jsval return type in xpidl causes crashynessin XPCConvert::NativeData2JS, because the dereference is **((jsval**)s). Luke tells me this is correct, and that the bug lies in http://mxr.mozilla.org/mozilla-central/source/js/src/xpconnect/src/xpcwrappedjsclass.cpp#1545
To be a bit more specific, its a disconnect between the code linked by comment 0 and the T_JSVAL case in NativeData2JS. This already happened once in JSData2Native (bug 589329 comment 7) and we chose to fix it by having the T_JSVAL case use either one or two levels of indirection: http://mxr.mozilla.org/mozilla-central/source/js/src/xpconnect/src/xpcconvert.cpp#630 However, here there is no analogous parameter, so we can fix it in the caller by not stripping the indirection for in/out params that are also jsvals. We could even go back and fix JSData2Native in the same way which seems more consistent.
I'm lost in the above explanation, tbh; I tried the suggested fix on irc at xpcwrappedjsclass.cpp:1545, but it didn't work; reading the code, this is inside an in-param block. The jsval in question here is a pure out param, so we'll never go through this path. This is also inside nsXPCWrappedJSClass, which seems like it's the wrong direction -- I'm making a call from JS to a C++ component, so there's no wrapped JS class.
Blocks: 539771
blocking2.0: --- → betaN+
Sorry, didn't pay attention to the cause, just looked for the same cause as before. comment 1 may actually be a bug though...
Attached patch patch that can reproduce this (deleted) — Splinter Review
This work-in-progress patch can reproduce this bug -- note that it has the workaround that changes **((jsval**)s) -> *((jsval*)s), which seems to work. Remove the workaround to see the original bug, which you can reproduce by opening mozilla-central/content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html . The function in question is getContextAttributes, on CanvasRenderingContextWebGL.
Assigning this to Luke, let me know if that's not correct...
Assignee: nobody → lw
Here's my understanding of what happens with jsval, in sort of pseudocode, gleaned from xpc code, looking at xpcwrappednative only: ConvertIndependentParams converts the incoming params for making a native call. The jsval bits look roughly like this: useAllocator = false; if (isout) { dp->SetPtrIsData(); if (is_jsval) { if (is_retval) { dp->ptr = mCallContext.GetRetVal(); } else { dp->ptr = (jsval*) &dp->val.u64 call dp->SetValIsJSRoot() } } if (!isin) continue; } else { if (is_jsval) { dp->SetValIsallocated(); useAllocator = true; } } // actually call JSData2Native for in or inout params JSData2Native(&dp->val, src, type, useAllocator) in JSData2Native, the jsval case is: if useAllocator: *((jsval**)(&dp->val)) = new jsval(s) else: *((jsval*)(dp->val)) = s; From this I get a few things: - For in params, dp->val ends up holding a jsval* unconditionally; useAllocator is set to true, so JSData2Native will allocate a jsval. - For pure out params, dp->ptr will hold either the direct return jsval pointer, or will hold a pointer just reusing &dp->val.u64 space, and rooting it. - For return params, dp->val doesn't seem to be valid - For non-return params, dp->val is a jsval - For *in out* params, we'll treat dp->val as a jsval that we'll assign the incoming jsval to, and dp->ptr will be set correctly to its pointer Or, put another way: - retval: dp->ptr = jsval* dp->val = ignored/invalid - out/inout: dp->val = bare jsval (rooted) dp->ptr = &dp->val - in: dp->val = jsval* dp->ptr = ignored/invalid The problems I think are on the other end; GatherAndConvertResults calls NativeData2JS (again, omitting anything but what we'd hit for T_JSVAL): if (!isout) continue; // make the call to convert, passing in only &dp->val NativeData2JS(&v, &dp->val, T_JSVAL); if (isretval) { if (!cc.return_value_was_set && type != T_JSVAL) { cc.SetRetVal(v); } } and in NativeData2JS, for T_JSVAL: NativeData2JS(d = &v, s = &dp->val, type) *d = **((jsval**)s); First - why do we even call NativeData2JS if the param is a retval? Isn't dp->val bogus in that case, presumably the direct value of dp->ptr was passed to the call (because SetPtrIsData)? I don't see where it was set to anything valid on the incoming side of things. Second - For retval out params, dp->val is a bare jsval, and NativeData2JS gets &dp->val as the 's' arg. So, having it do |d = **((jsval**)s)| is incorrect -- s is just a jsval*, and will always be just a jsval*, never a **. For it to be a jsval**, that would mean that dp->val would be a jsval*, which doesn't happen for the out param case.
Attached patch fix (deleted) — Splinter Review
Based on the above, I believe this patch is correct. I removed the assert because this code doesn't directly depend on sizeof(jsval) <= sizeof(uint64) -- the code that actually makes that assumption has the assert there.
Assignee: lw → vladimir
Attachment #488079 - Flags: review?(jorendorff)
(In reply to comment #6) > Or, put another way: > - retval: > dp->ptr = jsval* > dp->val = ignored/invalid > - out/inout: > dp->val = bare jsval (rooted) > dp->ptr = &dp->val > - in: > dp->val = jsval* > dp->ptr = ignored/invalid Great. Thanks! > First - why do we even call NativeData2JS if the param is a retval? Because it's simpler to call it than to have yet another special case where it doesn't get called. I'm opposed to adding another if statement to this code unless there's a really really good reason. That NativeData2JS call is one of the few things in here that I'm totally OK with. ;)
Comment on attachment 488079 [details] [diff] [review] fix Sorry for the slow review. I had to stare at a lot of code before this made sense to me.
Attachment #488079 - Flags: review?(jorendorff) → review+
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Depends on: 655878
This caused bug 604196
Er, I meant this caused bug 655878.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: