Skip to content

feat(libSceAddressSanitizer): run the module as a passthrough runtime - #16462

Closed
QW1CKS wants to merge 1 commit into
boykopovar:mainfrom
QW1CKS:feat/libSce-address-sanitizer-passthrough
Closed

QW1CKS wants to merge 1 commit into
boykopovar:mainfrom
QW1CKS:feat/libSce-address-sanitizer-passthrough

Conversation

@QW1CKS

@QW1CKS QW1CKS commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

What

libSceAddressSanitizer declared 301 exports and every one of them threw, so a title that imports an instrumented runtime failed at import resolution instead of starting. The module now carries a real passthrough runtime.

The allocator (__asan_malloc, __asan_calloc, __asan_realloc, __asan_memalign, __asan_aligned_alloc, __asan_posix_memalign, __asan_reallocalign, __asan_free, __asan_malloc_usable_size) and __asan_memcpy, __asan_memmove and __asan_memset forward to the guest libc entry points, so the module and the title share one heap and either can free the other's pointer. The report family records the address, access type, size and expected value and calls the callback set by __asan_set_error_report_callback. The UBSan _abort handlers call abort() as the compiler expects; the rest let execution continue. __asan_init, the global, elf and image registration calls, the coverage guard init and the fiber switch calls keep the state the runtime reports.

It does not implement shadow memory. That is the passthrough model agreed in #12063: reserving the 124 GiB shadow of the guest arena would change the guest memory map, which is a memory-layout change rather than a library one. So no load or store is checked, no allocation carries a redzone and there is no quarantine, which means heap-buffer-overflow, use-after-free, double-free, stack-buffer-overflow, global-buffer-overflow and container-overflow go unreported. The debt entry names each of those, and the 19 exports whose prototype or data-object shape is not established still throw.

This closes no issue. It is section 1 of #12063; sections 2 to 4 of that issue (the Psml NIDs, the LoginDialog parameter layout and the list of exports that throw where Kyty has a body) are untouched, so the checklist line is Fixes: none rather than closing it.

tools/progress.py: 29.44% → 30.18%, 282 of 301 implemented.

Tested

Ubuntu 24.04 (Codespace), GCC 13.3, CMake 3.28, Release, -DBUILD_TESTING=ON, full build.

  • ctest -R '^guest_address_sanitizer$' passes. The test registers the guest heap, then exercises allocation, reallocation and free across the module, the alignment entry points, the three memory calls, the unaligned load and store helpers, the pointer comparison helpers, every no-op check and poison call, the report recording and callback, the fiber and coverage state, the symbolizer and contiguous-container calls, and every non-aborting UBSan handler.
  • Red on main: the same test binary with main's library linked instead aborts in __asan_report_present not implemented.
  • python3 tools/check_conventions.py --base upstream/main passes.
  • The NID patch step reports OK and the patched library defines 301 exports with no name left unpatched.
  • Not run: Windows and macOS builds, and any title. No title is known to import this module, so nothing was executed against one, and the console's behaviour for a report that this model returns from instead of ending the process is unverified.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

Every export threw, so an instrumented title failed at import resolution. The
allocator and the three memory calls forward to the guest libc entry points in
prx/libc/src/FileAndHeap.cpp and the rest implement the no-shadow model that
compiler-rt's asan_interface.h describes, with every gap listed in the debt file.
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown

Progress report (bb606f9 → e4ecb48)

📈 System libraries: 30.73% (+0.75%, +282 implemented functions)

✅ 282 implemented
Library Name
libSceAddressSanitizer __asan_addr_is_in_fake_stack
libSceAddressSanitizer __asan_address_is_poisoned
libSceAddressSanitizer __asan_after_dynamic_init
libSceAddressSanitizer __asan_aligned_alloc
libSceAddressSanitizer __asan_alloca_poison
libSceAddressSanitizer __asan_allocas_unpoison
libSceAddressSanitizer __asan_before_dynamic_init
libSceAddressSanitizer __asan_calloc
libSceAddressSanitizer __asan_describe_address
libSceAddressSanitizer __asan_exp_load1
libSceAddressSanitizer __asan_exp_load16
libSceAddressSanitizer __asan_exp_load16_noabort
libSceAddressSanitizer __asan_exp_load1_noabort
libSceAddressSanitizer __asan_exp_load2
libSceAddressSanitizer __asan_exp_load2_noabort
libSceAddressSanitizer __asan_exp_load4
libSceAddressSanitizer __asan_exp_load4_noabort
libSceAddressSanitizer __asan_exp_load8
libSceAddressSanitizer __asan_exp_load8_noabort
libSceAddressSanitizer __asan_exp_loadN
libSceAddressSanitizer __asan_exp_loadN_noabort
libSceAddressSanitizer __asan_exp_store1
libSceAddressSanitizer __asan_exp_store16
libSceAddressSanitizer __asan_exp_store16_noabort
libSceAddressSanitizer __asan_exp_store1_noabort
libSceAddressSanitizer __asan_exp_store2
libSceAddressSanitizer __asan_exp_store2_noabort
libSceAddressSanitizer __asan_exp_store4
libSceAddressSanitizer __asan_exp_store4_noabort
libSceAddressSanitizer __asan_exp_store8
libSceAddressSanitizer __asan_exp_store8_noabort
libSceAddressSanitizer __asan_exp_storeN
libSceAddressSanitizer __asan_exp_storeN_noabort
libSceAddressSanitizer __asan_free
libSceAddressSanitizer __asan_get_current_fake_stack
libSceAddressSanitizer __asan_get_report_access_size
libSceAddressSanitizer __asan_get_report_access_type
libSceAddressSanitizer __asan_get_report_address
libSceAddressSanitizer __asan_get_report_bp
libSceAddressSanitizer __asan_get_report_description
libSceAddressSanitizer __asan_get_report_pc
libSceAddressSanitizer __asan_get_report_sp
libSceAddressSanitizer __asan_handle_no_return
libSceAddressSanitizer __asan_init
libSceAddressSanitizer __asan_init_v5
libSceAddressSanitizer __asan_load1
libSceAddressSanitizer __asan_load16
libSceAddressSanitizer __asan_load16_noabort
libSceAddressSanitizer __asan_load1_noabort
libSceAddressSanitizer __asan_load2
libSceAddressSanitizer __asan_load2_noabort
libSceAddressSanitizer __asan_load4
libSceAddressSanitizer __asan_load4_noabort
libSceAddressSanitizer __asan_load8
libSceAddressSanitizer __asan_load8_noabort
libSceAddressSanitizer __asan_loadN
libSceAddressSanitizer __asan_loadN_noabort
libSceAddressSanitizer __asan_load_cxx_array_cookie
libSceAddressSanitizer __asan_locate_address
libSceAddressSanitizer __asan_malloc
libSceAddressSanitizer __asan_malloc_stats
libSceAddressSanitizer __asan_malloc_usable_size
libSceAddressSanitizer __asan_memalign
libSceAddressSanitizer __asan_memcpy
libSceAddressSanitizer __asan_memmove
libSceAddressSanitizer __asan_memset
libSceAddressSanitizer __asan_poison_cxx_array_cookie
libSceAddressSanitizer __asan_poison_intra_object_redzone
libSceAddressSanitizer __asan_poison_memory_region
libSceAddressSanitizer __asan_poison_stack_memory
libSceAddressSanitizer __asan_posix_memalign
libSceAddressSanitizer __asan_print_accumulated_stats
libSceAddressSanitizer __asan_realloc
libSceAddressSanitizer __asan_reallocalign
libSceAddressSanitizer __asan_region_is_poisoned
libSceAddressSanitizer __asan_register_elf_globals
libSceAddressSanitizer __asan_register_globals
libSceAddressSanitizer __asan_register_image_globals
libSceAddressSanitizer __asan_report_error
libSceAddressSanitizer __asan_report_exp_load1
libSceAddressSanitizer __asan_report_exp_load16
libSceAddressSanitizer __asan_report_exp_load16_noabort
libSceAddressSanitizer __asan_report_exp_load1_noabort
libSceAddressSanitizer __asan_report_exp_load2
libSceAddressSanitizer __asan_report_exp_load2_noabort
libSceAddressSanitizer __asan_report_exp_load4
libSceAddressSanitizer __asan_report_exp_load4_noabort
libSceAddressSanitizer __asan_report_exp_load8
libSceAddressSanitizer __asan_report_exp_load8_noabort
libSceAddressSanitizer __asan_report_exp_load_n
libSceAddressSanitizer __asan_report_exp_load_n_noabort
libSceAddressSanitizer __asan_report_exp_store1
libSceAddressSanitizer __asan_report_exp_store16
libSceAddressSanitizer __asan_report_exp_store16_noabort
libSceAddressSanitizer __asan_report_exp_store1_noabort
libSceAddressSanitizer __asan_report_exp_store2
libSceAddressSanitizer __asan_report_exp_store2_noabort
libSceAddressSanitizer __asan_report_exp_store4
libSceAddressSanitizer __asan_report_exp_store4_noabort
libSceAddressSanitizer __asan_report_exp_store8
... 182 more
⚪ 153 behaviourally empty (constant return or throw)
Library Name
libSceAddressSanitizer __asan_address_is_poisoned
libSceAddressSanitizer __asan_alloca_poison
libSceAddressSanitizer __asan_allocas_unpoison
libSceAddressSanitizer __asan_describe_address
libSceAddressSanitizer __asan_exp_load1
libSceAddressSanitizer __asan_exp_load16
libSceAddressSanitizer __asan_exp_load16_noabort
libSceAddressSanitizer __asan_exp_load1_noabort
libSceAddressSanitizer __asan_exp_load2
libSceAddressSanitizer __asan_exp_load2_noabort
libSceAddressSanitizer __asan_exp_load4
libSceAddressSanitizer __asan_exp_load4_noabort
libSceAddressSanitizer __asan_exp_load8
libSceAddressSanitizer __asan_exp_load8_noabort
libSceAddressSanitizer __asan_exp_loadN
libSceAddressSanitizer __asan_exp_loadN_noabort
libSceAddressSanitizer __asan_exp_store1
libSceAddressSanitizer __asan_exp_store16
libSceAddressSanitizer __asan_exp_store16_noabort
libSceAddressSanitizer __asan_exp_store1_noabort
libSceAddressSanitizer __asan_exp_store2
libSceAddressSanitizer __asan_exp_store2_noabort
libSceAddressSanitizer __asan_exp_store4
libSceAddressSanitizer __asan_exp_store4_noabort
libSceAddressSanitizer __asan_exp_store8
libSceAddressSanitizer __asan_exp_store8_noabort
libSceAddressSanitizer __asan_exp_storeN
libSceAddressSanitizer __asan_exp_storeN_noabort
libSceAddressSanitizer __asan_get_current_fake_stack
libSceAddressSanitizer __asan_handle_no_return
libSceAddressSanitizer __asan_load1
libSceAddressSanitizer __asan_load16
libSceAddressSanitizer __asan_load16_noabort
libSceAddressSanitizer __asan_load1_noabort
libSceAddressSanitizer __asan_load2
libSceAddressSanitizer __asan_load2_noabort
libSceAddressSanitizer __asan_load4
libSceAddressSanitizer __asan_load4_noabort
libSceAddressSanitizer __asan_load8
libSceAddressSanitizer __asan_load8_noabort
libSceAddressSanitizer __asan_loadN
libSceAddressSanitizer __asan_loadN_noabort
libSceAddressSanitizer __asan_malloc_stats
libSceAddressSanitizer __asan_poison_cxx_array_cookie
libSceAddressSanitizer __asan_poison_intra_object_redzone
libSceAddressSanitizer __asan_poison_memory_region
libSceAddressSanitizer __asan_poison_stack_memory
libSceAddressSanitizer __asan_print_accumulated_stats
libSceAddressSanitizer __asan_region_is_poisoned
libSceAddressSanitizer __asan_set_shadow_00
libSceAddressSanitizer __asan_set_shadow_01
libSceAddressSanitizer __asan_set_shadow_02
libSceAddressSanitizer __asan_set_shadow_03
libSceAddressSanitizer __asan_set_shadow_04
libSceAddressSanitizer __asan_set_shadow_05
libSceAddressSanitizer __asan_set_shadow_06
libSceAddressSanitizer __asan_set_shadow_07
libSceAddressSanitizer __asan_set_shadow_f1
libSceAddressSanitizer __asan_set_shadow_f2
libSceAddressSanitizer __asan_set_shadow_f3
libSceAddressSanitizer __asan_set_shadow_f5
libSceAddressSanitizer __asan_set_shadow_f8
libSceAddressSanitizer __asan_stack_free_0
libSceAddressSanitizer __asan_stack_free_1
libSceAddressSanitizer __asan_stack_free_10
libSceAddressSanitizer __asan_stack_free_2
libSceAddressSanitizer __asan_stack_free_3
libSceAddressSanitizer __asan_stack_free_4
libSceAddressSanitizer __asan_stack_free_5
libSceAddressSanitizer __asan_stack_free_6
libSceAddressSanitizer __asan_stack_free_7
libSceAddressSanitizer __asan_stack_free_8
libSceAddressSanitizer __asan_stack_free_9
libSceAddressSanitizer __asan_stack_malloc_0
libSceAddressSanitizer __asan_stack_malloc_1
libSceAddressSanitizer __asan_stack_malloc_10
libSceAddressSanitizer __asan_stack_malloc_2
libSceAddressSanitizer __asan_stack_malloc_3
libSceAddressSanitizer __asan_stack_malloc_4
libSceAddressSanitizer __asan_stack_malloc_5
libSceAddressSanitizer __asan_stack_malloc_6
libSceAddressSanitizer __asan_stack_malloc_7
libSceAddressSanitizer __asan_stack_malloc_8
libSceAddressSanitizer __asan_stack_malloc_9
libSceAddressSanitizer __asan_stack_malloc_always_0
libSceAddressSanitizer __asan_stack_malloc_always_1
libSceAddressSanitizer __asan_stack_malloc_always_10
libSceAddressSanitizer __asan_stack_malloc_always_2
libSceAddressSanitizer __asan_stack_malloc_always_3
libSceAddressSanitizer __asan_stack_malloc_always_4
libSceAddressSanitizer __asan_stack_malloc_always_5
libSceAddressSanitizer __asan_stack_malloc_always_6
libSceAddressSanitizer __asan_stack_malloc_always_7
libSceAddressSanitizer __asan_stack_malloc_always_8
libSceAddressSanitizer __asan_stack_malloc_always_9
libSceAddressSanitizer __asan_store1
libSceAddressSanitizer __asan_store16
libSceAddressSanitizer __asan_store16_noabort
libSceAddressSanitizer __asan_store1_noabort
libSceAddressSanitizer __asan_store2
... 53 more

Changed libraries (implemented exports)

Library Before After Change
libSceAddressSanitizer 0/301 (0.00%) 282/301 (93.69%) +93.69%

@github-actions github-actions Bot added the fix error Closes an issue (Fixes #N) label Nov 6, 2026
@JJenkx

JJenkx commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Windows check of head e4ecb48713, merged onto main 95b1b4df6d (05ce6a6403, clean merge).

Setup: Windows 11 Enterprise 22621, WinLibs GCC 15.2 UCRT, Release. The hosted Windows check does not run these tests on pull requests.

  • guest_address_sanitizer passes in 3 of 3 runs, none skipped.

AI-assisted: yes.

@QW1CKS

QW1CKS commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Closing this in favour of #13265 and #13331 by @PrivacyOnion, which I found after opening it. Both predate this branch by a week, and #13331 already covers every export implemented here, so this adds nothing they do not.

The overlap check I ran before opening reported no open pull requests because tools/pr_overlap.py resolves the remote to my fork rather than upstream. --repo boykopovar/AnyPS5 reports 1905 open pull requests and names both immediately. My mistake, not the tool's.

For the record, this branch is green: guest_address_sanitizer passes on Linux and in three Windows runs reported by @JJenkx, the negative control against main's library aborts in a throwing stub, and conventions clean. Nothing in it needs salvaging into #13265, which does its own allocator rather than delegating to the guest heap.

@QW1CKS QW1CKS closed this Nov 6, 2026
@QW1CKS
QW1CKS deleted the feat/libSce-address-sanitizer-passthrough branch November 6, 2026 19:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build docs fix error Closes an issue (Fixes #N) prx

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants