[JSC] IPInt fast path for `memory.atomic.wait32`/`wait64` wraps the Memory64 effective address
Every Memory64 load/store in IPInt traps on pointer-overflow. Atomic-wait was the lone holdout — and a pointer near `UINT64_MAX` wraps in-bounds.
Source/JavaScriptCore/llint/InPlaceInterpreter64.asm
IPInt(In-Place Interpreter)는 WebKit의 assembly 수준 WebAssembly bytecode interpreter입니다. Memory64는 Wasm에 완전한 i64 주소 지정 방식을 도입하며, runtime base pointer와 instruction에 인코딩된 static immediate offset이 모두 64비트이므로 두 값의 합은 overflow할 수 있습니다. baddpc 매크로는 carry를 인식하는 덧셈 연산으로, 일반 Memory64 load/store fast path에서 이미 채택된 방식입니다. 덧셈 수행 후 CPU carry flag가 설정되면 _ipint_throw_OutOfBoundsMemoryAccess로 분기합니다.
이 패치는 memory.atomic.wait32와 memory.atomic.wait64의 Memory64 fast path에서 발생하던 silent integer overflow를 수정했습니다. 유효 주소를 계산하는 pointer + offset 연산에 overflow 검사가 없는 addq가 사용되었습니다. 그 결과, UINT64_MAX 근처의 64비트 pointer에 0이 아닌 immediate offset을 더하면 trap이 발생하는 대신 작은 in-bounds 주소로 wrap되었습니다. atomic wait fast path는 baddpc를 적용하지 않은 유일한 Memory64 fast path였습니다. 계산된 주소는 아무런 검사 없이 slow path로 전달되었고, slow path 자체에도 독립적인 overflow 검사가 없었습니다.
Significance
pointer 0xFFFF_FFFF_FFFF_FFF8n에 memory.atomic.wait32 offset=8을 사용하는 Memory64 모듈에서는, 엔진이 주소 0으로 wrap한 뒤 in-bounds로 처리했습니다. 이는 보안에 민감한 fast path에서 OOB bypass primitive를 직접 확보할 수 있는 경우에 해당합니다.
Audit directions
InPlaceInterpreter64.asm의 다른 Memory64 instruction handler. atomic wait handler는 주요 memory access fast path와 별도로 작성된 것으로 보이며,baddpc를 누락한 곳이 이곳만이 아닐 가능성이 있습니다. 파일 전체에서 pointer+offset 계산에 사용된 bareaddq를 검색해야 합니다.- Atomic slow path의 overflow 가정.
ipint_slow_path_memory_atomic_wait32/64에 독립적인 overflow 검출이 없었다는 점은 확인되었습니다. 현재 버전에서 전달받은 주소에 대해 독립적인 bounds check를 수행하는지 확인해야 합니다. wrapped 주소와 정당한 작은 pointer를 구별할 수 없기 때문입니다.