Skip to content

Commit e17ee44

Browse files
authored
V5: Fix OOB reads/writes - CVE-2026-55893 & CVE-2026-55894 (#2969)
* Fix several OOB writes by adding bounds checks * Add bounds check for index into decoder table
1 parent c04e7f2 commit e17ee44

1 file changed

Lines changed: 98 additions & 35 deletions

File tree

arch/SH/SHDisassembler.c

Lines changed: 98 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,33 @@ static void regs_rw(cs_detail *detail, enum direction rw, sh_reg reg)
3131
}
3232
}
3333

34-
static void set_reg_n(sh_info *info, sh_reg reg, int pos,
35-
enum direction rw, cs_detail *detail)
34+
static bool set_reg_n(sh_info *info, sh_reg reg, int pos, enum direction rw,
35+
cs_detail *detail)
3636
{
37+
if (pos >= ARR_SIZE(info->op.operands)) {
38+
return false;
39+
}
3740
info->op.operands[pos].type = SH_OP_REG;
3841
info->op.operands[pos].reg = reg;
3942
regs_rw(detail, rw, reg);
43+
return true;
4044
}
4145

4246
static void set_reg(sh_info *info, sh_reg reg, enum direction rw,
4347
cs_detail *detail)
4448
{
45-
set_reg_n(info, reg, info->op.op_count, rw, detail);
49+
if (!set_reg_n(info, reg, info->op.op_count, rw, detail)) {
50+
return;
51+
}
4652
info->op.op_count++;
4753
}
4854

49-
static void set_mem_n(sh_info *info, sh_op_mem_type address,
50-
sh_reg reg, uint32_t disp, int sz, int pos,
51-
cs_detail *detail)
55+
static bool set_mem_n(sh_info *info, sh_op_mem_type address, sh_reg reg,
56+
uint32_t disp, int sz, int pos, cs_detail *detail)
5257
{
58+
if (pos >= ARR_SIZE(info->op.operands)) {
59+
return false;
60+
}
5361
info->op.operands[pos].type = SH_OP_MEM;
5462
info->op.operands[pos].mem.address = address;
5563
info->op.operands[pos].mem.reg = reg;
@@ -75,12 +83,16 @@ static void set_mem_n(sh_info *info, sh_op_mem_type address,
7583
regs_read(detail, reg);
7684
break;
7785
}
86+
return true;
7887
}
7988

8089
static void set_mem(sh_info *info, sh_op_mem_type address,
8190
sh_reg reg, uint32_t disp, int sz, cs_detail *detail)
8291
{
83-
set_mem_n(info, address, reg, disp, sz, info->op.op_count, detail);
92+
if (!set_mem_n(info, address, reg, disp, sz, info->op.op_count,
93+
detail)) {
94+
return;
95+
}
8496
info->op.op_count++;
8597
}
8698

@@ -311,20 +323,31 @@ static bool opMOVx(uint16_t code, uint64_t address, MCInst *MI,
311323
rw = (ad >> 1);
312324
{
313325
nm(code, rw);
314-
set_reg_n(info, SH_REG_R0 + m, rw, rw, detail);
315-
set_mem_n(info, SH_OP_MEM_REG_R0, SH_REG_R0 + n,
316-
0, size, 1 - rw, detail);
317-
info->op.op_count = 2;
326+
if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
327+
return false;
328+
}
329+
info->op.op_count++;
330+
if (!set_mem_n(info, SH_OP_MEM_REG_R0, SH_REG_R0 + n, 0,
331+
size, 1 - rw, detail)) {
332+
return false;
333+
}
334+
info->op.op_count++;
318335
}
319336
break;
320337
case 0x20: /// mov.X Rs,@-Rd
321338
case 0x60: /// mov.X @Rs+,Rd
322339
rw = (ad >> 6) & 1;
323340
{
324341
nm(code, rw);
325-
set_reg_n(info, SH_REG_R0 + m, rw, rw, detail);
326-
set_mem_n(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n,
327-
0, size, 1 - rw, detail);
342+
if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
343+
return false;
344+
}
345+
info->op.op_count++;
346+
if (!set_mem_n(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n,
347+
0, size, 1 - rw, detail)) {
348+
return false;
349+
}
350+
info->op.op_count++;
328351
}
329352
break;
330353
default:
@@ -550,10 +573,16 @@ static bool opMOV_L_dsp(uint16_t code, uint64_t address, MCInst *MI,
550573
int rw = (code >> 14) & 1;
551574
nm(code, rw);
552575
MCInst_setOpcode(MI, SH_INS_MOV);
553-
set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n, dsp,
554-
32, 1 - rw, detail);
555-
set_reg_n(info, SH_REG_R0 + m, rw, rw, detail);
556-
info->op.op_count = 2;
576+
if (!set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n, dsp, 32, 1 - rw,
577+
detail)) {
578+
return false;
579+
}
580+
info->op.op_count++;
581+
582+
if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
583+
return false;
584+
}
585+
info->op.op_count++;
557586
return MCDisassembler_Success;
558587
}
559588

