omegafox/patches/webgl-spoofing.patch
2025-04-21 20:41:38 -07:00

394 lines
15 KiB
Diff

diff --git a/dom/canvas/ClientWebGLContext.cpp b/dom/canvas/ClientWebGLContext.cpp
index a1e5c4792d..be99491bf8 100644
--- a/dom/canvas/ClientWebGLContext.cpp
+++ b/dom/canvas/ClientWebGLContext.cpp
@@ -4,6 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ClientWebGLContext.h"
+#include "MaskConfig.hpp"
+#include <algorithm>
+#include <cstddef>
#include <bitset>
@@ -750,6 +753,13 @@ void ClientWebGLContext::SetUnpackColorSpace(
Run<RPROC(SetUnpackColorSpace)>(*mUnpackColorSpace);
}
+bool ClientWebGLContext::MBoolVal(const std::string& key, bool defaultValue) {
+ if (auto value = MaskConfig::GetAttribute<bool>(key, mIsWebGL2);
+ value.has_value())
+ return value.value();
+ return defaultValue;
+}
+
void ClientWebGLContext::GetContextAttributes(
dom::Nullable<dom::WebGLContextAttributes>& retval) {
retval.SetNull();
@@ -760,15 +770,40 @@ void ClientWebGLContext::GetContextAttributes(
const auto& options = mNotLost->info.options;
- result.mAlpha.Construct(options.alpha);
- result.mDepth = options.depth;
- result.mStencil = options.stencil;
- result.mAntialias.Construct(options.antialias);
- result.mPremultipliedAlpha = options.premultipliedAlpha;
- result.mPreserveDrawingBuffer = options.preserveDrawingBuffer;
- result.mFailIfMajorPerformanceCaveat = options.failIfMajorPerformanceCaveat;
- result.mPowerPreference = options.powerPreference;
- result.mForceSoftwareRendering = options.forceSoftwareRendering;
+ result.mAlpha.Construct(MBoolVal("alpha", options.alpha));
+ result.mDepth = MBoolVal("depth", options.depth);
+ result.mStencil = MBoolVal("stencil", options.stencil);
+ result.mAntialias.Construct(MBoolVal("antialias", options.antialias));
+ result.mPremultipliedAlpha = MBoolVal(
+ "webGl:contextAttributes.premultipliedAlpha", options.premultipliedAlpha);
+ result.mPreserveDrawingBuffer =
+ MBoolVal("preserveDrawingBuffer", options.preserveDrawingBuffer);
+ result.mFailIfMajorPerformanceCaveat = MBoolVal(
+ "failIfMajorPerformanceCaveat", options.failIfMajorPerformanceCaveat);
+ if (auto value =
+ MaskConfig::GetAttribute<std::string>("powerPreference", mIsWebGL2);
+ value.has_value()) {
+ // Convert to enum
+ switch (value.value()[0]) {
+ case 'd':
+ result.mPowerPreference = dom::WebGLPowerPreference::Default;
+ break;
+ case 'l':
+ result.mPowerPreference = dom::WebGLPowerPreference::Low_power;
+ break;
+ case 'h':
+ result.mPowerPreference = dom::WebGLPowerPreference::High_performance;
+ break;
+ default:
+ // Invalid value
+ result.mPowerPreference = options.powerPreference;
+ break;
+ }
+ } else {
+ result.mPowerPreference = options.powerPreference;
+ }
+ result.mForceSoftwareRendering = MBoolVal(
+ "forceSoftwareRendering", options.forceSoftwareRendering);
}
// -----------------------
@@ -986,18 +1021,28 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
std::unordered_map<GLenum, bool> webgl::MakeIsEnabledMap(const bool webgl2) {
auto ret = std::unordered_map<GLenum, bool>{};
- ret[LOCAL_GL_BLEND] = false;
- ret[LOCAL_GL_CULL_FACE] = false;
- ret[LOCAL_GL_DEPTH_TEST] = false;
- ret[LOCAL_GL_DITHER] = true;
- ret[LOCAL_GL_POLYGON_OFFSET_FILL] = false;
- ret[LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE] = false;
- ret[LOCAL_GL_SAMPLE_COVERAGE] = false;
- ret[LOCAL_GL_SCISSOR_TEST] = false;
- ret[LOCAL_GL_STENCIL_TEST] = false;
+ ret[LOCAL_GL_BLEND] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_BLEND, false, webgl2);
+ ret[LOCAL_GL_CULL_FACE] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_CULL_FACE, false, webgl2);
+ ret[LOCAL_GL_DEPTH_TEST] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_DEPTH_TEST, false, webgl2);
+ ret[LOCAL_GL_DITHER] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_DITHER, true, webgl2);
+ ret[LOCAL_GL_POLYGON_OFFSET_FILL] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_POLYGON_OFFSET_FILL, false, webgl2);
+ ret[LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE] = MaskConfig::MParamGL<bool>(
+ LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false, webgl2);
+ ret[LOCAL_GL_SAMPLE_COVERAGE] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_SAMPLE_COVERAGE, false, webgl2);
+ ret[LOCAL_GL_SCISSOR_TEST] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_SCISSOR_TEST, false, webgl2);
+ ret[LOCAL_GL_STENCIL_TEST] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_STENCIL_TEST, false, webgl2);
if (webgl2) {
- ret[LOCAL_GL_RASTERIZER_DISCARD] = false;
+ ret[LOCAL_GL_RASTERIZER_DISCARD] =
+ MaskConfig::MParamGL<bool>(LOCAL_GL_RASTERIZER_DISCARD, false, webgl2);
}
return ret;
@@ -2066,6 +2111,57 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
const auto& state = State();
// -
+ std::optional<
+ std::variant<int64_t, bool, double, std::string, std::nullptr_t>>
+ data;
+ data = MaskConfig::GLParam(pname, mIsWebGL2);
+
+ if (data.has_value()) {
+ const auto& value = data.value();
+ if (std::holds_alternative<int64_t>(value)) {
+ retval.set(JS::NumberValue(double(std::get<int64_t>(value))));
+ return;
+ }
+ if (std::holds_alternative<double>(value)) {
+ retval.set(JS::NumberValue(std::get<double>(value)));
+ return;
+ }
+ if (std::holds_alternative<bool>(value)) {
+ retval.set(JS::BooleanValue(std::get<bool>(value)));
+ return;
+ }
+ if (std::holds_alternative<std::string>(value)) {
+ retval.set(StringValue(cx, std::get<std::string>(value), rv));
+ return;
+ }
+ if (std::holds_alternative<std::nullptr_t>(value)) {
+ retval.set(JS::NullValue());
+ return;
+ }
+ }
+ // If the value is not array (we will handle those later),
+ // then check if it should be blocked.
+ switch (pname) {
+ case LOCAL_GL_DEPTH_RANGE:
+ case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
+ case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE:
+ case LOCAL_GL_COLOR_CLEAR_VALUE:
+ case LOCAL_GL_BLEND_COLOR:
+ case LOCAL_GL_MAX_VIEWPORT_DIMS:
+ case LOCAL_GL_SCISSOR_BOX:
+ case LOCAL_GL_VIEWPORT:
+ case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS:
+ case LOCAL_GL_COLOR_WRITEMASK:
+ case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_RENDERER_WEBGL:
+ case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_VENDOR_WEBGL:
+ break;
+ default:
+ if (MaskConfig::CheckBool(mIsWebGL2 ? "webGl2:parameters:blockIfNotDefined"
+ : "webGl:parameters:blockIfNotDefined")) {
+ retval.set(JS::NullValue());
+ return;
+ }
+ }
const auto fnSetRetval_Buffer = [&](const GLenum target) {
const auto buffer = *MaybeFind(state.mBoundBufferByTarget, target);
@@ -2171,49 +2267,84 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
// 2 floats
case LOCAL_GL_DEPTH_RANGE:
- retval.set(Create<dom::Float32Array>(cx, this, state.mDepthRange, rv));
+ retval.set(Create<dom::Float32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<float, 2UL>>(pname, state.mDepthRange,
+ mIsWebGL2),
+ rv));
return;
case LOCAL_GL_ALIASED_POINT_SIZE_RANGE:
- retval.set(
- Create<dom::Float32Array>(cx, this, limits.pointSizeRange, rv));
+ retval.set(Create<dom::Float32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<float, 2UL>>(
+ pname, limits.pointSizeRange, mIsWebGL2),
+ rv));
return;
case LOCAL_GL_ALIASED_LINE_WIDTH_RANGE:
- retval.set(
- Create<dom::Float32Array>(cx, this, limits.lineWidthRange, rv));
+ retval.set(Create<dom::Float32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<float, 2UL>>(
+ pname, limits.lineWidthRange, mIsWebGL2),
+ rv));
return;
// 4 floats
case LOCAL_GL_COLOR_CLEAR_VALUE:
- retval.set(Create<dom::Float32Array>(cx, this, state.mClearColor, rv));
+ retval.set(Create<dom::Float32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<float, 4UL>>(pname, state.mClearColor,
+ mIsWebGL2),
+ rv));
return;
case LOCAL_GL_BLEND_COLOR:
- retval.set(Create<dom::Float32Array>(cx, this, state.mBlendColor, rv));
+ retval.set(Create<dom::Float32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<float, 4UL>>(pname, state.mBlendColor,
+ mIsWebGL2),
+ rv));
return;
// 2 ints
case LOCAL_GL_MAX_VIEWPORT_DIMS: {
auto maxViewportDim = BitwiseCast<int32_t>(limits.maxViewportDim);
const auto dims = std::array<int32_t, 2>{maxViewportDim, maxViewportDim};
- retval.set(Create<dom::Int32Array>(cx, this, dims, rv));
+ retval.set(Create<dom::Int32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<int32_t, 2UL>>(pname, dims,
+ mIsWebGL2),
+ rv));
return;
}
// 4 ints
case LOCAL_GL_SCISSOR_BOX:
- retval.set(Create<dom::Int32Array>(cx, this, state.mScissor, rv));
+ retval.set(Create<dom::Int32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<int32_t, 4UL>>(pname, state.mScissor,
+ mIsWebGL2),
+ rv));
return;
case LOCAL_GL_VIEWPORT:
- retval.set(Create<dom::Int32Array>(cx, this, state.mViewport, rv));
+ retval.set(Create<dom::Int32Array>(
+ cx, this,
+ MaskConfig::MParamGL<std::array<int32_t, 4UL>>(pname, state.mViewport,
+ mIsWebGL2),
+ rv));
return;
- // any
case LOCAL_GL_COMPRESSED_TEXTURE_FORMATS:
- retval.set(Create<dom::Uint32Array>(cx, this,
- state.mCompressedTextureFormats, rv));
+ std::vector<uint32_t> compressedTextureUint32(
+ state.mCompressedTextureFormats.begin(),
+ state.mCompressedTextureFormats.end());
+ retval.set(Create<dom::Uint32Array>(
+ cx, this,
+ MaskConfig::MParamGLVector<uint32_t>(pname, compressedTextureUint32,
+ mIsWebGL2),
+ rv));
return;
}
@@ -2393,6 +2524,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
switch (pname) {
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_RENDERER_WEBGL:
+ if (auto value = MaskConfig::GetString("webGl:renderer")) {
+ ret = Some(value.value());
+ break;
+ }
ret = GetUnmaskedRenderer();
if (ret && StaticPrefs::webgl_sanitize_unmasked_renderer()) {
*ret = webgl::SanitizeRenderer(*ret);
@@ -2400,6 +2535,10 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
break;
case dom::WEBGL_debug_renderer_info_Binding::UNMASKED_VENDOR_WEBGL:
+ if (auto value = MaskConfig::GetString("webGl:vendor")) {
+ ret = Some(value.value());
+ break;
+ }
ret = GetUnmaskedVendor();
break;
@@ -2490,7 +2629,9 @@ void ClientWebGLContext::GetParameter(JSContext* cx, GLenum pname,
case LOCAL_GL_COLOR_WRITEMASK: {
const auto mask = uint8_t(*maybe);
const auto bs = std::bitset<4>(mask);
- const auto src = std::array<bool, 4>{bs[0], bs[1], bs[2], bs[3]};
+ const auto src = MaskConfig::MParamGL<std::array<bool, 4>>(
+ pname, std::array<bool, 4>{bs[0], bs[1], bs[2], bs[3]},
+ mIsWebGL2);
JS::Rooted<JS::Value> arr(cx);
if (!dom::ToJSValue(cx, src.data(), src.size(), &arr)) {
rv = NS_ERROR_OUT_OF_MEMORY;
@@ -2873,6 +3014,24 @@ ClientWebGLContext::GetShaderPrecisionFormat(const GLenum shadertype,
const GLenum precisiontype) {
if (IsContextLost()) return nullptr;
const auto info = [&]() {
+ // Check for spoofed value
+ if (auto value =
+ MaskConfig::MShaderData(shadertype, precisiontype, mIsWebGL2)) {
+ const auto& format = value.value();
+ return Some(webgl::ShaderPrecisionFormat{
+ format[0], // rangeMin
+ format[1], // rangeMax
+ format[2] // precision
+ });
+ }
+ // Check if block if not defined is on
+ if (MaskConfig::CheckBool(
+ mIsWebGL2 ? "webGl2:shaderPrecisionFormats:blockIfNotDefined"
+ : "webGl:shaderPrecisionFormats:blockIfNotDefined")) {
+ Maybe<webgl::ShaderPrecisionFormat> ret;
+ return ret;
+ }
+
const auto& inProcess = mNotLost->inProcess;
if (inProcess) {
return inProcess->GetShaderPrecisionFormat(shadertype, precisiontype);
@@ -5853,6 +6012,17 @@ bool ClientWebGLContext::IsSupported(const WebGLExtensionID ext,
return false;
}
+ if (std::vector<std::string> maskValues =
+ MaskConfig::GetStringList(mIsWebGL2 ? "webGl2:supportedExtensions"
+ : "webGl:supportedExtensions");
+ !maskValues.empty()) {
+ if (std::find(maskValues.begin(), maskValues.end(),
+ GetExtensionName(ext)) != maskValues.end()) {
+ return true;
+ }
+ return false;
+ }
+
const auto& limits = Limits();
return limits.supportedExtensions[ext];
}
@@ -5864,6 +6034,18 @@ void ClientWebGLContext::GetSupportedExtensions(
if (!mNotLost) return;
auto& retarr = retval.SetValue();
+
+ // Implement separately to prevent O(n^2) timing
+ if (std::vector<std::string> maskValues =
+ MaskConfig::GetStringList(mIsWebGL2 ? "webGl2:supportedExtensions"
+ : "webGl:supportedExtensions");
+ !maskValues.empty()) {
+ for (const auto& ext : maskValues) {
+ retarr.AppendElement(NS_ConvertUTF8toUTF16(ext));
+ }
+ return;
+ }
+
for (const auto i : MakeEnumeratedRange(WebGLExtensionID::Max)) {
if (!IsSupported(i, callerType)) continue;
diff --git a/dom/canvas/ClientWebGLContext.h b/dom/canvas/ClientWebGLContext.h
index 62957ee445..dfb2b8ff53 100644
--- a/dom/canvas/ClientWebGLContext.h
+++ b/dom/canvas/ClientWebGLContext.h
@@ -1074,6 +1074,9 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
// -
+ // Helper to get booleans set in MaskConfig
+ bool MBoolVal(const std::string& key, bool defaultValue);
+
void GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval);
private:
diff --git a/dom/canvas/moz.build b/dom/canvas/moz.build
index 3a533d36d1..41d74d9b3f 100644
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -221,3 +221,6 @@ if CONFIG["CC_TYPE"] == "gcc":
# Add libFuzzer configuration directives
include("/tools/fuzzing/libfuzzer-config.mozbuild")
+
+# DOM Mask
+LOCAL_INCLUDES += ["/omegacfg"]
\ No newline at end of file