skate3recomp-multiplayer/src
andrewnakas ace55528f3 Fix cross-thread use-after-free on WorldPresentation instance teardown
The intermittent map-load crash is heap corruption, not a null pointer.
It surfaces as a store through NULL in sub_8298CEF8 (intrusive list
unlink) reached from sub_82990768 +0x1D8, the guest small-block pool
allocator. Decoded with --protect_zero=true:

  sub_82990768  reads the chunk's free-block list head [chunk+8] and
                gets 0xFFFFFFFF, treats it as a free block, and rounds
                it down to a chunk header:
                ((0xFFFFFFFF+0x7FFF) & 0xFFFF8000) - 0x8000 = 0xFFFF8000
  sub_8298CEF8  node->next/prev at that address read as 0, so
                "next->prev = prev" stores through NULL

So the null store is three steps downstream. The defect is that
0xFFFFFFFF was in the free list at all.

Root cause, caught in the act by a store watch over the pool arena:

  WRITE INTO A FREE BLOCK: guest 0x40D22A6C, 2 bytes, thread "Job Manager"
    = +12 of free block 0x40D22A60 (size 64)
  writer:    sub_82816A40 <- sub_82817138 <- sub_82812A20
             <- sub_8290AFA0 <- sub_8290B750 <- sub_82A412B8
  freed by:  sub_82792040 <- sub_82791FD8 <- sub_82791500 (render_thread)

sub_82791CF8 (under Sk8::WorldPresentation::AddRenderInstance) allocates
two u16 arrays at self+496/+500 and publishes INTERIOR pointers into
them - &A[idx], &B[idx] - into other objects' +64/+68. A job work item
captures one at its +12 and walks it writing 4x u16 records. When
sub_82792040 frees those arrays on render_thread, the job keeps writing
into freed memory. If the block is on the pool's free list, the write
lands on its link word, which is how 0xFFFFFFFF gets there.

The fix, skate3_instance_free_defer_ms (default 0 = off), holds the
arrays freed by that teardown for N ms so a late job write lands on
memory the allocator has not reused. It is bounded by a 512 KB cap, so
a long job latency cannot starve the pool. This is a mitigation: the
root fix is draining or cancelling the outstanding jobs before teardown,
which needs a job-manager drain primitive I could not identify.

Also adds the diagnostics that found it, all default-off: a pool
integrity checker (per-alloc sweep of all 20 size-class bins, poison and
verify of freed blocks, and a check of the link word carried out of a
popped block), and the store watch's host side. The watch needs a
REX_STORE_* hook in the generated header, which is regenerated by
codegen and so is not included here.

Validation is honest but incomplete: 28 runs / 865 map-load events with
the fix on produced no corruption and no crash, but the corruption
occurred only ~2-3 times in ~3900 map-load events without it, so a clean
arm this size has close to even odds by chance. Longer soaks needed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 10:59:09 -06:00
..
native render: recover streaming-revoked guest read faults on linux and macos 2026-07-24 19:03:31 +01:00
exception_compat.cpp add Skate 3 Title Update 3 support 2026-06-10 05:56:35 +01:00
main.cpp macos: name the app bundle and window title skate3recomp 2026-07-24 13:38:01 +01:00
skate3.rc.in build: embed version resources in the windows binaries (SDK bump) 2026-07-24 19:40:48 +01:00
skate3_app.manifest create Skate 3 recompilation project 2026-05-18 23:03:10 +01:00
skate3_app_common.cpp video: use the 2x first-run render scale on macOS too 2026-07-24 13:38:01 +01:00
skate3_app_common.h render: true ultrawide through the native renderer 2026-07-20 00:36:16 +01:00
skate3_demo_path.cpp render: true ultrawide through the native renderer 2026-07-20 00:36:16 +01:00
skate3_demo_path.h render: extended draw distance and world streaming pre-load 2026-07-19 18:24:12 +01:00
skate3_draw_distance.cpp app: unload stream-probe cells before map transitions tear them down 2026-07-24 13:38:01 +01:00
skate3_fov.cpp add ultrawide and live FOV support 2026-06-10 05:56:34 +01:00
skate3_fov.h add ultrawide and live FOV support 2026-06-10 05:56:34 +01:00
skate3_heap_check.cpp Fix cross-thread use-after-free on WorldPresentation instance teardown 2026-08-12 10:59:09 -06:00
skate3_iso_installer.cpp installer: read the ISO install directory before the wizard moves the paths (SDK bump) 2026-07-24 20:47:39 +01:00
skate3_iso_installer.h add macOS build and launch support 2026-06-06 15:15:18 +01:00
skate3_iso_installer_macos.mm add Skate 3 Title Update 3 support 2026-06-10 05:56:35 +01:00
skate3_native_debug_dialog.cpp render: surface the sticky-failure fallback (EMULATED readout, F5 retry, forced-failure debug hook) 2026-07-21 03:31:11 +01:00
skate3_native_debug_dialog.h render: showcase decals/dyn layers, blackout bookends, and hot-rebuild fixes 2026-07-21 02:40:19 +01:00
skate3_native_render.cpp render: recover streaming-revoked guest read faults on linux and macos 2026-07-24 19:03:31 +01:00
skate3_native_render.h debug: frame snapshot harness and offline guest data-model reconstruction 2026-07-02 01:03:49 +01:00
skate3_native_scene.cpp render: recover streaming-revoked guest read faults on linux and macos 2026-07-24 19:03:31 +01:00
skate3_native_scene.h render: stand the static sun shadows down in venues with no sane world lighting capture 2026-07-24 13:38:02 +01:00
skate3_native_scene_gpu.cpp render: declare copy-source usage on the readback source textures 2026-07-24 21:49:05 +01:00
skate3_native_scene_gpu_internal.h render: occlusion-cull statics hidden behind rendered geometry 2026-07-24 13:38:01 +01:00
skate3_native_scene_post.cpp render: declare copy-source usage on the readback source textures 2026-07-24 21:49:05 +01:00
skate3_native_scene_state.h capture: place sort-list batched piece clones with their instance matrix 2026-07-24 13:38:02 +01:00
skate3_screenshot.cpp shading parity program: shader source mirror, A/B capture, offline ucode emulation 2026-07-06 23:23:13 +01:00
skate3_screenshot.h shading parity program: shader source mirror, A/B capture, offline ucode emulation 2026-07-06 23:23:13 +01:00
skate3_shader_disasm.cpp in-world neon spline waypoints, F5 live renderer toggle, F6 screenshots, compass icon fixes 2026-07-05 01:38:10 +01:00
skate3_shader_disasm.h in-world neon spline waypoints, F5 live renderer toggle, F6 screenshots, compass icon fixes 2026-07-05 01:38:10 +01:00
skate3_title_update_installer.cpp installer: adopt the restyled setup wizards 2026-07-19 13:35:54 +01:00
skate3_title_update_installer.h add Skate 3 Title Update 3 support 2026-06-10 05:56:35 +01:00
skate3_ultrawide_guest.h src: include cstddef in headers that use size_t 2026-07-24 13:38:01 +01:00
skate3_user_settings.cpp add user profiles and in-game settings 2026-06-04 15:47:46 +01:00
skate3_user_settings.h add user profiles and in-game settings 2026-06-04 15:47:46 +01:00
skate3_version.h.in add packaging presets and runtime staging 2026-06-04 18:56:43 +01:00
skate3_win_icon.cpp win-icon: no more visible pre-icon duplicate next to the exe 2026-07-17 04:26:56 +01:00
skate3_win_icon.h exe icon from the player's own game files at runtime; close-clone prop jitter fix 2026-07-11 09:29:02 +01:00