@@ -565,9 +594,14 @@ static bool opMOV_rind(uint16_t code, uint64_t address, MCInst *MI,
565594
nm(code, rw);
566595
MCInst_setOpcode(MI, SH_INS_MOV);
567596
sz = 8 << sz;
568-
set_mem_n(info, SH_OP_MEM_REG_IND, SH_REG_R0 + n, 0,
569-
sz, 1 - rw, detail);
570-
set_reg_n(info, SH_REG_R0 + m, rw, rw, detail);
597+
if (!set_mem_n(info, SH_OP_MEM_REG_IND, SH_REG_R0 + n, 0, sz, 1 - rw,
598+
detail)) {
599+
return false;
600+
}
601+
602+
if (!set_reg_n(info, SH_REG_R0 + m, rw, rw, detail)) {
603+
return false;
604+
}
571605
info->op.op_count = 2;
572606
return MCDisassembler_Success;
573607
}
@@ -957,11 +991,17 @@ static bool op4xxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode,
957991
set_groups(detail, 1, grp);
958992
} else {
959993
if (insn_code != 1) {
960-
set_reg_n(info, SH_REG_R0, rw, rw, detail);
994+
if (!set_reg_n(info, SH_REG_R0, rw, rw,
995+
detail)) {
996+
return false;
997+
}
961998
info->op.op_count++;
962999
}
963-
set_mem_n(info, memop, SH_REG_R0 + r, 0, sz,
964-
1 - rw, detail);
1000+
if (!set_mem_n(info, memop, SH_REG_R0 + r, 0, sz,
1001+
1 - rw, detail)) {
1002+
return false;
1003+
}
1004+
9651005
info->op.op_count++;
9661006
}
9671007
return MCDisassembler_Success;
@@ -1024,10 +1064,17 @@ static bool opMOV_BW_dsp(uint16_t code, uint64_t address, MCInst *MI,
10241064
int size = 1 + ((code >> 8) & 1);
10251065
int rw = (code >> 10) & 1;
10261066
MCInst_setOpcode(MI, SH_INS_MOV);
1027-
set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + r, dsp * size,
1028-
8 * size, 1 - rw, detail);
1029-
set_reg_n(info, SH_REG_R0, rw, rw, detail);
1030-
info->op.op_count = 2;
1067+
if (!set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + r, dsp * size,
1068+
8 * size, 1 - rw, detail)) {
1069+
return false;
1070+
}
1071+
info->op.op_count++;
1072+
1073+
if (!set_reg_n(info, SH_REG_R0, rw, rw, detail)) {
1074+
return false;
1075+
}
1076+
1077+
info->op.op_count++;
10311078
return MCDisassembler_Success;
10321079
}
10331080

@@ -1213,10 +1260,16 @@ static bool opMOV_gbr(uint16_t code, uint64_t address, MCInst *MI,
12131260
int dsp = (code & 0x00ff) * (sz / 8);
12141261
int rw = (code >> 10) & 1;
12151262
MCInst_setOpcode(MI, SH_INS_MOV);
1216-
set_mem_n(info, SH_OP_MEM_GBR_DISP, SH_REG_GBR, dsp, sz,
1217-
1 - rw, detail);
1218-
set_reg_n(info, SH_REG_R0, rw, rw, detail);
1219-
info->op.op_count = 2;
1263+
if (!set_mem_n(info, SH_OP_MEM_GBR_DISP, SH_REG_GBR, dsp, sz, 1 - rw,
1264+
detail)) {
1265+
return false;
1266+
}
1267+
info->op.op_count++;
1268+
1269+
if (!set_reg_n(info, SH_REG_R0, rw, rw, detail)) {
1270+
return false;
1271+
}
1272+
info->op.op_count++;
12201273
return MCDisassembler_Success;
12211274
}
12221275

@@ -1289,9 +1342,16 @@ static bool opFMOVm(MCInst *MI, enum direction rw, uint16_t code,
12891342
{
12901343
nm(code, (1 - rw));
12911344
MCInst_setOpcode(MI, SH_INS_FMOV);
1292-
set_mem_n(info, address, SH_REG_R0 + m, 0, 0, 1 - rw, detail);
1293-
set_reg_n(info, SH_REG_FR0 + n, rw, rw, detail);
1294-
info->op.op_count = 2;
1345+
if (!set_mem_n(info, address, SH_REG_R0 + m, 0, 0, 1 - rw, detail)) {
1346+
return false;
1347+
}
1348+
info->op.op_count++;
1349+
1350+
if (!set_reg_n(info, SH_REG_FR0 + n, rw, rw, detail)) {
1351+
return false;
1352+
}
1353+
info->op.op_count++;
1354+
12951355
return MCDisassembler_Success;
12961356
}
12971357

@@ -2162,6 +2222,9 @@ static bool sh_disassemble(const uint8_t *code, MCInst *MI, uint64_t address,
21622222
} else {
21632223
idx = ((insn >> 8) & 0xf0) | (insn & 0x000f);
21642224
}
2225+
if (idx >= ARR_SIZE(decode)) {
2226+
return MCDisassembler_Fail;
2227+
}
21652228

21662229
if (decode[idx]) {
21672230
return decode[idx](insn, address, MI, mode, info, detail);

0 commit comments

Comments
 (0)