CVE-2024-40776
Overview
Advisory: Apple Security Advisory
Impact:
Description: Processing maliciously crafted web content may lead to an unexpected process crash
Researchers: Huang Xilin of Ant Group Light-Year Security Lab
| Attribute | Value |
|---|---|
| CVE | CVE-2024-40776 |
| Bugzilla | 273176 |
| Component | WebKit |
| Bug Class | UAF |
| Severity | medium |
| Commit | d86fef64a7c35672… |
| Advisory | Apple Advisory |
Root Cause Analysis
A use-after-free issue was addressed with improved memory management.
Files Changed
Source Files
Source/WebGPU/WGSL/AST/ASTCallExpression.hSource/WebGPU/WGSL/GlobalVariableRewriter.cpp
Patch Preview
diff --git a/Source/WebGPU/WGSL/AST/ASTCallExpression.h b/Source/WebGPU/WGSL/AST/ASTCallExpression.h
index 7abadd2d3217..0a85ce277959 100644
--- a/Source/WebGPU/WGSL/AST/ASTCallExpression.h
+++ b/Source/WebGPU/WGSL/AST/ASTCallExpression.h
@@ -28,6 +28,7 @@
#include "ASTExpression.h"
namespace WGSL {
+class RewriteGlobalVariables;
class TypeChecker;
namespace AST {
@@ -39,6 +40,7 @@ namespace AST {
class CallExpression final : public Expression {
WGSL_AST_BUILDER_NODE(CallExpression);
+ friend RewriteGlobalVariables;
friend TypeChecker;
public:
diff --git a/Source/WebGPU/WGSL/GlobalVariableRewriter.cpp b/Source/WebGPU/WGSL/GlobalVariableRewriter.cpp
index edf73a1f6ce9..4dd9180b9f04 100644
--- a/Source/WebGPU/WGSL/GlobalVariableRewriter.cpp
+++ b/Source/WebGPU/WGSL/GlobalVariableRewriter.cpp
@@ -114,13 +114,12 @@ class RewriteGlobalVariables : public AST::Visitor {
AST::Expression& bufferLengthType();
AST::Expression& bufferLengthReferenceType();
- // atomics
- void initializeAtomics(AST::Function&, const UsedPrivateGlobals&, size_t);
+ // zero initialization
+ void initializeVariables(AST::Function&, const UsedPrivateGlobals&, size_t);
void insertWorkgroupBarrier(AST::Function&, size_t);
AST::Identifier& findOrInsertLocalInvocationIndex(AST::Function&);
- AST::Statement::List atomicStoreInitialValue(const UsedPrivateGlobals&);
- void atomicStoreInitialValue(AST::Expression&, AST::Statement::List&, unsigned);
- bool containsAtomic(const Type*);
+ AST::Statement::List storeInitialValue(const UsedPrivateGlobals&);
+ void storeInitialValue(AST::Expression&, AST::Statement::List&, unsigned, bool isNested);
void packResource(AST::Variable&);
void packArrayResource(AST::Variable&, const Types::Array*);
@@ -1415,12 +1414,12 @@ void RewriteGlobalVariables::insertLocalDefinitions(AST::Function& function, con
}
auto offset = function.body().statements().size() - initialBodySize;
- initializeAtomics(function, usedPrivateGlobals, offset);
+ initializeVariables(function, usedPrivateGlobals, offset);
}
-void RewriteGlobalVariables::initializeAtomics(AST::Function& function, const UsedPrivateGlobals& globals, size_t offset)
+void RewriteGlobalVariables::initializeVariables(AST::Function& function, const UsedPrivateGlobals& globals, size_t offset)
{
- auto initializations = atomicStoreInitialValue(globals);
+ auto initializations = storeInitialValue(globals);
if (initializations.isEmpty())
return;
@@ -1511,43 +1510,53 @@ AST::Identifier& RewriteGlobalVariables::findOrInsertLocalInvocationIndex(AST::F
return parameter.name();
}
-AST::Statement::List RewriteGlobalVariables::atomicStoreInitialValue(const UsedPrivateGlobals& globals)
+AST::Statement::List RewriteGlobalVariables::storeInitialValue(const UsedPrivateGlobals& globals)
{
AST::Statement::List statements;
for (auto* global : globals) {
auto& variable = *global->declaration;
- auto* type = variable.storeType();
- if (!containsAtomic(type))
+
+ if (auto addressSpace = variable.addressSpace(); !addressSpace.has_value() || *addressSpace != AddressSpace::Workgroup)
continue;
+ auto* type = variable.storeType();
auto& target = m_callGraph.ast().astBuilder().construct<AST::IdentifierExpression>(
SourceSpan::empty(),
AST::Identifier::make(variable.name().id())
);
target.m_inferredType = type;
- atomicStoreInitialValue(target, statements, 0);
+ storeInitialValue(target, statements, 0, false);
}
return statements;
}
-bool RewriteGlobalVariables::containsAtomic(const Type* type)
+void RewriteGlobalVariables::storeInitialValue(AST::Expression& target, AST::Statement::List& statements, unsigned arrayDepth, bool isNested)
{
- if (std::holds_alternative<Types::Atomic>(*type))
- return true;
- if (auto* arrayType = std::get_if<Types::Array>(type))
- return containsAtomic(arrayType->element);
- if (auto* structType = std::get_if<Types::Struct>(type)) {
- for (const auto& [_, fieldType] : structType->fields) {
- if (containsAtomic(fieldType))
- return true;
- }
- return false;
- }