← All issues

[15] ANGLE Metal: zero-init return for functions missing return statements

Severity: Medium | Component: ANGLE MSL translator | e539895

Rated Medium because the observable effect is garbage memory ... written to the framebuffer per the commit message, reachable from any web origin via WebGL2 and readPixels; the leak is passive (attacker observes but does not choose) and bounded by what Metal's compiler leaves in the return slot in practice.

Source/ThirdParty/ANGLE/src/compiler/translator/msl/TranslatorMSL.cpp

+#include "compiler/translator/tree_ops/AddDefaultReturnStatements.h"
...
+ if (!sh::AddDefaultReturnStatements(this, root))
+ return false;
+
if (!WrapMain(*this, idGen, *root))
return false;

The AddDefaultReturnStatements tree-op pass (previously HLSL-only) is moved from tree_ops/hlsl/ to the common tree_ops/ folder and invoked as the first transformation in TranslatorMSL::translateImpl(), before WrapMain. Two WebGL2 regression tests verify zero-init for vector and struct return types when GLSL functions fall off the end without an explicit return.

Failure to normalize GLSL's permissive end-of-function semantics to MSL's stricter rules, leaving a backend-specific undefined-behavior path that surfaces uninitialized GPU-thread memory.

ANGLE translates WebGL's GLSL ES sources to platform-native shading languages — HLSL, MSL, SPIR-V. GLSL ES allows non-void functions to lack a guaranteed return on every control-flow path; reaching the end is permitted and yields an unspecified value. MSL treats falling off the end of a non-void function as undefined behaviour — the Metal compiler may emit code that returns whatever lives in the return register/stack slot. AddDefaultReturnStatements walks the AST and appends a zero-initialised return to any function body whose final statement is not a return.

When a fragment shader's helper function takes the no-return branch and the caller writes the result to gl_FragColor, the framebuffer pixel ends up containing residual stack/register contents from the GPU thread.

🔒

Examines how a permissive corner of the GLSL spec turns into a content-observable framebuffer leak when crossed into a stricter shading language

Subscribe to read more

🔒

Multiple reusable audit patterns identified across ANGLE's per-backend translator passes, with concrete starting points for divergence-driven variant discovery

Subscribe to read more