Skip to content

Commit cbc22bf

Browse files
JoeMattclaude
andcommitted
fix: rotate-by-zero UB in GPU/DSP ROR/RORQ opcodes
UBSAN on PR #126 found: src/tom/gpu.c:1674: shift exponent 32 too large for uint32_t The classic rotate-right idiom (RN >> r1) | (RN << (32 - r1)) invokes UB when r1 == 0 (32-bit shift count of 32 is out of range). Replace with the standard portable pattern: (RN >> r1) | (RN << ((-r1) & 31)) which yields RN | RN == RN for r1 == 0 and is identical for r1 in [1, 31]. Modern GCC/clang pattern-match this idiom into a single rotate instruction (rorl on x86, ror on ARM). Six sites across two files: - src/tom/gpu.c gpu_opcode_ror, gpu_opcode_rorq - src/jerry/dsp.c dsp_opcode_ror, dsp_opcode_rorq, plus the prefetched (PRN) variants Co-Authored-By: Claude Opus 4.7 <[email protected]>
1 parent da531e5 commit cbc22bf

2 files changed

Lines changed: 6 additions & 6 deletions

File tree

src/jerry/dsp.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ INLINE static void dsp_opcode_shrq(void)
14091409
INLINE static void dsp_opcode_ror(void)
14101410
{
14111411
uint32_t r1 = RM & 0x1F;
1412-
uint32_t res = (RN >> r1) | (RN << (32 - r1));
1412+
uint32_t res = (RN >> r1) | (RN << ((-r1) & 31));
14131413
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
14141414
RN = res;
14151415
}
@@ -1419,7 +1419,7 @@ INLINE static void dsp_opcode_rorq(void)
14191419
{
14201420
uint32_t r1 = dsp_convert_zero[IMM_1 & 0x1F];
14211421
uint32_t r2 = RN;
1422-
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
1422+
uint32_t res = (r2 >> r1) | (r2 << ((-r1) & 31));
14231423
RN = res;
14241424
SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
14251425
}
@@ -2226,7 +2226,7 @@ INLINE static void DSP_resmac(void)
22262226
INLINE static void DSP_ror(void)
22272227
{
22282228
uint32_t r1 = PRM & 0x1F;
2229-
uint32_t res = (PRN >> r1) | (PRN << (32 - r1));
2229+
uint32_t res = (PRN >> r1) | (PRN << ((-r1) & 31));
22302230
SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
22312231
PRES = res;
22322232
}
@@ -2235,7 +2235,7 @@ INLINE static void DSP_rorq(void)
22352235
{
22362236
uint32_t r1 = dsp_convert_zero[PIMM1 & 0x1F];
22372237
uint32_t r2 = PRN;
2238-
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
2238+
uint32_t res = (r2 >> r1) | (r2 << ((-r1) & 31));
22392239
PRES = res;
22402240
SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
22412241
}

src/tom/gpu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@ INLINE static void gpu_opcode_shrq(void)
16711671
INLINE static void gpu_opcode_ror(void)
16721672
{
16731673
uint32_t r1 = RM & 0x1F;
1674-
uint32_t res = (RN >> r1) | (RN << (32 - r1));
1674+
uint32_t res = (RN >> r1) | (RN << ((-r1) & 31));
16751675
SET_ZN(res); gpu_flag_c = (RN >> 31) & 1;
16761676
RN = res;
16771677
}
@@ -1681,7 +1681,7 @@ INLINE static void gpu_opcode_rorq(void)
16811681
{
16821682
uint32_t r1 = gpu_convert_zero[IMM_1 & 0x1F];
16831683
uint32_t r2 = RN;
1684-
uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
1684+
uint32_t res = (r2 >> r1) | (r2 << ((-r1) & 31));
16851685
RN = res;
16861686
SET_ZN(res); gpu_flag_c = (r2 >> 31) & 0x01;
16871687
}

0 commit comments

Comments
 (0)