WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
314526
REGRESSION (
312740@main
): [ASan/TSan] `angle::PoolAllocator` has inconsistent layout across translation units, crashing GPU process on WebGL shader compile
https://bugs.webkit.org/show_bug.cgi?id=314526
Summary
REGRESSION (312740@main): [ASan/TSan] `angle::PoolAllocator` has inconsistent...
David Kilzer (:ddkilzer)
Reported
2026-05-10 21:28:27 PDT
ASan (and TSan) builds of WebKit cause any WebGL shader compile performed in the GPU process to abort with an AddressSanitizer stack-buffer-overflow report in `angle::PoolAllocator::PoolAllocator()`. This is observed across the majority of tests in `LayoutTests/fast/canvas/webgl/` on ASan builds. Stack trace (representative crash thread, from a local ASan build): ``` ==PID==ERROR: AddressSanitizer: stack-buffer-overflow WRITE of size 88 at 0x... thread TN 0 libclang_rt.asan_osx_dynamic.dylib: __asan_memset 1 libANGLE-shared.dylib: angle::PoolAllocator::PoolAllocator() 2 libANGLE-shared.dylib: sh::TCompiler::compile(angle::Span<char const* const>, ShCompileOptions const&) 3 libANGLE-shared.dylib: rx::ShaderTranslateTask::translate(void*, ShCompileOptions const&, std::string const&) 4 libANGLE-shared.dylib: gl::CompileTask::operator()() 5 libANGLE-shared.dylib: angle::UnlockedTailCall::runImpl(void*) 6 WebCore: WebCore::GraphicsContextGLANGLE::compileShader(unsigned int) 7 WebKit: WebKit::RemoteGraphicsContextGL::compileShader(unsigned int) 8 WebKit: WebKit::RemoteGraphicsContextGL::didReceiveStreamMessage(IPC::StreamServerConnection&, IPC::Decoder&) [...] ``` The ASan frame report shows the compiler-allocated stack slot for `scopedAlloc` (a `TScopedPoolAllocator` whose only member is an `angle::PoolAllocator`) is 24 bytes wide, but `angle::PoolAllocator::PoolAllocator()` performs an 88-byte `__asan_memset` to zero-initialize its members. The call writes past the end of the 24-byte slot, corrupting the adjacent ASan redzone and other stack locals. The 88-byte write size comes from the layout `std::vector<Segment> mSingleObjectSegments` + `Span<uint8_t> mCurrentPool` + `std::vector<Segment> mPoolSegments` + `std::vector<Segment> mUnusedSegments`. The 24-byte layout contains only `mSingleObjectSegments`. The three extra vectors are conditionally present under `#if !defined(ANGLE_DISABLE_POOL_ALLOC)` in `Source/ThirdParty/ANGLE/src/common/PoolAlloc.h`. `ANGLE_DISABLE_POOL_ALLOC` is defined at the top of `PoolAlloc.h` based on whether `ANGLE_WITH_ASAN` or `ANGLE_WITH_TSAN` is visible there. Those macros are defined in `common/platform.h` from `__has_feature()`. The `#if defined(ANGLE_WITH_ASAN) || defined(ANGLE_WITH_TSAN)` check in `PoolAlloc.h` runs BEFORE `common/platform.h` is transitively included (via `common/angleutils.h`, further down in the same header). As a result, whether the sanitizer macros are visible at that check depends on which headers the including translation unit already pulled in: * `Source/ThirdParty/ANGLE/src/common/PoolAlloc.cpp` includes `common/PoolAlloc.h` as its first include. At the macro check in `PoolAlloc.h`, `platform.h` has not been processed yet, so `ANGLE_WITH_ASAN` is NOT visible -> `ANGLE_DISABLE_POOL_ALLOC` is NOT defined -> `PoolAllocator` has the 88-byte layout, and the emitted `PoolAllocator::PoolAllocator()` body (defaulted) zero-initializes 88 bytes. * `Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp` (the `sh::TCompiler::compile` caller) includes `compiler/translator/Compiler.h` first, which transitively pulls in `common/platform.h` via `Diagnostics.h`/`SymbolTable.h` BEFORE `PoolAlloc.h` is processed. At the macro check, `ANGLE_WITH_ASAN` IS visible -> `ANGLE_DISABLE_POOL_ALLOC` IS defined -> `PoolAllocator` has the 24-byte layout, and the stack slot for `scopedAlloc.mAllocator` is 24 bytes wide. This is an ODR violation caused by a preprocessor macro check running before the macro-defining header is included. Introduced by
Bug 313441
/
312740@main
, where the `ANGLE_DISABLE_POOL_ALLOC` selection was added at the top of `PoolAlloc.h`. The previous macro selection at the same position (`#if !defined(NDEBUG)`) did not have this failure mode because `NDEBUG` is a standard compiler-provided macro that is visible regardless of include order. Steps to reproduce: 1. Build WebKit for macOS with ASan. 2. Run any WebGL layout test that compiles a shader: `Tools/Scripts/run-webkit-tests --no-build --release --no-timeout --no-show-results fast/canvas/webgl/gl-getshadersource.html` (or any similar test). 3. Observe GPU-process crash with ASan `stack-buffer-overflow` report in `WebKitBuild/Release/layout-test-results/com.apple.WebKit.GPU.Development-*-crash-log.txt`. Binary-level confirmation from `otool -tv` of `libANGLE-shared.dylib` pre-patch shows `angle::PoolAllocator::PoolAllocator()` calling `__asan_memset` with `w2 = #0x58` (88 bytes); consumer translation units allocate only 24 bytes of stack for the corresponding `scopedAlloc`.
Attachments
Add attachment
proposed patch, testcase, etc.
David Kilzer (:ddkilzer)
Comment 1
2026-05-10 21:28:29 PDT
<
rdar://problem/176749270
>
David Kilzer (:ddkilzer)
Comment 2
2026-05-10 21:44:11 PDT
Pull request:
https://github.com/WebKit/WebKit/pull/64653
EWS
Comment 3
2026-05-10 22:33:58 PDT
Committed
312987@main
(346deb2b1c82): <
https://commits.webkit.org/312987@main
> Reviewed commits have been landed. Closing PR #64653 and removing active labels.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug