Recompiler: vcallmsr reads ctx->vi[27], out of bounds on uint16_t vi[16], instead of ctx->vu0_cmsar0
Los mantenedores suelen responder en 5 días
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 28/100
Línea de trabajo
The mismatch is in ps2xRecomp/src/lib/vu_translation_helpers.cpp around the vcallmsr emitter (line 172 in the report) versus the ctc2 CMSAR0 path in vu_translator.cpp. Read those two sites and the vi[16] / vu0_cmsar0 layout in ps2xRuntime/include/ps2_runtime.h. Confirm other VU0_CR_* cases in the helpers do not index vi with a control-register number. PR #268 is already open against this issue, so do not start a parallel fix unless maintainers say otherwise.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
What happens
The two halves of the same instruction pair disagree about where the VU0 microprogram start address lives.
ctc2 $rt, $vi27 is translated correctly -- ps2xRecomp/src/lib/vu_translator.cpp:96:
case VU0_CR_CMSAR0:
return fmt::format("ctx->vu0_cmsar0 = GPR_U32(ctx, {});", rt);
But vcallmsr reads the value back from the vi array -- ps2xRecomp/src/lib/vu_translation_helpers.cpp:172:
" uint16_t instr_index = ctx->vi[{}] & 0x1FF; "
With vcallmsr $vi27 that formats to ctx->vi[27], and vi is declared uint16_t vi[16] (ps2xRuntime/include/ps2_runtime.h:75). Index 27 is 11 elements past the end; the read lands in the storage of the following fields (vu0_q / vu0_p in this layout). vu0_cmsar0 is declared separately at line 85, and is what the write filled.
clang flags it: array index 27 is past the end of the array.
Reproduction
Guest code at 0x002C4850 in SLUS_200.02:
andi $a0, $a0, 0xFFFF
ctc2 $a0, $vi27 ; VI27 = CMSAR0
jr $ra
vcallmsr ; delay slot: start the VU0 microprogram from CMSAR0
Generated output (Vu0StartMicroProgramReg_0x2c4850.cpp):
// 0x2c4854: 0x48c4d800 ctc2.ni $a0, $vi27
ctx->vu0_cmsar0 = GPR_U32(ctx, 4);
...
{ uint16_t instr_index = ctx->vi[27] & 0x1FF;
uint32_t target_byte_addr = (uint32_t)instr_index << 3;
ctx->vu0_pc = target_byte_addr;
runtime->vu0StartMicroProgram(rdram, ctx, target_byte_addr); }
The microprogram address never arrives, and the register-based VU0 microprogram launcher is broken.
Root cause
vcallmsr takes its address from CMSAR0 unconditionally -- that is what the instruction does. The $vi27 in the disassembly is how CMSAR0 is named in the VU0 control register space (VU0_CR_CMSAR0 = 27), which is a different namespace from the 16 VI integer registers. The emitter is using a control-register index to subscript the VI array.
Suggested fix
Emit the field the ctc2 side writes:
" uint16_t instr_index = (uint16_t)(ctx->vu0_cmsar0 & 0x1FF); "
The other VU0_CR_* cases in vu_translation_helpers.cpp are worth auditing for the same namespace confusion.
Scope
One occurrence in our 2751 functions -- the only vcallmsr in the binary, called only from FUN_002C4740. The 124 functions using the immediate form vcallms are unaffected, since there the address is encoded in the instruction. But this is an out-of-bounds read, so it is undefined behaviour rather than merely a wrong value, and it does not stay dormant safely.
Found while statically recompiling Ridge Racer V (NTSC-U, SLUS_200.02) with PS2Recomp.
Tested on commit 75d729ce; main was c5a9d02 at the time of writing, one README-only commit ahead.
Host: Windows 11 x64, clang-cl 22.1.3 + Ninja, MSVC toolset 14.51.36231, Windows SDK 10.0.26100.0, CMake 4.2.3.
None of these are specific to this game.
- Lenguaje dominante
- C++
- Estrellas
- 3.3k
- Forks
- 149
- Merge medio
- 5 d 10 h
- PR fusionados (30 d)
- 4
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de ran-j/PS2Recomp
-
VU0 macro VSQI / VSQD: address and source registers swapped in generated codePosiblemente ocupada @yanm1103 la tomó hace 1 día. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 5 días
-
Runtime: SampleTexture casts unbounded or NaN texture coordinates to int, which is undefined behaviourPosiblemente ocupada @luisbraganca la tomó hace 6 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
ran-j/PS2Recomp#273 · 2 comentarios ·
Los mantenedores suelen responder en 5 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 5 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
Los mantenedores suelen responder en 5 días
-
Runtime: writes to D_ENABLEW (0x1000F590) are never visible at D_ENABLER (0x1000F520), hanging any game that suspends the DMACPosiblemente ocupada @luisbraganca la tomó hace 6 días. Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
ran-j/PS2Recomp#257 · 1 comentario ·
Los mantenedores suelen responder en 5 días
Todos los issues de ran-j/PS2Recomp
Issues similares
-
accessibility good first issue hacktoberfest help wanted
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
OpenChemistry/avogadrolibs#3184 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Tracktion/tracktion_engine#475 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
redis/memtier_benchmark#732 ·
Los mantenedores suelen responder en 1 día
-
binding:web core docs p3
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
RunanywhereAI/runanywhere-sdks#1123 ·
Los mantenedores suelen responder en 1 día
-
ai_p3 comp-data-types
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
ClickHouse/ClickHouse#126316 ·
Los mantenedores suelen responder en 1 día