Add overflow check to cs_kern_os_calloc (#2980)

Co-authored by: orbisai0security
This commit is contained in:
Rot127 2026-07-10 09:53:40 +00:00 committed by GitHub
parent 6f41db9228
commit 857e556ced
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 64 additions and 1 deletions

6
cs.c
View file

@ -501,7 +501,11 @@ extern void *kern_os_realloc(void *addr, size_t nsize);
static void *cs_kern_os_calloc(size_t num, size_t size)
{
return kern_os_malloc(num * size); // malloc bzeroes the buffer
size_t alloc = num * size;
if (num && size != alloc / num) {
return NULL; // overflow check
}
return kern_os_malloc(alloc); // malloc bzeroes the buffer
}
cs_malloc_t cs_mem_malloc = kern_os_malloc;

View file

@ -110,6 +110,64 @@ static void test_overflow_set_reg_mem_n(void)
return;
}
/**
* \brief Clone of cs.c::cs_kern_os_calloc()
* So we can run it in the CI.
*/
static void *clone_cs_kern_os_calloc(size_t num, size_t size)
{
size_t alloc = num * size;
if (num && size != alloc / num) {
return NULL; // overflow check
}
return malloc(alloc);
}
#define VALID_N 10
static void test_integer_overflow(void)
{
// Invariant: Multiplication of num * size must not overflow before allocation
// We test this by ensuring the function handles boundary cases safely
// Test cases: exploit case, boundary values, valid input
struct {
size_t num;
size_t size;
const char *description;
} test_cases[] = {
// Valid normal input
{ VALID_N, VALID_N, "valid normal input" },
// Exploit case: multiplication overflows to small value
{ SIZE_MAX, 2, "overflow to small allocation" },
// Another overflow case
{ 1ULL << (sizeof(size_t) * 4), 1ULL << (sizeof(size_t) * 4),
"midpoint overflow" },
// Zero allocation (edge case)
{ 0, SIZE_MAX, "zero num" }
};
int num_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_cases; i++) {
printf("num = 0x%zx size = 0x%zx\n", test_cases[i].num,
test_cases[i].size);
// The security property: if multiplication would overflow,
// the function should handle it safely (return NULL or abort)
void *result = clone_cs_kern_os_calloc(test_cases[i].num,
test_cases[i].size);
// For valid inputs, we expect non-NULL (or NULL is also acceptable
// if memory allocation fails for other reasons)
if (test_cases[i].num == VALID_N || test_cases[i].num == 0) {
assert(result != NULL);
free(result);
} else {
assert(result == NULL);
}
}
}
/// Signed left shift overflow when assembling a little-endian SH-DSP
/// parallel instruction word. code[3] is promoted to int and shifted
/// left by 24, which is UB whenever its top bit is set (code[3] >= 0x80).
@ -155,6 +213,7 @@ int main()
test_overflow_cs_insn_bytes();
test_overflow_cs_insn_bytes_iter();
test_overflow_set_reg_mem_n();
test_integer_overflow();
test_ub_shift_sh_dsp_p();
test_ub_isintn_xtensa_offset();