Пример #1
0
static JSBool
XPC_SJOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
                    JSObject **objp)
{
  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    // No unsafe object, nothing to resolve here.

    return JS_TRUE;
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  // Resolve toString specially.
  if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
    *objp = obj;
    return JS_DefineFunction(cx, obj, "toString",
                             XPC_SJOW_toString, 0, 0) != nsnull;
  }

  return XPCWrapper::NewResolve(cx, obj, JS_FALSE, unsafeObj, id, flags, objp);
}
Пример #2
0
static JSBool
XPC_SJOW_Enumerate(JSContext *cx, JSObject *obj)
{
  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  // We are being notified of a for-in loop or similar operation on
  // this XPCSafeJSObjectWrapper. Forward to the correct high-level
  // object hook, OBJ_ENUMERATE on the unsafe object, called via the
  // JS_Enumerate API.  Then reflect properties named by the
  // enumerated identifiers from the unsafe object to the safe
  // wrapper.

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    return JS_TRUE;
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  // Since we enumerate using JS_Enumerate() on the unsafe object here
  // we don't need to do a security check since JS_Enumerate() will
  // look up unsafeObj.__iterator__ and if we don't have permission to
  // access that, it'll throw and we'll be safe.

  return XPCWrapper::Enumerate(cx, obj, unsafeObj);
}
Пример #3
0
static JSBool
XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
  // The constructor and toString properties needs to live on the safe
  // wrapper.
  if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_CONSTRUCTOR) ||
      id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
    return JS_TRUE;
  }

  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  // Do nothing here if we're in the middle of resolving a property on
  // this safe wrapper.
  jsval isResolving;
  JSBool ok = ::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_IS_RESOLVING,
                                   &isResolving);
  if (!ok || HAS_FLAGS(isResolving, FLAG_RESOLVING)) {
    return ok;
  }

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    return ThrowException(NS_ERROR_UNEXPECTED, cx);
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  return XPCWrapper::AddProperty(cx, obj, JS_FALSE, unsafeObj, id, vp);
}
Пример #4
0
static JSBool
XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
                          JSBool aIsSet)
{
  // We resolve toString to a function in our resolve hook.
  if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_TO_STRING)) {
    return JS_TRUE;
  }

  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    return ThrowException(NS_ERROR_UNEXPECTED, cx);
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  JSObject *scopeFun = GetScopeFunction(cx, obj);
  if (!scopeFun) {
    return JS_FALSE;
  }

  {
    SafeCallGuard guard(cx, FindObjectPrincipals(cx, obj, unsafeObj));
    if (!guard.ready()) {
      return JS_FALSE;
    }

    jsid interned_id;
    if (!JS_ValueToId(cx, id, &interned_id)) {
      return JS_FALSE;
    }

    if (aIsSet) {
      *vp = UnwrapJSValue(*vp);
    }

    JSBool ok = aIsSet
                ? js_SetPropertyByIdWithFakeFrame(cx, unsafeObj, scopeFun,
                                                  interned_id, vp)
                : js_GetPropertyByIdWithFakeFrame(cx, unsafeObj, scopeFun,
                                                  interned_id, vp);
    if (!ok) {
      return JS_FALSE;
    }
  }

  return WrapJSValue(cx, obj, *vp, vp);
}
Пример #5
0
static inline JSObject *
GetUnsafeObject(JSObject *obj)
{
  obj = FindSafeObject(obj);

  if (!obj) {
    return nsnull;
  }

  return STOBJ_GET_PARENT(obj);
}
Пример #6
0
static JSObject *
XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
  obj = FindSafeObject(obj);
  NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");

  JSObject *unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    ThrowException(NS_ERROR_INVALID_ARG, cx);

    return nsnull;
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return nsnull;
  }

  JSObject *tmp = XPCWrapper::UnwrapGeneric(cx, &sXPC_XOW_JSClass, unsafeObj);
  if (tmp) {
    unsafeObj = tmp;

    // Repeat the CanCallerAccess check because the XOW is parented to our
    // scope's global object which makes the above CanCallerAccess call lie.
    if (!CanCallerAccess(cx, unsafeObj)) {
      // CanCallerAccess() already threw for us.
      return nsnull;
    }
  }

  // Create our dummy SJOW.
  JSObject *wrapperIter =
    ::JS_NewObjectWithGivenProto(cx, &sXPC_SJOW_JSClass.base, nsnull,
                                 unsafeObj);
  if (!wrapperIter) {
    return nsnull;
  }

  if (!::JS_SetReservedSlot(cx, wrapperIter, XPC_SJOW_SLOT_IS_RESOLVING,
                            JSVAL_ZERO)) {
    return nsnull;
  }

  JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));

  // Initialize the wrapper.
  return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj, unsafeObj,
                                       keysonly);
}
Пример #7
0
JSObject *
GetUnsafeObject(JSContext *cx, JSObject *obj)
{
  obj = FindSafeObject(obj);

  if (!obj) {
    return nsnull;
  }

  jsval v;
  if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &v)) {
    JS_ClearPendingException(cx);
    return nsnull;
  }

  return JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : nsnull;
}
Пример #8
0
static JSBool
XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
                  jsval *rval)
{
  obj = FindSafeObject(obj);
  if (!obj) {
    return ThrowException(NS_ERROR_INVALID_ARG, cx);
  }

  JSObject *unsafeObj = GetUnsafeObject(obj);

  if (!unsafeObj) {
    // No unsafe object, nothing to stringify here, return "[object
    // XPCSafeJSObjectWrapper]" so callers know what they're looking
    // at.

    JSString *str = JS_NewStringCopyZ(cx, "[object XPCSafeJSObjectWrapper]");
    if (!str) {
      return JS_FALSE;
    }

    *rval = STRING_TO_JSVAL(str);

    return JS_TRUE;
  }

  // Check that the caller can access the unsafe object.
  if (!CanCallerAccess(cx, unsafeObj)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  {
    SafeCallGuard guard(cx, FindObjectPrincipals(cx, obj, unsafeObj));
    if (!guard.ready()) {
      return JS_FALSE;
    }

    JSString *str = JS_ValueToString(cx, OBJECT_TO_JSVAL(unsafeObj));
    if (!str) {
      return JS_FALSE;
    }
    *rval = STRING_TO_JSVAL(str);
  }
  return JS_TRUE;
}
Пример #9
0
static JSBool
XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
              jsval *rval)
{
  JSObject *tmp = FindSafeObject(obj);
  JSObject *unsafeObj, *callThisObj = nsnull;

  if (tmp) {
    // A function wrapped in an XPCSafeJSObjectWrapper is being called
    // directly (i.e. safeObj.fun()), set obj to be the safe object
    // wrapper. In this case, the "this" object used when calling the
    // function will be the unsafe object gotten off of the safe
    // object.
    obj = tmp;
  } else {
    // A function wrapped in an XPCSafeJSObjectWrapper is being called
    // indirectly off of an object that's not a safe wrapper
    // (i.e. foo.bar = safeObj.fun; foo.bar()), set obj to be the safe
    // wrapper for the function, and use the object passed in as the
    // "this" object when calling the function.
    callThisObj = obj;

    // Check that the caller can access the object we're about to pass
    // in as "this" for the call we're about to make.
    if (!CanCallerAccess(cx, callThisObj)) {
      // CanCallerAccess() already threw for us.
      return JS_FALSE;
    }

    obj = FindSafeObject(JSVAL_TO_OBJECT(argv[-2]));

    if (!obj) {
      return ThrowException(NS_ERROR_INVALID_ARG, cx);
    }
  }

  unsafeObj = GetUnsafeObject(obj);
  if (!unsafeObj) {
    return ThrowException(NS_ERROR_UNEXPECTED, cx);
  }

  if (!callThisObj) {
    callThisObj = unsafeObj;
  }

  JSObject *safeObj = JSVAL_TO_OBJECT(argv[-2]);
  JSObject *funToCall = GetUnsafeObject(safeObj);

  if (!funToCall) {
    // Someone has called XPCSafeJSObjectWrapper.prototype() causing
    // us to find a safe object wrapper without an unsafeObject as
    // its parent. That call shouldn't do anything, so bail here.
    return JS_TRUE;
  }

  // Check that the caller can access the unsafe object on which the
  // call is being made, and the actual function we're about to call.
  if (!CanCallerAccess(cx, unsafeObj) || !CanCallerAccess(cx, funToCall)) {
    // CanCallerAccess() already threw for us.
    return JS_FALSE;
  }

  JSObject *scopeFun = GetScopeFunction(cx, safeObj);
  if (!scopeFun) {
    return JS_FALSE;
  }

  {
    SafeCallGuard guard(cx, FindObjectPrincipals(cx, safeObj, funToCall));

    for (uintN i = 0; i < argc; ++i) {
      argv[i] = UnwrapJSValue(argv[i]);
    }

    if (!js_CallFunctionValueWithFakeFrame(cx, callThisObj, scopeFun,
                                           OBJECT_TO_JSVAL(funToCall),
                                           argc, argv, rval)) {
      return JS_FALSE;
    }
  }

  return WrapJSValue(cx, obj, *rval, rval);
}