JSObject * WrapperFactory::Rewrap(JSContext *cx, JSObject *existing, JSObject *obj, JSObject *wrappedProto, JSObject *parent, unsigned flags) { MOZ_ASSERT(!IsWrapper(obj) || GetProxyHandler(obj) == &XrayWaiver || js::GetObjectClass(obj)->ext.innerObject, "wrapped object passed to rewrap"); MOZ_ASSERT(JS_GetClass(obj) != &XrayUtils::HolderClass, "trying to wrap a holder"); MOZ_ASSERT(!js::IsInnerObject(obj)); // We sometimes end up here after nsContentUtils has been shut down but before // XPConnect has been shut down, so check the context stack the roundabout way. MOZ_ASSERT(XPCJSRuntime::Get()->GetJSContextStack()->Peek() == cx); // Compute the information we need to select the right wrapper. JSCompartment *origin = js::GetObjectCompartment(obj); JSCompartment *target = js::GetContextCompartment(cx); bool originIsChrome = AccessCheck::isChrome(origin); bool targetIsChrome = AccessCheck::isChrome(target); bool originSubsumesTarget = AccessCheck::subsumes(origin, target); bool targetSubsumesOrigin = AccessCheck::subsumes(target, origin); bool sameOrigin = targetSubsumesOrigin && originSubsumesTarget; XrayType xrayType = GetXrayType(obj); // By default we use the wrapped proto of the underlying object as the // prototype for our wrapper, but we may select something different below. JSObject *proxyProto = wrappedProto; Wrapper *wrapper; CompartmentPrivate *targetdata = EnsureCompartmentPrivate(target); // // First, handle the special cases. // // If UniversalXPConnect is enabled, this is just some dumb mochitest. Use // a vanilla CCW. if (xpc::IsUniversalXPConnectEnabled(target)) { wrapper = &CrossCompartmentWrapper::singleton; // If this is a chrome object being exposed to content without Xrays, use // a COW. } else if (originIsChrome && !targetIsChrome && xrayType == NotXray) { wrapper = &ChromeObjectWrapper::singleton; // If content is accessing a Components object or NAC, we need a special filter, // even if the object is same origin. } else if (IsComponentsObject(obj) && !AccessCheck::isChrome(target)) { wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, ComponentsObjectPolicy>::singleton; } else if (AccessCheck::needsSystemOnlyWrapper(obj) && !(targetIsChrome || (targetSubsumesOrigin && nsContentUtils::IsCallerXBL()))) { wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, OnlyIfSubjectIsSystem>::singleton; } // // Now, handle the regular cases. // // These are wrappers we can compute using a rule-based approach. In order // to do so, we need to compute some parameters. // else { // The wrapper is a security wrapper (protecting the wrappee) if and // only if the target does not subsume the origin. bool securityWrapper = !targetSubsumesOrigin; // Xrays are warranted if either the target or the origin don't trust // each other. This is generally the case, unless the two are same-origin // and the caller has not requested same-origin Xrays. // // Xrays are a bidirectional protection, since it affords clarity to the // caller and privacy to the callee. bool wantXrays = !(sameOrigin && !targetdata->wantXrays); // If Xrays are warranted, the caller may waive them for non-security // wrappers. bool waiveXrays = wantXrays && !securityWrapper && (flags & WAIVE_XRAY_WRAPPER_FLAG); wrapper = SelectWrapper(securityWrapper, wantXrays, xrayType, waiveXrays); } // If the prototype of a chrome object being wrapped in content is a prototype // for a standard class, use the one from the content compartment so // that we can safely take advantage of things like .forEach(). // // If the prototype chain of chrome object |obj| looks like this: // // obj => foo => bar => chromeWin.StandardClass.prototype // // The prototype chain of COW(obj) looks lke this: // // COW(obj) => COW(foo) => COW(bar) => contentWin.StandardClass.prototype if (wrapper == &ChromeObjectWrapper::singleton) { JSProtoKey key = JSProto_Null; { JSAutoCompartment ac(cx, obj); JSObject *unwrappedProto; if (!js::GetObjectProto(cx, obj, &unwrappedProto)) return NULL; if (unwrappedProto && IsCrossCompartmentWrapper(unwrappedProto)) unwrappedProto = Wrapper::wrappedObject(unwrappedProto); if (unwrappedProto) { JSAutoCompartment ac2(cx, unwrappedProto); key = JS_IdentifyClassPrototype(cx, unwrappedProto); } } if (key != JSProto_Null) { JSObject *homeProto; if (!JS_GetClassPrototype(cx, key, &homeProto)) return NULL; MOZ_ASSERT(homeProto); proxyProto = homeProto; } // This shouldn't happen, but do a quick check to make some dumb addon // doesn't expose chrome eval or Function(). JSFunction *fun = JS_GetObjectFunction(obj); if (fun) { if (JS_IsBuiltinEvalFunction(fun) || JS_IsBuiltinFunctionConstructor(fun)) { JS_ReportError(cx, "Not allowed to access chrome eval or Function from content"); return nullptr; } } } DEBUG_CheckUnwrapSafety(obj, wrapper, origin, target); if (existing && proxyProto == wrappedProto) return Wrapper::Renew(cx, existing, obj, wrapper); return Wrapper::New(cx, obj, proxyProto, parent, wrapper); }
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, GetJSIDByIndex(cx, XPCJSContext::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<PropertyDescriptor> desc(cx); if (!JS_GetPropertyDescriptorById(cx, wrappedObject, exposedPropsId, &desc)) return false; if (!desc.object()) return false; if (desc.hasGetterOrSetter()) { EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be a value property"); return false; } RootedValue exposedProps(cx, desc.value()); if (exposedProps.isNullOrUndefined()) return false; if (!exposedProps.isObject()) { EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object"); return false; } RootedObject hallpass(cx, &exposedProps.toObject()); if (!AccessCheck::subsumes(js::UncheckedUnwrap(hallpass), wrappedObject)) { EnterAndThrowASCII(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()) { EnterAndThrowASCII(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) { EnterAndThrowASCII(cx, wrapper, "duplicate 'readable' property flag"); return false; } access = Access(access | READ); break; case 'w': if (access & WRITE) { EnterAndThrowASCII(cx, wrapper, "duplicate 'writable' property flag"); return false; } access = Access(access | WRITE); break; default: EnterAndThrowASCII(cx, wrapper, "properties can only be readable or read and writable"); return false; } } if (access == NO_ACCESS) { EnterAndThrowASCII(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()) { EnterAndThrowASCII(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)) { EnterAndThrowASCII(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited"); return false; } } return true; }
int main(int argc, char** argv){ ros::init(argc, argv, "simple_navigation_goals"); //tell the action client that we want to spin a thread by default MoveBaseClient ac("move_base", true); move_base_msgs::MoveBaseGoal goal; goal.target_pose.header.frame_id = "map"; goal.target_pose.header.stamp = ros::Time::now(); MoveBaseClient ac2("move_base", true); MoveBaseClient ac0("move_base", true); ros::Rate r(100); ros::NodeHandle n; int flag = 0; int sum = 0; ros::Publisher updown_flag = n.advertise<std_msgs::UInt8>("updown_flag",1); //std_msgs::UInt8 ud_flag; while(ros::ok()) { ROS_INFO("sum \t%d",sum); ROS_INFO("flag \t%d",flag); sum ++; switch(flag) { case 0:{ ROS_INFO("Hooray, the base moved 0 meter forward 0"); //wait for the action server to come up while(!ac.waitForServer(ros::Duration(5.0))){ ROS_INFO("Waiting for the move_base action server to come up"); } goal.target_pose.pose.position.x = 20; goal.target_pose.pose.position.y = 2.1; goal.target_pose.pose.orientation.z = 0; goal.target_pose.pose.orientation.w = 1; ROS_INFO("Sending goal"); ac.sendGoal(goal); ac.waitForResult(); if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { ROS_INFO("Hooray, the base moved 0 meter forward "); //ud_flag.data = 1; //updown_flag.publish(ud_flag); ros::Duration(120).sleep(); //ud_flag.data = 2; //updown_flag.publish(ud_flag); //ros::Duration(23).sleep(); flag = 1; } else ROS_INFO("The base failed to move forward 0 meter for some reason"); break; } case 1:{ //wait for the action server to come up while(!ac.waitForServer(ros::Duration(5.0))){ ROS_INFO("Waiting for the move_base action server to come up"); } goal.target_pose.pose.position.x = 0; goal.target_pose.pose.position.y = 0; goal.target_pose.pose.orientation.z = 0; goal.target_pose.pose.orientation.w = 1; ROS_INFO("Sending goal"); ac.sendGoal(goal); ac.waitForResult(); if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { ROS_INFO("Hooray, the base moved 1 meter forward"); //ud_flag.data = 1; //updown_flag.publish(ud_flag); ros::Duration(2000).sleep(); //ud_flag.data = 2; //updown_flag.publish(ud_flag); //ros::Duration(23).sleep(); flag = 2; } else ROS_INFO("The base failed to move forward 1 meter for some reason"); break; } case 2: { ROS_INFO("Hooray, the base moved 2 meter forward 0"); //wait for the action server to come up while(!ac.waitForServer(ros::Duration(5.0))){ ROS_INFO("Waiting for the move_base action server to come up"); } goal.target_pose.pose.position.x = 0; goal.target_pose.pose.position.y = 0; goal.target_pose.pose.orientation.z = 0; goal.target_pose.pose.orientation.w = 1; ROS_INFO("Sending goal"); ac.sendGoal(goal); ac.waitForResult(); if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED) { ROS_INFO("Hooray, the base moved 2 meter forward"); //ud_flag.data = 1; //updown_flag.publish(ud_flag); ros::Duration(20).sleep(); //ud_flag.data = 2; //updown_flag.publish(ud_flag); //ros::Duration(60).sleep(); flag = 0; } else ROS_INFO("The base failed to move forward 2 meter for some reason"); break; } } } return 0; }