bool AccessCheck::isCrossOriginAccessPermitted(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act) { if (act == Wrapper::CALL) return false; if (act == Wrapper::ENUMERATE) return true; // For the case of getting a property descriptor, we allow if either GET or SET // is allowed, and rely on FilteringWrapper to filter out any disallowed accessors. if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) { return isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::GET) || isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::SET); } RootedObject obj(cx, js::UncheckedUnwrap(wrapper, /* stopAtOuter = */ false)); CrossOriginObjectType type = IdentifyCrossOriginObject(obj); if (JSID_IS_STRING(id)) { if (IsPermitted(type, JSID_TO_FLAT_STRING(id), act == Wrapper::SET)) return true; } if (act != Wrapper::GET) return false; // Check for frame IDs. If we're resolving named frames, make sure to only // resolve ones that don't shadow native properties. See bug 860494. if (type == CrossOriginWindow) { if (JSID_IS_STRING(id)) { bool wouldShadow = false; if (!XrayUtils::HasNativeProperty(cx, wrapper, id, &wouldShadow) || wouldShadow) { // If the named subframe matches the name of a DOM constructor, // the global resolve triggered by the HasNativeProperty call // above will try to perform a CheckedUnwrap on |wrapper|, and // throw a security error if it fails. That exception isn't // really useful for our callers, so we silence it and just // deny access to the property (since it matched a builtin). // // Note that this would be a problem if the resolve code ever // tried to CheckedUnwrap the wrapper _before_ concluding that // the name corresponds to a builtin global property, since it // would mean that we'd never permit cross-origin named subframe // access (something we regrettably need to support). JS_ClearPendingException(cx); return false; } } return IsFrameId(cx, obj, id); } return false; }
static void ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type) { /* Don't mark properties for singletons. They'll be purged by the GC. */ if (!type->singleton) { unsigned count = type->getPropertyCount(); for (unsigned i = 0; i < count; i++) { types::Property *prop = type->getProperty(i); if (prop && JSID_IS_STRING(prop->id)) PushMarkStack(gcmarker, JSID_TO_STRING(prop->id)); } } if (TaggedProto(type->proto).isObject()) PushMarkStack(gcmarker, type->proto); if (type->singleton && !type->lazy()) PushMarkStack(gcmarker, type->singleton); if (type->newScript) { PushMarkStack(gcmarker, type->newScript->fun); PushMarkStack(gcmarker, type->newScript->shape); } if (type->interpretedFunction) PushMarkStack(gcmarker, type->interpretedFunction); }
static bool IsFrameId(JSContext* cx, JSObject* obj, jsid idArg) { MOZ_ASSERT(!js::IsWrapper(obj)); RootedId id(cx, idArg); nsGlobalWindow* win = WindowOrNull(obj); if (!win) { return false; } nsCOMPtr<nsIDOMWindowCollection> col = win->GetFrames(); if (!col) { return false; } nsCOMPtr<nsIDOMWindow> domwin; if (JSID_IS_INT(id)) { col->Item(JSID_TO_INT(id), getter_AddRefs(domwin)); } else if (JSID_IS_STRING(id)) { nsAutoJSString idAsString; if (!idAsString.init(cx, JSID_TO_STRING(id))) { return false; } col->NamedItem(idAsString, getter_AddRefs(domwin)); } return domwin != nullptr; }
std::string gjs_debug_id(jsid id) { if (JSID_IS_STRING(id)) return gjs_debug_flat_string(JSID_TO_FLAT_STRING(id)); return gjs_debug_value(js::IdToValue(id)); }
static void ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type) { if (!type->singleton) { unsigned count = type->getPropertyCount(); for (unsigned i = 0; i < count; i++) { types::Property *prop = type->getProperty(i); if (prop && JSID_IS_STRING(prop->id)) PushMarkStack(gcmarker, JSID_TO_STRING(prop->id)); } } if (type->proto) PushMarkStack(gcmarker, type->proto); if (type->newScript) { PushMarkStack(gcmarker, type->newScript->fun); PushMarkStack(gcmarker, type->newScript->shape); } if (type->interpretedFunction) PushMarkStack(gcmarker, type->interpretedFunction); if (type->singleton && !type->lazy()) PushMarkStack(gcmarker, type->singleton); if (type->interpretedFunction) PushMarkStack(gcmarker, type->interpretedFunction); }
/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsid id, in PRUint32 flags, out JSObjectPtr objp); */ NS_IMETHODIMP calDateTime::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsid id, PRUint32 flags, JSObject * *objp, bool *_retval) { NS_ENSURE_ARG_POINTER(objp); NS_ENSURE_ARG_POINTER(_retval); if (JSID_IS_STRING(id)) { size_t length; JSString *idString = JSID_TO_STRING(id); const jschar *str = JS_GetStringCharsAndLength(cx, idString, &length); nsDependentString const name(reinterpret_cast<PRUnichar const*>(str), length); if (name.EqualsLiteral("jsDate")) { *_retval = JS_DefineUCProperty(cx, obj, str, length, JSVAL_VOID, nsnull, nsnull, 0); *objp = obj; return *_retval ? NS_OK : NS_ERROR_FAILURE; } } *_retval = PR_TRUE; return NS_OK; }
StringData ObjectWrapper::Key::toStringData(JSContext* cx, JSStringWrapper* jsstr) { if (_type == Type::Field) { return _field; } if (_type == Type::Index) { *jsstr = JSStringWrapper(_idx); return jsstr->toStringData(); } JS::RootedId rid(cx); if (_type == Type::Id) { rid.set(_id); } else { InternedStringId id(cx, _internedString); rid.set(id); } if (JSID_IS_INT(rid)) { *jsstr = JSStringWrapper(JSID_TO_INT(rid)); return jsstr->toStringData(); } if (JSID_IS_STRING(rid)) { *jsstr = JSStringWrapper(cx, JSID_TO_STRING(rid)); return jsstr->toStringData(); } uasserted(ErrorCodes::BadValue, "Couldn't convert key to String"); }
bool doResolve(JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { CHECK_EQUAL(resolveExitCount, 0); AutoIncrCounters incr(this); CHECK(obj == obj1 || obj == obj2); CHECK(JSID_IS_STRING(id)); JSFlatString* str = JS_FlattenString(cx, JSID_TO_STRING(id)); CHECK(str); JS::RootedValue v(cx); if (JS_FlatStringEqualsAscii(str, "x")) { if (obj == obj1) { /* First resolve hook invocation. */ CHECK_EQUAL(resolveEntryCount, 1); EVAL("obj2.y = true", &v); CHECK(v.isTrue()); CHECK(JS_DefinePropertyById(cx, obj, id, JS::FalseHandleValue, JSPROP_RESOLVING)); *resolvedp = true; return true; } if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 4); *resolvedp = false; return true; } } else if (JS_FlatStringEqualsAscii(str, "y")) { if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 2); CHECK(JS_DefinePropertyById(cx, obj, id, JS::NullHandleValue, JSPROP_RESOLVING)); EVAL("obj1.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y", &v); CHECK(v.isInt32(0)); *resolvedp = true; return true; } if (obj == obj1) { CHECK_EQUAL(resolveEntryCount, 3); EVAL("obj1.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y", &v); CHECK(v.isUndefined()); EVAL("obj2.y", &v); CHECK(v.isNull()); EVAL("obj2.x", &v); CHECK(v.isUndefined()); EVAL("obj1.y = 0", &v); CHECK(v.isInt32(0)); *resolvedp = true; return true; } } CHECK(false); return false; }
bool doResolve(JSObject *obj, jsid id, uintN flags, JSObject **objp) { CHECK_EQUAL(resolveExitCount, 0); AutoIncrCounters incr(this); CHECK_EQUAL(obj, obj1 || obj == obj2); CHECK(JSID_IS_STRING(id)); JSFlatString *str = JS_FlattenString(cx, JSID_TO_STRING(id)); CHECK(str); jsval v; if (JS_FlatStringEqualsAscii(str, "x")) { if (obj == obj1) { /* First resolve hook invocation. */ CHECK_EQUAL(resolveEntryCount, 1); EVAL("obj2.y = true", &v); CHECK_SAME(v, JSVAL_TRUE); CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_FALSE, NULL, NULL, 0)); *objp = obj; return true; } if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 4); *objp = NULL; return true; } } else if (JS_FlatStringEqualsAscii(str, "y")) { if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 2); CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_NULL, NULL, NULL, 0)); EVAL("obj1.x", &v); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y", &v); CHECK_SAME(v, JSVAL_ZERO); *objp = obj; return true; } if (obj == obj1) { CHECK_EQUAL(resolveEntryCount, 3); EVAL("obj1.x", &v); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y", &v); CHECK(JSVAL_IS_VOID(v)); EVAL("obj2.y", &v); CHECK(JSVAL_IS_NULL(v)); EVAL("obj2.x", &v); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y = 0", &v); CHECK_SAME(v, JSVAL_ZERO); *objp = obj; return true; } } CHECK(false); return false; }
bool doResolve(JSHandleObject obj, JSHandleId id, unsigned flags, JSMutableHandleObject objp) { CHECK_EQUAL(resolveExitCount, 0); AutoIncrCounters incr(this); CHECK_EQUAL(obj, obj1 || obj == obj2); CHECK(JSID_IS_STRING(id)); JSFlatString *str = JS_FlattenString(cx, JSID_TO_STRING(id)); CHECK(str); JS::RootedValue v(cx); if (JS_FlatStringEqualsAscii(str, "x")) { if (obj == obj1) { /* First resolve hook invocation. */ CHECK_EQUAL(resolveEntryCount, 1); EVAL("obj2.y = true", v.address()); CHECK_SAME(v, JSVAL_TRUE); CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_FALSE, NULL, NULL, 0)); objp.set(obj); return true; } if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 4); objp.set(NULL); return true; } } else if (JS_FlatStringEqualsAscii(str, "y")) { if (obj == obj2) { CHECK_EQUAL(resolveEntryCount, 2); CHECK(JS_DefinePropertyById(cx, obj, id, JSVAL_NULL, NULL, NULL, 0)); EVAL("obj1.x", v.address()); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y", v.address()); CHECK_SAME(v, JSVAL_ZERO); objp.set(obj); return true; } if (obj == obj1) { CHECK_EQUAL(resolveEntryCount, 3); EVAL("obj1.x", v.address()); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y", v.address()); CHECK(JSVAL_IS_VOID(v)); EVAL("obj2.y", v.address()); CHECK(JSVAL_IS_NULL(v)); EVAL("obj2.x", v.address()); CHECK(JSVAL_IS_VOID(v)); EVAL("obj1.y = 0", v.address()); CHECK_SAME(v, JSVAL_ZERO); objp.set(obj); return true; } } CHECK(false); return false; }
NS_IMETHODIMP StatementParams::Resolve(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, bool *resolvedp, bool *_retval) { NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); // We do not throw at any point after this unless our index is out of range // because we want to allow the prototype chain to be checked for the // property. JS::RootedObject scope(aCtx, aScopeObj); JS::RootedId id(aCtx, aId); bool resolved = false; bool ok = true; if (JSID_IS_INT(id)) { uint32_t idx = JSID_TO_INT(id); // Ensure that our index is within range. We do not care about the // prototype chain being checked here. if (idx >= mParamCount) return NS_ERROR_INVALID_ARG; ok = ::JS_DefineElement(aCtx, scope, idx, JS::UndefinedHandleValue, JSPROP_ENUMERATE | JSPROP_RESOLVING); resolved = true; } else if (JSID_IS_STRING(id)) { JSString *str = JSID_TO_STRING(id); nsAutoJSString autoStr; if (!autoStr.init(aCtx, str)) { return NS_ERROR_FAILURE; } // Check to see if there's a parameter with this name, and if not, let // the rest of the prototype chain be checked. NS_ConvertUTF16toUTF8 name(autoStr); uint32_t idx; nsresult rv = mStatement->GetParameterIndex(name, &idx); if (NS_SUCCEEDED(rv)) { ok = ::JS_DefinePropertyById(aCtx, scope, id, JS::UndefinedHandleValue, JSPROP_ENUMERATE | JSPROP_RESOLVING); resolved = true; } } *_retval = ok; *resolvedp = resolved && ok; return NS_OK; }
NS_IMETHODIMP StatementParams::NewResolve(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, uint32_t aFlags, JSObject **_objp, bool *_retval) { NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); // We do not throw at any point after this unless our index is out of range // because we want to allow the prototype chain to be checked for the // property. JS::RootedObject scope(aCtx, aScopeObj); JS::RootedId id(aCtx, aId); bool resolved = false; bool ok = true; if (JSID_IS_INT(id)) { uint32_t idx = JSID_TO_INT(id); // Ensure that our index is within range. We do not care about the // prototype chain being checked here. if (idx >= mParamCount) return NS_ERROR_INVALID_ARG; ok = ::JS_DefineElement(aCtx, scope, idx, JSVAL_VOID, nullptr, nullptr, JSPROP_ENUMERATE); resolved = true; } else if (JSID_IS_STRING(id)) { JSString *str = JSID_TO_STRING(id); size_t nameLength; const jschar *nameChars = JS_GetStringCharsAndLength(aCtx, str, &nameLength); NS_ENSURE_TRUE(nameChars, NS_ERROR_UNEXPECTED); // Check to see if there's a parameter with this name, and if not, let // the rest of the prototype chain be checked. NS_ConvertUTF16toUTF8 name(nameChars, nameLength); uint32_t idx; nsresult rv = mStatement->GetParameterIndex(name, &idx); if (NS_SUCCEEDED(rv)) { ok = ::JS_DefinePropertyById(aCtx, scope, id, JSVAL_VOID, nullptr, nullptr, JSPROP_ENUMERATE); resolved = true; } } *_retval = ok; *_objp = resolved && ok ? scope.get() : nullptr; return NS_OK; }
static inline void MarkIdInternal(JSTracer *trc, jsid *id) { if (JSID_IS_STRING(*id)) { JSString *str = JSID_TO_STRING(*id); MarkInternal(trc, &str); *id = ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str)); } else if (JS_UNLIKELY(JSID_IS_OBJECT(*id))) { JSObject *obj = JSID_TO_OBJECT(*id); MarkInternal(trc, &obj); *id = OBJECT_TO_JSID(obj); } }
StringData IdWrapper::toStringData(JSStringWrapper* jsstr) const { if (JSID_IS_STRING(_value)) { *jsstr = JSStringWrapper(_context, JSID_TO_STRING(_value)); } else if (JSID_IS_INT(_value)) { *jsstr = JSStringWrapper(JSID_TO_INT(_value)); } else { throwCurrentJSException(_context, ErrorCodes::TypeMismatch, "Cannot toString() non-string and non-integer jsid"); } return jsstr->toStringData(); }
JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsid id, jsval* rval) { Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj << Debug::flush; SessionData* data = JavaObject::getSessionData(ctx, obj); if (!data) { // TODO: replace the frame with an error page instead? *rval = JSVAL_VOID; return JS_TRUE; } int objectRef = JavaObject::getObjectId(ctx, obj); if (JSID_IS_STRING(id)) { JSString* str = JSID_TO_STRING(id); if ((JS_GetStringEncodingLength(ctx, str) == 8) && !strncmp("toString", JS_EncodeString(ctx, str), 8)) { *rval = data->getToStringTearOff(); return JS_TRUE; } if ((JS_GetStringEncodingLength(ctx, str) == 2) && !strncmp("id", JS_EncodeString(ctx, str), 2)) { *rval = INT_TO_JSVAL(objectRef); return JS_TRUE; } if ((JS_GetStringEncodingLength(ctx, str) == 16) && !strncmp("__noSuchMethod__", JS_EncodeString(ctx, str), 16)) { // Avoid error spew if we are disconnected *rval = JSVAL_VOID; return JS_TRUE; } // TODO: dumpJsVal can no longer handle this case //Debug::log(Debug::Error) << "Getting unexpected string property " // << dumpJsVal(ctx, id) << Debug::flush; // TODO: throw a better exception here return JS_FALSE; } if (!JSID_IS_INT(id)) { // TODO: dumpJsVal can no longer handle this case //Debug::log(Debug::Error) << "Getting non-int/non-string property " // << dumpJsVal(ctx, id) << Debug::flush; // TODO: throw a better exception here return JS_FALSE; } int dispId = JSID_TO_INT(id); HostChannel* channel = data->getHostChannel(); SessionHandler* handler = data->getSessionHandler(); gwt::Value value = ServerMethods::getProperty(*channel, handler, objectRef, dispId); data->makeJsvalFromValue(*rval, ctx, value); return JS_TRUE; }
NS_IMETHODIMP StatementParams::NewResolve(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, PRUint32 aFlags, JSObject **_objp, PRBool *_retval) { NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED); // We do not throw at any point after this unless our index is out of range // because we want to allow the prototype chain to be checked for the // property. bool resolved = false; PRBool ok = PR_TRUE; if (JSID_IS_INT(aId)) { PRUint32 idx = JSID_TO_INT(aId); // Ensure that our index is within range. We do not care about the // prototype chain being checked here. if (idx >= mParamCount) return NS_ERROR_INVALID_ARG; ok = ::JS_DefineElement(aCtx, aScopeObj, idx, JSVAL_VOID, nsnull, nsnull, JSPROP_ENUMERATE); resolved = true; } else if (JSID_IS_STRING(aId)) { JSString *str = JSID_TO_STRING(aId); jschar *nameChars = ::JS_GetStringChars(str); size_t nameLength = ::JS_GetStringLength(str); // Check to see if there's a parameter with this name, and if not, let // the rest of the prototype chain be checked. NS_ConvertUTF16toUTF8 name(reinterpret_cast<const PRUnichar *>(nameChars), nameLength); PRUint32 idx; nsresult rv = mStatement->GetParameterIndex(name, &idx); if (NS_SUCCEEDED(rv)) { ok = ::JS_DefineUCProperty(aCtx, aScopeObj, nameChars, nameLength, JSVAL_VOID, nsnull, nsnull, JSPROP_ENUMERATE); resolved = true; } } *_retval = ok; *_objp = resolved && ok ? aScopeObj : nsnull; return NS_OK; }
static void ScanShape(GCMarker *gcmarker, Shape *shape) { restart: PushMarkStack(gcmarker, shape->base()); const HeapId &id = shape->propidRef(); if (JSID_IS_STRING(id)) PushMarkStack(gcmarker, JSID_TO_STRING(id)); else if (JS_UNLIKELY(JSID_IS_OBJECT(id))) PushMarkStack(gcmarker, JSID_TO_OBJECT(id)); shape = shape->previous(); if (shape && shape->markIfUnmarked(gcmarker->getMarkColor())) goto restart; }
NS_INTERFACE_MAP_END //////////////////////////////////////////////////////////////////////////////// //// nsIXPCScriptable #define XPC_MAP_CLASSNAME StatementJSHelper #define XPC_MAP_QUOTED_CLASSNAME "StatementJSHelper" #define XPC_MAP_WANT_GETPROPERTY #define XPC_MAP_WANT_RESOLVE #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE #include "xpc_map_end.h" NS_IMETHODIMP StatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, JS::Value *_result, bool *_retval) { if (!JSID_IS_STRING(aId)) return NS_OK; JS::Rooted<JSObject*> scope(aCtx, aScopeObj); JS::Rooted<jsid> id(aCtx, aId); #ifdef DEBUG { nsCOMPtr<mozIStorageStatement> isStatement( do_QueryInterface(aWrapper->Native())); NS_ASSERTION(isStatement, "How is this not a statement?!"); } #endif Statement *stmt = static_cast<Statement *>( static_cast<mozIStorageStatement *>(aWrapper->Native()) ); JSFlatString *str = JSID_TO_FLAT_STRING(id); if (::JS_FlatStringEqualsAscii(str, "row")) return getRow(stmt, aCtx, scope, _result); if (::JS_FlatStringEqualsAscii(str, "params")) return getParams(stmt, aCtx, scope, _result); return NS_OK; }
// static void XPCThrower::Verbosify(XPCCallContext& ccx, char** psz, PRBool own) { char* sz = nsnull; if(ccx.HasInterfaceAndMember()) { XPCNativeInterface* iface = ccx.GetInterface(); jsid id = JSID_VOID; #ifdef XPC_IDISPATCH_SUPPORT NS_ASSERTION(ccx.GetIDispatchMember() == nsnull || ccx.GetMember() == nsnull, "Both IDispatch member and regular XPCOM member " "were set in XPCCallContext"); if(ccx.GetIDispatchMember()) { XPCDispInterface::Member * member = reinterpret_cast<XPCDispInterface::Member*>(ccx.GetIDispatchMember()); if(member && JSID_IS_STRING(member->GetName())) { id = member->GetName(); } } else #endif { id = ccx.GetMember()->GetName(); } JSAutoByteString bytes; const char *name = JSID_IS_VOID(id) ? "Unknown" : bytes.encode(ccx, JSID_TO_STRING(id)); if(!name) { name = ""; } sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name); } if(sz) { if(own) JS_smprintf_free(*psz); *psz = sz; } }
static inline void MarkIdInternal(JSTracer *trc, jsid *id) { if (JSID_IS_STRING(*id)) { JSString *str = JSID_TO_STRING(*id); JS_SET_TRACING_LOCATION(trc, (void *)id); MarkInternal(trc, &str); *id = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str)); } else if (JS_UNLIKELY(JSID_IS_OBJECT(*id))) { JSObject *obj = JSID_TO_OBJECT(*id); JS_SET_TRACING_LOCATION(trc, (void *)id); MarkInternal(trc, &obj); *id = OBJECT_TO_JSID(obj); } else { /* Unset realLocation manually if we do not call MarkInternal. */ JS_UNSET_TRACING_LOCATION(trc); } }
NS_IMETHODIMP StatementJSHelper::Resolve(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, bool *aResolvedp, bool *_retval) { if (!JSID_IS_STRING(aId)) return NS_OK; JS::RootedObject scope(aCtx, aScopeObj); if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) { *_retval = ::JS_DefineFunction(aCtx, scope, "step", stepFunc, 0, JSPROP_RESOLVING) != nullptr; *aResolvedp = true; return NS_OK; } return NS_OK; }
NS_IMETHODIMP StatementJSHelper::NewResolve(nsIXPConnectWrappedNative *aWrapper, JSContext *aCtx, JSObject *aScopeObj, jsid aId, PRUint32 aFlags, JSObject **_objp, bool *_retval) { if (!JSID_IS_STRING(aId)) return NS_OK; if (::JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), "step")) { *_retval = ::JS_DefineFunction(aCtx, aScopeObj, "step", stepFunc, 0, 0) != nullptr; *_objp = aScopeObj; return NS_OK; } return NS_OK; }
/* bool setProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsid id, in JSValPtr vp); */ NS_IMETHODIMP calDateTime::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj, jsid id, jsval * vp, bool *_retval) { NS_ENSURE_ARG_POINTER(_retval); if (JSID_IS_STRING(id)) { size_t length; JSString *idString = JSID_TO_STRING(id); const jschar *str = JS_GetStringCharsAndLength(cx, idString, &length); nsDependentString const val(reinterpret_cast<PRUnichar const*>(str), length); if (val.EqualsLiteral("jsDate") && vp) { JSObject *dobj; if (!JSVAL_IS_OBJECT(*vp) || !js_DateIsValid(cx, (dobj = JSVAL_TO_OBJECT(*vp)))) { mIsValid = PR_FALSE; } else { jsdouble utcMsec = js_DateGetMsecSinceEpoch(cx, dobj); PRTime utcTime, thousands; LL_F2L(utcTime, utcMsec); LL_I2L(thousands, 1000); LL_MUL(utcTime, utcTime, thousands); nsresult rv = SetNativeTime(utcTime); if (NS_SUCCEEDED(rv)) { mIsValid = PR_TRUE; } else { mIsValid = PR_FALSE; } } *_retval = PR_TRUE; return NS_SUCCESS_I_DID_SOMETHING; } } *_retval = PR_TRUE; return NS_OK; }
/* bool getProperty (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsid id, in JSValPtr vp); */ NS_IMETHODIMP calDateTime::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext * cx, JSObject * obj_, jsid id, jsval * vp, bool *_retval) { NS_ENSURE_ARG_POINTER(vp); NS_ENSURE_ARG_POINTER(_retval); if (JSID_IS_STRING(id)) { size_t length; JSString *idString = JSID_TO_STRING(id); const jschar *str = JS_GetStringCharsAndLength(cx, idString, &length); nsDependentString const val(reinterpret_cast<PRUnichar const*>(str), length); if (val.EqualsLiteral("jsDate")) { PRTime tmp, thousand; jsdouble msec; LL_I2L(thousand, 1000); LL_DIV(tmp, mNativeTime, thousand); LL_L2D(msec, tmp); ensureTimezone(); JSObject *obj; bool b; if (NS_SUCCEEDED(mTimezone->GetIsFloating(&b)) && b) { obj = js_NewDateObject(cx, mYear, mMonth, mDay, mHour, mMinute, mSecond); } else { obj = js_NewDateObjectMsec(cx, msec); } *vp = OBJECT_TO_JSVAL(obj); *_retval = PR_TRUE; return NS_SUCCESS_I_DID_SOMETHING; } } *_retval = PR_TRUE; return NS_OK; }
/* static */ bool WebIDLGlobalNameHash::ResolveForSystemGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId, bool* aResolvedp) { MOZ_ASSERT(JS_IsGlobalObject(aObj)); // First we try to resolve standard classes. if (!JS_ResolveStandardClass(aCx, aObj, aId, aResolvedp)) { return false; } if (*aResolvedp) { return true; } // We don't resolve any non-string entries. if (!JSID_IS_STRING(aId)) { return true; } // XXX(nika): In the Window case, we unwrap our global object here to handle // XRays. I don't think we ever create xrays to system globals, so I believe // we can skip this step. MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(aObj), "Xrays not supported!"); // Look up the corresponding entry in the name table, and resolve if enabled. const WebIDLNameTableEntry* entry = GetEntry(JSID_TO_FLAT_STRING(aId)); if (entry && (!entry->mEnabled || entry->mEnabled(aCx, aObj))) { if (NS_WARN_IF(!GetPerInterfaceObjectHandle( aCx, entry->mConstructorId, entry->mCreate, /* aDefineOnGlobal = */ true))) { return Throw(aCx, NS_ERROR_FAILURE); } *aResolvedp = true; } return true; }
/* static */ bool WebIDLGlobalNameHash::DefineIfEnabled( JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId, JS::MutableHandle<JS::PropertyDescriptor> aDesc, bool* aFound) { MOZ_ASSERT(JSID_IS_STRING(aId), "Check for string id before calling this!"); const WebIDLNameTableEntry* entry; { entry = GetEntry(JSID_TO_FLAT_STRING(aId)); } if (!entry) { *aFound = false; return true; } *aFound = true; ConstructorEnabled checkEnabledForScope = entry->mEnabled; // We do the enabled check on the current Realm of aCx, but for the // actual object we pass in the underlying object in the Xray case. That // way the callee can decide whether to allow access based on the caller // or the window being touched. // // Using aCx to represent the current Realm for CheckedUnwrapDynamic // purposes is OK here, because that's the Realm where we plan to do // our property-defining. JS::Rooted<JSObject*> global( aCx, js::CheckedUnwrapDynamic(aObj, aCx, /* stopAtWindowProxy = */ false)); if (!global) { return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR); } { // It's safe to pass "&global" here, because we've already unwrapped it, but // for general sanity better to not have debug code even having the // appearance of mutating things that opt code uses. #ifdef DEBUG JS::Rooted<JSObject*> temp(aCx, global); DebugOnly<nsGlobalWindowInner*> win; MOZ_ASSERT(NS_SUCCEEDED( UNWRAP_MAYBE_CROSS_ORIGIN_OBJECT(Window, &temp, win, aCx))); #endif } if (checkEnabledForScope && !checkEnabledForScope(aCx, global)) { return true; } // The DOM constructor resolve machinery interacts with Xrays in tricky // ways, and there are some asymmetries that are important to understand. // // In the regular (non-Xray) case, we only want to resolve constructors // once (so that if they're deleted, they don't reappear). We do this by // stashing the constructor in a slot on the global, such that we can see // during resolve whether we've created it already. This is rather // memory-intensive, so we don't try to maintain these semantics when // manipulating a global over Xray (so the properties just re-resolve if // they've been deleted). // // Unfortunately, there's a bit of an impedance-mismatch between the Xray // and non-Xray machinery. The Xray machinery wants an API that returns a // JS::PropertyDescriptor, so that the resolve hook doesn't have to get // snared up with trying to define a property on the Xray holder. At the // same time, the DefineInterface callbacks are set up to define things // directly on the global. And re-jiggering them to return property // descriptors is tricky, because some DefineInterface callbacks define // multiple things (like the Image() alias for HTMLImageElement). // // So the setup is as-follows: // // * The resolve function takes a JS::PropertyDescriptor, but in the // non-Xray case, callees may define things directly on the global, and // set the value on the property descriptor to |undefined| to indicate // that there's nothing more for the caller to do. We assert against // this behavior in the Xray case. // // * We make sure that we do a non-Xray resolve first, so that all the // slots are set up. In the Xray case, this means unwrapping and doing // a non-Xray resolve before doing the Xray resolve. // // This all could use some grand refactoring, but for now we just limp // along. if (xpc::WrapperFactory::IsXrayWrapper(aObj)) { JS::Rooted<JSObject*> constructor(aCx); { JSAutoRealm ar(aCx, global); constructor = FindNamedConstructorForXray(aCx, aId, entry); } if (NS_WARN_IF(!constructor)) { return Throw(aCx, NS_ERROR_FAILURE); } if (!JS_WrapObject(aCx, &constructor)) { return Throw(aCx, NS_ERROR_FAILURE); } FillPropertyDescriptor(aDesc, aObj, 0, JS::ObjectValue(*constructor)); return true; } JS::Rooted<JSObject*> interfaceObject( aCx, GetPerInterfaceObjectHandle(aCx, entry->mConstructorId, entry->mCreate, /* aDefineOnGlobal = */ true)); if (NS_WARN_IF(!interfaceObject)) { return Throw(aCx, NS_ERROR_FAILURE); } // We've already defined the property. We indicate this to the caller // by filling a property descriptor with JS::UndefinedValue() as the // value. We still have to fill in a property descriptor, though, so // that the caller knows the property is in fact on this object. It // doesn't matter what we pass for the "readonly" argument here. FillPropertyDescriptor(aDesc, aObj, JS::UndefinedValue(), false); return true; }
bool WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId, bool /* unused */, JS::MutableHandle<JSPropertyDescriptor> aDesc) const { if (!JSID_IS_STRING(aId)) { // Nothing to do if we're resolving a non-string property. return true; } JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy)); if (HasPropertyOnPrototype(aCx, aProxy, aId)) { return true; } nsAutoJSString str; if (!str.init(aCx, JSID_TO_STRING(aId))) { return false; } // Grab the DOM window. nsGlobalWindow* win = GetWindowFromGlobal(global); if (win->Length() > 0) { nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str); if (childWin && ShouldExposeChildWindow(str, childWin)) { // We found a subframe of the right name. Shadowing via |var foo| in // global scope is still allowed, since |var| only looks up |own| // properties. But unqualified shadowing will fail, per-spec. JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, childWin, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } } // The rest of this function is for HTML documents only. nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc()); if (!htmlDoc) { return true; } nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get()); Element* element = document->GetElementById(str); if (element) { JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, element, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } nsWrapperCache* cache; nsISupports* result = document->ResolveName(str, &cache); if (!result) { return true; } JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, result, cache, nullptr, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; }
bool IdWrapper::isString() const { return JSID_IS_STRING(_value); }
bool ExposedPropertiesOnly::check(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act) { RootedObject wrappedObject(cx, Wrapper::wrappedObject(wrapper)); if (act == Wrapper::CALL) return false; // For the case of getting a property descriptor, we allow if either GET or SET // is allowed, and rely on FilteringWrapper to filter out any disallowed accessors. if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) { return check(cx, wrapper, id, Wrapper::GET) || check(cx, wrapper, id, Wrapper::SET); } RootedId exposedPropsId(cx, GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)); // We need to enter the wrappee's compartment to look at __exposedProps__, // but we want to be in the wrapper's compartment if we call Deny(). // // Unfortunately, |cx| can be in either compartment when we call ::check. :-( JSAutoCompartment ac(cx, wrappedObject); bool found = false; if (!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found)) return false; // If no __exposedProps__ existed, deny access. if (!found) { // Previously we automatically granted access to indexed properties and // .length for Array COWs. We're not doing that anymore, so make sure to // let people know what's going on. bool isArray; if (!JS_IsArrayObject(cx, wrappedObject, &isArray)) return false; if (!isArray) isArray = JS_IsTypedArrayObject(wrappedObject); bool isIndexedAccessOnArray = isArray && JSID_IS_INT(id) && JSID_TO_INT(id) >= 0; bool isLengthAccessOnArray = isArray && JSID_IS_STRING(id) && JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "length"); if (isIndexedAccessOnArray || isLengthAccessOnArray) { JSAutoCompartment ac2(cx, wrapper); ReportWrapperDenial(cx, id, WrapperDenialForCOW, "Access to elements and length of privileged Array not permitted"); } return false; } if (id == JSID_VOID) return true; Rooted<JSPropertyDescriptor> desc(cx); if (!JS_GetPropertyDescriptorById(cx, wrappedObject, exposedPropsId, &desc)) return false; if (!desc.object()) return false; if (desc.hasGetterOrSetter()) { EnterAndThrow(cx, wrapper, "__exposedProps__ must be a value property"); return false; } RootedValue exposedProps(cx, desc.value()); if (exposedProps.isNullOrUndefined()) return false; if (!exposedProps.isObject()) { EnterAndThrow(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object"); return false; } RootedObject hallpass(cx, &exposedProps.toObject()); if (!AccessCheck::subsumes(js::UncheckedUnwrap(hallpass), wrappedObject)) { EnterAndThrow(cx, wrapper, "Invalid __exposedProps__"); return false; } Access access = NO_ACCESS; if (!JS_GetPropertyDescriptorById(cx, hallpass, id, &desc)) { return false; // Error } if (!desc.object() || !desc.enumerable()) return false; if (!desc.value().isString()) { EnterAndThrow(cx, wrapper, "property must be a string"); return false; } JSFlatString* flat = JS_FlattenString(cx, desc.value().toString()); if (!flat) return false; size_t length = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(flat)); for (size_t i = 0; i < length; ++i) { char16_t ch = JS_GetFlatStringCharAt(flat, i); switch (ch) { case 'r': if (access & READ) { EnterAndThrow(cx, wrapper, "duplicate 'readable' property flag"); return false; } access = Access(access | READ); break; case 'w': if (access & WRITE) { EnterAndThrow(cx, wrapper, "duplicate 'writable' property flag"); return false; } access = Access(access | WRITE); break; default: EnterAndThrow(cx, wrapper, "properties can only be readable or read and writable"); return false; } } if (access == NO_ACCESS) { EnterAndThrow(cx, wrapper, "specified properties must have a permission bit set"); return false; } if ((act == Wrapper::SET && !(access & WRITE)) || (act != Wrapper::SET && !(access & READ))) { return false; } // Inspect the property on the underlying object to check for red flags. if (!JS_GetPropertyDescriptorById(cx, wrappedObject, id, &desc)) return false; // Reject accessor properties. if (desc.hasGetterOrSetter()) { EnterAndThrow(cx, wrapper, "Exposing privileged accessor properties is prohibited"); return false; } // Reject privileged or cross-origin callables. if (desc.value().isObject()) { RootedObject maybeCallable(cx, js::UncheckedUnwrap(&desc.value().toObject())); if (JS::IsCallable(maybeCallable) && !AccessCheck::subsumes(wrapper, maybeCallable)) { EnterAndThrow(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited"); return false; } } return true; }
JSBool RUST_JSID_IS_STRING(jsid id) { return JSID_IS_STRING(id); }