From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- js/xpconnect/wrappers/FilteringWrapper.cpp | 172 +++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 js/xpconnect/wrappers/FilteringWrapper.cpp (limited to 'js/xpconnect/wrappers/FilteringWrapper.cpp') diff --git a/js/xpconnect/wrappers/FilteringWrapper.cpp b/js/xpconnect/wrappers/FilteringWrapper.cpp new file mode 100644 index 0000000000..f4812e04ba --- /dev/null +++ b/js/xpconnect/wrappers/FilteringWrapper.cpp @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "FilteringWrapper.h" +#include "AccessCheck.h" +#include "ChromeObjectWrapper.h" +#include "XrayWrapper.h" +#include "nsJSUtils.h" +#include "mozilla/ErrorResult.h" +#include "xpcpublic.h" +#include "xpcprivate.h" + +#include "jsapi.h" +#include "js/Symbol.h" + +using namespace JS; +using namespace js; + +namespace xpc { + +static JS::SymbolCode sCrossOriginWhitelistedSymbolCodes[] = { + JS::SymbolCode::toStringTag, JS::SymbolCode::hasInstance, + JS::SymbolCode::isConcatSpreadable}; + +static bool IsCrossOriginWhitelistedSymbol(JSContext* cx, JS::HandleId id) { + if (!id.isSymbol()) { + return false; + } + + JS::Symbol* symbol = id.toSymbol(); + for (auto code : sCrossOriginWhitelistedSymbolCodes) { + if (symbol == JS::GetWellKnownSymbol(cx, code)) { + return true; + } + } + + return false; +} + +bool IsCrossOriginWhitelistedProp(JSContext* cx, JS::HandleId id) { + return id == GetJSIDByIndex(cx, XPCJSContext::IDX_THEN) || + IsCrossOriginWhitelistedSymbol(cx, id); +} + +bool AppendCrossOriginWhitelistedPropNames(JSContext* cx, + JS::MutableHandleIdVector props) { + // Add "then" if it's not already in the list. + RootedIdVector thenProp(cx); + if (!thenProp.append(GetJSIDByIndex(cx, XPCJSContext::IDX_THEN))) { + return false; + } + + if (!AppendUnique(cx, props, thenProp)) { + return false; + } + + // Now add the three symbol-named props cross-origin objects have. +#ifdef DEBUG + for (size_t n = 0; n < props.length(); ++n) { + MOZ_ASSERT(!props[n].isSymbol(), "Unexpected existing symbol-name prop"); + } +#endif + if (!props.reserve( + props.length() + + mozilla::ArrayLength(sCrossOriginWhitelistedSymbolCodes))) { + return false; + } + + for (auto code : sCrossOriginWhitelistedSymbolCodes) { + props.infallibleAppend(JS::GetWellKnownSymbolKey(cx, code)); + } + + return true; +} + +// Note: Previously, FilteringWrapper supported complex access policies where +// certain properties on an object were accessible and others weren't. Today, +// the only supported policies are Opaque and OpaqueWithCall, none of which need +// that. So we just stub out the unreachable paths. +template +bool FilteringWrapper::getOwnPropertyDescriptor( + JSContext* cx, HandleObject wrapper, HandleId id, + MutableHandle> desc) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template +bool FilteringWrapper::ownPropertyKeys( + JSContext* cx, HandleObject wrapper, MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template +bool FilteringWrapper::getOwnEnumerablePropertyKeys( + JSContext* cx, HandleObject wrapper, MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template +bool FilteringWrapper::enumerate( + JSContext* cx, HandleObject wrapper, + JS::MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template +bool FilteringWrapper::call(JSContext* cx, + JS::Handle wrapper, + const JS::CallArgs& args) const { + if (!Policy::checkCall(cx, wrapper, args)) { + return false; + } + return Base::call(cx, wrapper, args); +} + +template +bool FilteringWrapper::construct(JSContext* cx, + JS::Handle wrapper, + const JS::CallArgs& args) const { + if (!Policy::checkCall(cx, wrapper, args)) { + return false; + } + return Base::construct(cx, wrapper, args); +} + +template +bool FilteringWrapper::nativeCall( + JSContext* cx, JS::IsAcceptableThis test, JS::NativeImpl impl, + const JS::CallArgs& args) const { + if (Policy::allowNativeCall(cx, test, impl)) { + return Base::Permissive::nativeCall(cx, test, impl, args); + } + return Base::Restrictive::nativeCall(cx, test, impl, args); +} + +template +bool FilteringWrapper::getPrototype( + JSContext* cx, JS::HandleObject wrapper, + JS::MutableHandleObject protop) const { + // Filtering wrappers do not allow access to the prototype. + protop.set(nullptr); + return true; +} + +template +bool FilteringWrapper::enter(JSContext* cx, HandleObject wrapper, + HandleId id, Wrapper::Action act, + bool mayThrow, bool* bp) const { + if (!Policy::check(cx, wrapper, id, act)) { + *bp = + JS_IsExceptionPending(cx) ? false : Policy::deny(cx, act, id, mayThrow); + return false; + } + *bp = true; + return true; +} + +#define NNXOW FilteringWrapper +#define NNXOWC FilteringWrapper + +template <> +const NNXOW NNXOW::singleton(0); +template <> +const NNXOWC NNXOWC::singleton(0); + +template class NNXOW; +template class NNXOWC; +template class ChromeObjectWrapperBase; +} // namespace xpc -- cgit v1.2.3