alloc: guard calloc size overflow

This commit is contained in:
CinderSocket
2026-06-17 16:09:15 -07:00
parent 4536c81e75
commit 477aebd9f1
5 changed files with 51 additions and 2 deletions
+1
View File
@@ -40,6 +40,7 @@ test-host:
board_power_lifecycle.c \
sam_startup_ui.c \
ccid_logic.c \
allocation_policy.c \
credential_sio_label.c \
t_1_logic.c \
t_1.c \
+16
View File
@@ -0,0 +1,16 @@
#include "allocation_policy.h"
#include <stdint.h>
bool seader_size_multiply_checked(size_t count, size_t size, size_t* out) {
if(!out) {
return false;
}
if(count != 0U && size > SIZE_MAX / count) {
return false;
}
*out = count * size;
return true;
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
bool seader_size_multiply_checked(size_t count, size_t size, size_t* out);
+20
View File
@@ -1,6 +1,8 @@
#include <string.h>
#include <stdint.h>
#include "munit.h"
#include "allocation_policy.h"
#include "runtime_policy.h"
#include "seader_hf_read_plan.h"
@@ -296,6 +298,23 @@ static MunitResult test_virtual_credential_loop_terminal_policy(
return MUNIT_OK;
}
static MunitResult test_checked_size_multiply_rejects_overflow(
const MunitParameter params[],
void* fixture) {
(void)params;
(void)fixture;
size_t total_size = 0U;
munit_assert_true(seader_size_multiply_checked(4U, 8U, &total_size));
munit_assert_size(total_size, ==, 32U);
total_size = 123U;
munit_assert_false(seader_size_multiply_checked(SIZE_MAX, 2U, &total_size));
munit_assert_size(total_size, ==, 123U);
munit_assert_false(seader_size_multiply_checked(1U, 1U, NULL));
return MUNIT_OK;
}
static MunitTest test_runtime_policy_cases[] = {
{(char*)"/reset-sam-metadata", test_reset_cached_sam_metadata_clears_all_fields, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{(char*)"/begin-uhf-probe", test_begin_uhf_probe_sets_runtime_and_initializes_probe, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
@@ -309,6 +328,7 @@ static MunitTest test_runtime_policy_cases[] = {
{(char*)"/reset-hf-mode", test_reset_hf_mode_clears_selection_and_detected_types, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{(char*)"/cancel-hf-type-prompt", test_cancel_hf_type_prompt_resets_future_read_to_full_polling, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{(char*)"/virtual-credential-terminal-policy", test_virtual_credential_loop_terminal_policy, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{(char*)"/checked-size-multiply", test_checked_size_multiply_rejects_overflow, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL},
{NULL, NULL, NULL, NULL, 0, NULL},
};
+8 -2
View File
@@ -7,6 +7,7 @@
#include "uhf_snmp_probe.h"
#include "card_details_builder.h"
#include "uhf_status_label.h"
#include "allocation_policy.h"
#include <toolbox/path.h>
#include <toolbox/version.h>
#include <bit_lib/bit_lib.h>
@@ -341,9 +342,14 @@ uint8_t select_desfire_app_no_le[] =
uint8_t FILE_NOT_FOUND[] = {0x6a, 0x82};
void* calloc(size_t count, size_t size) {
void* ptr = malloc(count * size);
size_t total_size = 0U;
if(!seader_size_multiply_checked(count, size, &total_size)) {
return NULL;
}
void* ptr = malloc(total_size);
if(ptr) {
memset(ptr, 0, count * size);
memset(ptr, 0, total_size);
}
return ptr;
}