Skip to content

Commit 605cdba

Browse files
authored
Handle case of vsprintf returning oob pointer offset. (#3060)
1 parent e6fb396 commit 605cdba

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

cs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,10 @@ static void skipdata_opstr(char *opstr, const uint8_t *buffer, size_t size)
12241224
}
12251225

12261226
len = cs_snprintf(p, available, "0x%02x", buffer[0]);
1227+
if (len < 0 || (size_t)len > available - 1) {
1228+
opstr[0] = '\0';
1229+
return;
1230+
}
12271231
p += len;
12281232
available -= len;
12291233

tests/integration/test_poc.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,25 @@
22
// SPDX-FileCopyrightText: 2025 Finder16
33
// SPDX-FileCopyrightText: 2025 Rot127 <unisono@quyllur.org>
44

5+
#include <limits.h>
56
#include <stdint.h>
67
#include <stdio.h>
78
#include <stdlib.h>
89

910
#include <capstone/platform.h>
1011
#include <capstone/capstone.h>
1112

13+
/* Malicious vsnprintf: writes like a real vsnprintf (at most `size` bytes,
14+
* in-bounds) but returns a huge fabricated length (INT_MAX). */
15+
static int evil_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
16+
{
17+
(void)str;
18+
(void)size;
19+
(void)fmt;
20+
(void)ap;
21+
return INT_MAX;
22+
}
23+
1224
static size_t big_skip(const uint8_t *code, size_t code_size, size_t offset,
1325
void *user_data)
1426
{
@@ -318,6 +330,32 @@ static void test_tms320_ghsa_8qp8_2vg2_8mr4(void)
318330
cs_close(&h);
319331
}
320332

333+
int test_evil_vsnprintf_ghsa_gj26_93q5_cr54(void)
334+
{
335+
csh handle;
336+
cs_insn *insn = NULL;
337+
size_t n;
338+
/* Non-instruction bytes: ARM decode fails -> SKIPDATA path runs */
339+
const uint8_t code[4] = { 0xff, 0xff, 0xff, 0xff };
340+
cs_opt_mem mem = { malloc, calloc, realloc, free, evil_vsnprintf };
341+
342+
printf("[poc] registering malicious cs_opt_mem.vsnprintf (CS_OPT_MEM)\n");
343+
if (cs_option(0, CS_OPT_MEM, (size_t)&mem) != CS_ERR_OK)
344+
return 1;
345+
if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle) != CS_ERR_OK)
346+
return 1;
347+
if (cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON) != CS_ERR_OK)
348+
return 1;
349+
350+
printf("[poc] cs_disasm() on 0xffffffff with SKIPDATA enabled\n");
351+
fflush(stdout);
352+
n = cs_disasm(handle, code, sizeof(code), 0x1000, 0, &insn);
353+
printf("[poc] cs_disasm returned %zu instructions without fault\n", n);
354+
cs_free(insn, n);
355+
cs_close(&handle);
356+
return 0;
357+
}
358+
321359
int main()
322360
{
323361
test_overflow_cs_insn_bytes();
@@ -330,6 +368,7 @@ int main()
330368
test_sh_oob_read_ghsa_5q63_4654_94v6();
331369
test_arm_pop_ghsa_8qp8_2vg2_8mr4();
332370
test_tms320_ghsa_8qp8_2vg2_8mr4();
371+
test_evil_vsnprintf_ghsa_gj26_93q5_cr54();
333372

334373
return 0;
335374
}

0 commit comments

Comments
 (0)