static JSBool DefineGetterOrSetter(JSContext *cx, uintN argc, JSBool wantGetter, jsval *vp) { uintN attrs; JSBool found; JSPropertyOp getter, setter; JSObject *obj2; jsval v; jsid interned_id; XPC_QS_ASSERT_CONTEXT_OK(cx); JSObject *obj = JS_THIS_OBJECT(cx, vp); if (!obj) return JS_FALSE; JSFastNative forward = wantGetter ? js_obj_defineGetter : js_obj_defineSetter; jsval id = (argc >= 1) ? JS_ARGV(cx, vp)[0] : JSVAL_VOID; if(!JSVAL_IS_STRING(id)) return forward(cx, argc, vp); JSString *str = JSVAL_TO_STRING(id); const char *name = JS_GetStringBytes(str); if(!JS_ValueToId(cx, id, &interned_id) || !JS_LookupPropertyWithFlagsById(cx, obj, interned_id, JSRESOLVE_QUALIFIED, &obj2, &v) || (obj2 && !JS_GetPropertyAttrsGetterAndSetterById(cx, obj2, interned_id, &attrs, &found, &getter, &setter))) return JS_FALSE; // The property didn't exist, already has a getter or setter, or is not // our property, then just forward now. if(!obj2 || (attrs & (JSPROP_GETTER | JSPROP_SETTER)) || !(getter || setter) || !IS_PROTO_CLASS(STOBJ_GET_CLASS(obj2))) return forward(cx, argc, vp); // Reify the getter and setter... if(!ReifyPropertyOps(cx, obj, id, interned_id, name, getter, setter, nsnull, nsnull)) return JS_FALSE; return forward(cx, argc, vp); }
static JSBool LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, uintN argc, jsval *vp) { XPC_QS_ASSERT_CONTEXT_OK(cx); if(argc == 0) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } JSObject *obj = JS_THIS_OBJECT(cx, vp); if(!obj) return JS_FALSE; jsval idval = JS_ARGV(cx, vp)[0]; jsid interned_id; JSPropertyDescriptor desc; if(!JS_ValueToId(cx, idval, &interned_id) || !JS_GetPropertyDescriptorById(cx, obj, interned_id, JSRESOLVE_QUALIFIED, &desc)) return JS_FALSE; // No property at all means no getters or setters possible. if(!desc.obj) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } // Inline obj_lookup[GS]etter here. if(wantGetter) { if(desc.attrs & JSPROP_GETTER) { JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter))); return JS_TRUE; } }
static JSBool LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, uintN argc, jsval *vp) { uintN attrs; JSBool found; JSPropertyOp getter, setter; JSObject *obj2; jsid interned_id; jsval v; XPC_QS_ASSERT_CONTEXT_OK(cx); if(argc == 0) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } JSObject *obj = JS_THIS_OBJECT(cx, vp); if (!obj) return JS_FALSE; jsval idval = JS_ARGV(cx, vp)[0]; const char *name = JSVAL_IS_STRING(idval) ? JS_GetStringBytes(JSVAL_TO_STRING(idval)) : nsnull; if(!JS_ValueToId(cx, idval, &interned_id) || !JS_LookupPropertyWithFlagsById(cx, obj, interned_id, JSRESOLVE_QUALIFIED, &obj2, &v) || (obj2 && !JS_GetPropertyAttrsGetterAndSetterById(cx, obj2, interned_id, &attrs, &found, &getter, &setter))) return JS_FALSE; // No property at all means no getters or setters possible. if(!obj2 || !found) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } // Inline obj_lookup[GS]etter here. if(wantGetter) { if(attrs & JSPROP_GETTER) { JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, getter))); return JS_TRUE; } } else { if(attrs & JSPROP_SETTER) { JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, setter))); return JS_TRUE; } } // Since XPConnect doesn't use JSPropertyOps in any other contexts, // ensuring that we have an XPConnect prototype object ensures that // we are only going to expose quickstubbed properties to script. // Also be careful not to overwrite existing properties! if(!name || !IS_PROTO_CLASS(STOBJ_GET_CLASS(obj2)) || (attrs & (JSPROP_GETTER | JSPROP_SETTER)) || !(getter || setter)) { JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } JSObject *getterobj, *setterobj; if(!ReifyPropertyOps(cx, obj, idval, interned_id, name, getter, setter, &getterobj, &setterobj)) return JS_FALSE; JSObject *wantedobj = wantGetter ? getterobj : setterobj; v = wantedobj ? OBJECT_TO_JSVAL(wantedobj) : JSVAL_VOID; JS_SET_RVAL(cx, vp, v); return JS_TRUE; }
static JSBool CVE_2012_0478_firefox4_0_1_nsIDOMWebGLRenderingContext_TexImage2D(JSContext *cx, uintN argc, jsval *vp) { XPC_QS_ASSERT_CONTEXT_OK(cx); JSObject *obj = JS_THIS_OBJECT(cx, vp); if (!obj) return JS_FALSE; nsresult rv; nsIDOMWebGLRenderingContext *self; xpc_qsSelfRef selfref; js::AutoValueRooter tvr(cx); if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.jsval_addr(), nsnull)) return JS_FALSE; if (argc < 6 || argc == 7 || argc == 8) return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); jsval *argv = JS_ARGV(cx, vp); // arguments common to all cases GET_UINT32_ARG(argv0, 0); GET_INT32_ARG(argv1, 1); if (argc > 5 && !JSVAL_IS_PRIMITIVE(argv[5])) { // implement the variants taking a DOMElement as argv[5] GET_UINT32_ARG(argv2, 2); GET_UINT32_ARG(argv3, 3); GET_UINT32_ARG(argv4, 4); nsIDOMElement *elt; xpc_qsSelfRef eltRef; rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[5], &elt, &eltRef.ptr, &argv[5]); if (NS_FAILED(rv)) return JS_FALSE; rv = self->TexImage2D_dom(argv0, argv1, argv2, argv3, argv4, elt); if (NS_FAILED(rv)) { // failed to interprete argv[5] as a DOMElement, now try to interprete it as ImageData JSObject *argv5 = JSVAL_TO_OBJECT(argv[5]); jsval js_width, js_height, js_data; JS_GetProperty(cx, argv5, "width", &js_width); JS_GetProperty(cx, argv5, "height", &js_height); JS_GetProperty(cx, argv5, "data", &js_data); if (js_width == JSVAL_VOID || js_height == JSVAL_VOID || js_data == JSVAL_VOID) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5); return JS_FALSE; } int32 int_width, int_height; JSObject *obj_data = JSVAL_TO_OBJECT(js_data); if (!JS_ValueToECMAInt32(cx, js_width, &int_width) || !JS_ValueToECMAInt32(cx, js_height, &int_height)) { return JS_FALSE; } if (!js_IsTypedArray(obj_data)) { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 5); return JS_FALSE; } rv = self->TexImage2D_imageData(argv0, argv1, argv2, int_width, int_height, 0, argv3, argv4, js::TypedArray::fromJSObject(obj_data)); } } else if (argc > 8 && JSVAL_IS_OBJECT(argv[8])) // here, we allow null ! { // implement the variants taking a buffer/array as argv[8] GET_UINT32_ARG(argv2, 2); GET_INT32_ARG(argv3, 3); GET_INT32_ARG(argv4, 4); GET_INT32_ARG(argv5, 5); GET_UINT32_ARG(argv6, 6); GET_UINT32_ARG(argv7, 7); JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]); // then try to grab either a js::ArrayBuffer, js::TypedArray, or null if (argv8 == nsnull) { rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3, argv4, argv5, argv6, argv7, nsnull); } else if (js_IsArrayBuffer(argv8)) { rv = self->TexImage2D_buf(argv0, argv1, argv2, argv3, argv4, argv5, argv6, argv7, js::ArrayBuffer::fromJSObject(argv8)); } else if (js_IsTypedArray(argv8)) { rv = self->TexImage2D_array(argv0, argv1, argv2, argv3, argv4, argv5, argv6, argv7, js::TypedArray::fromJSObject(argv8)); } else { xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8); return JS_FALSE; } } else { xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS); return JS_FALSE; } if (NS_FAILED(rv)) return xpc_qsThrowMethodFailed(cx, rv, vp); *vp = JSVAL_VOID; return JS_TRUE; }