Skip to content

Commit facdaac

Browse files
authored
Fix stale values in the detail struct (#2881)
* RISCV: fix stale values in the detail struct * Skip RISC-V unit test without CAPSTONE_RISCV_SUPPORT
1 parent dbc69c9 commit facdaac

File tree

6 files changed

+140
-0
lines changed

6 files changed

+140
-0
lines changed

arch/RISCV/RISCVDisassembler.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "../../utils.h"
3939
#include "RISCVDisassemblerExtension.h"
4040
#include "RISCVBaseInfo.h"
41+
#include "RISCVMapping.h"
4142

4243
#define GET_SUBTARGETINFO_ENUM
4344
#include "RISCVGenSubtargetInfo.inc"
@@ -745,6 +746,7 @@ bool RISCV_LLVM_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen,
745746
MCInst *MI, uint16_t *Size, uint64_t Address,
746747
void *Info)
747748
{
749+
RISCV_init_cs_detail(MI);
748750
MI->MRI = (MCRegisterInfo *)Info;
749751
return RISCV_getInstruction(MI, Size, Bytes, ByteLen, Address, NULL) !=
750752
MCDisassembler_Fail;

arch/RISCV/RISCVMapping.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,14 @@ static inline void RISCV_add_adhoc_groups(MCInst *MI)
262262
RISCV_add_ret_group(MI);
263263
}
264264

265+
// memset all stalled values in the detail struct to 0 before disassembling any next instruction
266+
void RISCV_init_cs_detail(MCInst *MI)
267+
{
268+
if (detail_is_set(MI))
269+
memset(get_detail(MI), 0,
270+
offsetof(cs_detail, riscv) + sizeof(cs_riscv));
271+
}
272+
265273
// for weird reasons some instructions end up with valid operands that are
266274
// interspersed with invalid operands, i.e. the operands array is an "island"
267275
// of valid operands with invalid gaps between them, this function will compactify

arch/RISCV/RISCVMapping.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ void RISCV_add_cs_detail_0(MCInst *MI, riscv_op_group opgroup, unsigned OpNum);
2525

2626
void RISCV_add_groups(MCInst *MI);
2727

28+
void RISCV_init_cs_detail(MCInst *MI);
29+
2830
void RISCV_compact_operands(MCInst *MI);
2931

3032
void RISCV_add_missing_write_access(MCInst *MI);

tests/issues/issues.yaml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6321,3 +6321,81 @@ test_cases:
63216321
reg: $2
63226322
- type: ALPHA_OP_IMM
63236323
imm: 0x12001b350
6324+
-
6325+
input:
6326+
name: "RISCV - #2881 - op_count must not accumulate across instructions (real)"
6327+
bytes: [ 0x41, 0x11, 0x13, 0x85, 0x15, 0x00, 0x41, 0x11 ]
6328+
arch: "CS_ARCH_RISCV"
6329+
options: [ CS_MODE_RISCV64, CS_MODE_RISCV_C, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL, CS_OPT_SYNTAX_NO_ALIAS_TEXT, CS_OPT_SYNTAX_NO_ALIAS_TEXT_COMPRESSED ]
6330+
expected:
6331+
insns:
6332+
-
6333+
asm_text: "c.addi sp, -0x10"
6334+
details:
6335+
riscv:
6336+
operands:
6337+
- type: "RISCV_OP_REG"
6338+
reg: "sp"
6339+
- type: "RISCV_OP_IMM"
6340+
imm: -0x10
6341+
-
6342+
asm_text: "addi a0, a1, 1"
6343+
details:
6344+
riscv:
6345+
operands:
6346+
- type: "RISCV_OP_REG"
6347+
reg: "a0"
6348+
- type: "RISCV_OP_REG"
6349+
reg: "a1"
6350+
- type: "RISCV_OP_IMM"
6351+
imm: 1
6352+
-
6353+
asm_text: "c.addi sp, -0x10"
6354+
details:
6355+
riscv:
6356+
operands:
6357+
- type: "RISCV_OP_REG"
6358+
reg: "sp"
6359+
- type: "RISCV_OP_IMM"
6360+
imm: -0x10
6361+
-
6362+
input:
6363+
name: "RISCV - #2881 - op_count must not accumulate across instructions (alias)"
6364+
bytes: [ 0x41, 0x11, 0x13, 0x85, 0x15, 0x00, 0x41, 0x11 ]
6365+
arch: "CS_ARCH_RISCV"
6366+
options: [ CS_MODE_RISCV64, CS_MODE_RISCV_C, CS_OPT_DETAIL ]
6367+
expected:
6368+
insns:
6369+
-
6370+
asm_text: "addi sp, sp, -0x10"
6371+
details:
6372+
riscv:
6373+
operands:
6374+
- type: "RISCV_OP_REG"
6375+
reg: "sp"
6376+
- type: "RISCV_OP_REG"
6377+
reg: "sp"
6378+
- type: "RISCV_OP_IMM"
6379+
imm: -0x10
6380+
-
6381+
asm_text: "addi a0, a1, 1"
6382+
details:
6383+
riscv:
6384+
operands:
6385+
- type: "RISCV_OP_REG"
6386+
reg: "a0"
6387+
- type: "RISCV_OP_REG"
6388+
reg: "a1"
6389+
- type: "RISCV_OP_IMM"
6390+
imm: 1
6391+
-
6392+
asm_text: "addi sp, sp, -0x10"
6393+
details:
6394+
riscv:
6395+
operands:
6396+
- type: "RISCV_OP_REG"
6397+
reg: "sp"
6398+
- type: "RISCV_OP_REG"
6399+
reg: "sp"
6400+
- type: "RISCV_OP_IMM"
6401+
imm: -0x10

