diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /js/xpconnect/wrappers/FilteringWrapper.cpp | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/xpconnect/wrappers/FilteringWrapper.cpp')
-rw-r--r-- | js/xpconnect/wrappers/FilteringWrapper.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
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 <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::getOwnPropertyDescriptor( + JSContext* cx, HandleObject wrapper, HandleId id, + MutableHandle<mozilla::Maybe<PropertyDescriptor>> desc) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::ownPropertyKeys( + JSContext* cx, HandleObject wrapper, MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::getOwnEnumerablePropertyKeys( + JSContext* cx, HandleObject wrapper, MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::enumerate( + JSContext* cx, HandleObject wrapper, + JS::MutableHandleIdVector props) const { + MOZ_CRASH("FilteringWrappers are now always opaque"); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::call(JSContext* cx, + JS::Handle<JSObject*> wrapper, + const JS::CallArgs& args) const { + if (!Policy::checkCall(cx, wrapper, args)) { + return false; + } + return Base::call(cx, wrapper, args); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::construct(JSContext* cx, + JS::Handle<JSObject*> wrapper, + const JS::CallArgs& args) const { + if (!Policy::checkCall(cx, wrapper, args)) { + return false; + } + return Base::construct(cx, wrapper, args); +} + +template <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::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 <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::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 <typename Base, typename Policy> +bool FilteringWrapper<Base, Policy>::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<CrossCompartmentSecurityWrapper, Opaque> +#define NNXOWC FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall> + +template <> +const NNXOW NNXOW::singleton(0); +template <> +const NNXOWC NNXOWC::singleton(0); + +template class NNXOW; +template class NNXOWC; +template class ChromeObjectWrapperBase; +} // namespace xpc |