Skip to content

Commit cbef767

Browse files
authored
Merge commit from fork
The overflow was reported by Github user Finder16
1 parent 2c77971 commit cbef767

File tree

3 files changed

+94
-7
lines changed

3 files changed

+94
-7
lines changed

cs.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,11 +1323,13 @@ size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size,
13231323
skipdata_bytes = handle->skipdata_size;
13241324

13251325
// we have to skip some amount of data, depending on arch & mode
1326-
insn_cache->id =
1327-
0; // invalid ID for this "data" instruction
1326+
// invalid ID for this "data" instruction
1327+
insn_cache->id = 0;
13281328
insn_cache->address = offset;
1329-
insn_cache->size = (uint16_t)skipdata_bytes;
1330-
memcpy(insn_cache->bytes, buffer, skipdata_bytes);
1329+
insn_cache->size = (uint16_t)MIN(
1330+
skipdata_bytes, sizeof(insn_cache->bytes));
1331+
memcpy(insn_cache->bytes, buffer,
1332+
MIN(skipdata_bytes, sizeof(insn_cache->bytes)));
13311333
#ifdef CAPSTONE_DIET
13321334
insn_cache->mnemonic[0] = '\0';
13331335
insn_cache->op_str[0] = '\0';
@@ -1537,12 +1539,13 @@ bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
15371539
// we have to skip some amount of data, depending on arch & mode
15381540
insn->id = 0; // invalid ID for this "data" instruction
15391541
insn->address = *address;
1540-
insn->size = (uint16_t)skipdata_bytes;
1542+
insn->size = (uint16_t)MIN(skipdata_bytes, sizeof(insn->bytes));
1543+
memcpy(insn->bytes, *code,
1544+
MIN(skipdata_bytes, sizeof(insn->bytes)));
15411545
#ifdef CAPSTONE_DIET
15421546
insn->mnemonic[0] = '\0';
15431547
insn->op_str[0] = '\0';
15441548
#else
1545-
memcpy(insn->bytes, *code, skipdata_bytes);
15461549
strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
15471550
sizeof(insn->mnemonic) - 1);
15481551
skipdata_opstr(insn->op_str, *code, skipdata_bytes);

tests/integration/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ add_test(NAME integration_c_compat_headers
3333
WORKING_DIRECTORY ${COMPAT_C_TEST_DIR}
3434
)
3535

36-
set(INTEGRATION_TEST_SRC test_litbase.c)
36+
set(INTEGRATION_TEST_SRC test_litbase.c test_poc.c)
3737
if(CMAKE_BUILD_TYPE STREQUAL "Release")
3838
set(INTEGRATION_TEST_SRC ${INTEGRATION_TEST_SRC} test_assert_macros.c)
3939
endif()

tests/integration/test_poc.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// SPDX-License-Identifier: BSD-3
2+
// SPDX-FileCopyrightText: 2025 Finder16
3+
// SPDX-FileCopyrightText: 2025 Rot127 <unisono@quyllur.org>
4+
5+
#include <stdint.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
9+
#include <capstone/platform.h>
10+
#include <capstone/capstone.h>
11+
12+
static size_t big_skip(const uint8_t *code, size_t code_size, size_t offset,
13+
void *user_data)
14+
{
15+
(void)code;
16+
(void)code_size;
17+
(void)offset;
18+
(void)user_data;
19+
return 1024; // larger than cs_insn.bytes (24)
20+
}
21+
22+
/// Possible buffer overflow of cs_insn.bytes if number of skipped bytes
23+
/// is larger.
24+
/// Reported by Finder16.
25+
static void test_overflow_cs_insn_bytes()
26+
{
27+
csh handle;
28+
if (cs_open(CS_ARCH_WASM, CS_MODE_LITTLE_ENDIAN, &handle) !=
29+
CS_ERR_OK) {
30+
return;
31+
}
32+
cs_opt_skipdata skip = { .mnemonic = ".byte",
33+
.callback = big_skip,
34+
.user_data = NULL };
35+
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
36+
cs_option(handle, CS_OPT_SKIPDATA_SETUP, (size_t)&skip);
37+
uint8_t buf[1024] = { 0 };
38+
buf[0] = 0x06; // invalid WASM opcode to force skipdata path
39+
cs_insn *insn = NULL;
40+
// Overflowed cs_insn->bytes before the fix.
41+
cs_disasm(handle, buf, sizeof(buf), 0, 1, &insn);
42+
cs_free(insn, 1);
43+
cs_close(&handle);
44+
return;
45+
}
46+
47+
/// Possible buffer overflow of cs_insn.bytes if number of skipped bytes
48+
/// is larger.
49+
/// Reported by Finder16.
50+
static void test_overflow_cs_insn_bytes_iter()
51+
{
52+
csh handle;
53+
if (cs_open(CS_ARCH_WASM, CS_MODE_LITTLE_ENDIAN, &handle) !=
54+
CS_ERR_OK) {
55+
return;
56+
}
57+
cs_opt_skipdata skip = { .mnemonic = ".byte",
58+
.callback = big_skip,
59+
.user_data = NULL };
60+
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
61+
cs_option(handle, CS_OPT_SKIPDATA_SETUP, (size_t)&skip);
62+
uint64_t address = 0;
63+
uint8_t buf[1024] = { 0 };
64+
const uint8_t *b = buf;
65+
size_t size = sizeof(buf);
66+
buf[0] = 0x06; // invalid WASM opcode to force skipdata path
67+
cs_insn *insn = cs_malloc(handle);
68+
;
69+
// Overflowed cs_insn->bytes before the fix.
70+
while (cs_disasm_iter(handle, &b, &size, &address, insn)) {
71+
continue;
72+
}
73+
cs_free(insn, 1);
74+
cs_close(&handle);
75+
return;
76+
}
77+
78+
int main()
79+
{
80+
test_overflow_cs_insn_bytes();
81+
test_overflow_cs_insn_bytes_iter();
82+
83+
return 0;
84+
}

0 commit comments

Comments
 (0)