tests/unit/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.15)
22

33
enable_testing()
44
set(UNIT_TEST_SOURCES sstream.c utils.c)
5+
if(CAPSTONE_RISCV_SUPPORT)
6+
list(APPEND UNIT_TEST_SOURCES riscv_op_count_iter.c)
7+
endif()
58
include_directories(include)
69

710
foreach(TSRC ${UNIT_TEST_SOURCES})

tests/unit/riscv_op_count_iter.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "unit_test.h"
2+
#include <capstone/capstone.h>
3+
#include <stdio.h>
4+
#include <inttypes.h>
5+
6+
// c.addi sp, -16 (2 ops) -> addi a0, a1, 1 (3 ops) -> c.addi sp, -16 (2 ops)
7+
// Without RISCV_init_cs_detail(), op_count accumulates: 2, 5, 7
8+
static bool test_riscv_op_count_no_stale()
9+
{
10+
printf("Test test_riscv_op_count_no_stale\n");
11+
static const uint8_t code[] = {
12+
0x41, 0x11, // c.addi sp, -16
13+
0x13, 0x85, 0x15, 0x00, // addi a0, a1, 1
14+
0x41, 0x11, // c.addi sp, -16
15+
};
16+
static const int32_t expected_op_counts[] = { 2, 3, 2 };
17+
18+
csh handle;
19+
cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCV_C, &handle);
20+
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON | CS_OPT_DETAIL_REAL);
21+
cs_option(handle, CS_OPT_SYNTAX,
22+
CS_OPT_SYNTAX_NO_ALIAS_TEXT |
23+
CS_OPT_SYNTAX_NO_ALIAS_TEXT_COMPRESSED);
24+
cs_insn *insn = cs_malloc(handle);
25+
26+
const uint8_t *start = code;
27+
size_t size = sizeof(code);
28+
uint64_t address = 0;
29+
size_t i = 0;
30+
31+
while (cs_disasm_iter(handle, &start, &size, &address, insn)) {
32+
CHECK_INT_EQUAL_RET_FALSE((size_t)insn->detail->riscv.op_count,
33+
expected_op_counts[i]);
34+
++i;
35+
}
36+
37+
cs_free(insn, 1);
38+
cs_close(&handle);
39+
return true;
40+
}
41+
42+
int main(void)
43+
{
44+
bool ret = true;
45+
ret &= test_riscv_op_count_no_stale();
46+
return ret ? 0 : -1;
47+
}

0 commit comments

Comments
 (0)