Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Recompiler: vcallmsr reads ctx->vi[27], out of bounds on uint16_t vi[16], instead of ctx->vu0_cmsar0

Abierto
#262 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 5 días

@drakolordx7 ya está trabajando en esto.

Desde el 30/9/2026.

  • #268 de @drakolordx7 — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
28/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Estancado
Stack tecnológico
cpp

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

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de ran-j/PS2Recomp

Todos los issues de ran-j/PS2Recomp

Issues similares

Más issues de C++

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.