mirror of
https://github.com/VirusTotal/yara.git
synced 2026-10-12 02:10:00 +00:00
fix: validate arena buffer count
Ensure `YR_ARENA` objects are created, loaded, and accessed with a valid number of buffers. This prevents out-of-bounds memory access and improves robustness against corrupted arena data or incorrect API usage. Closes #2238.
This commit is contained in:
+6
-3
@@ -137,7 +137,7 @@ static int _yr_arena_allocate_memory(
|
||||
size_t size,
|
||||
YR_ARENA_REF* ref)
|
||||
{
|
||||
if (buffer_id > arena->num_buffers)
|
||||
if (buffer_id >= arena->num_buffers)
|
||||
return ERROR_INVALID_ARGUMENT;
|
||||
|
||||
YR_ARENA_BUFFER* b = &arena->buffers[buffer_id];
|
||||
@@ -234,6 +234,9 @@ int yr_arena_create(
|
||||
size_t initial_buffer_size,
|
||||
YR_ARENA** arena)
|
||||
{
|
||||
if (num_buffers == 0 || num_buffers > YR_MAX_ARENA_BUFFERS)
|
||||
return ERROR_INVALID_ARGUMENT;
|
||||
|
||||
YR_ARENA* new_arena = (YR_ARENA*) yr_calloc(1, sizeof(YR_ARENA));
|
||||
|
||||
if (new_arena == NULL)
|
||||
@@ -555,8 +558,8 @@ int yr_arena_load_stream(YR_STREAM* stream, YR_ARENA** arena)
|
||||
if (hdr.version != YR_ARENA_FILE_VERSION)
|
||||
return ERROR_UNSUPPORTED_FILE_VERSION;
|
||||
|
||||
if (hdr.num_buffers > YR_MAX_ARENA_BUFFERS)
|
||||
return ERROR_INVALID_FILE;
|
||||
if (hdr.num_buffers == 0 || hdr.num_buffers > YR_MAX_ARENA_BUFFERS)
|
||||
return ERROR_CORRUPT_FILE;
|
||||
|
||||
YR_ARENA_FILE_BUFFER buffers[YR_MAX_ARENA_BUFFERS];
|
||||
|
||||
|
||||
@@ -325,6 +325,9 @@ YR_API int yr_rules_scan_proc(
|
||||
|
||||
int yr_rules_from_arena(YR_ARENA* arena, YR_RULES** rules)
|
||||
{
|
||||
if (arena->num_buffers < YR_NUM_SECTIONS)
|
||||
return ERROR_CORRUPT_FILE;
|
||||
|
||||
YR_SUMMARY* summary = (YR_SUMMARY*) yr_arena_get_ptr(
|
||||
arena, YR_SUMMARY_SECTION, 0);
|
||||
|
||||
|
||||
@@ -886,6 +886,55 @@ void test_load_rules_corrupt_ac_transition()
|
||||
yr_finalize();
|
||||
}
|
||||
|
||||
void test_load_rules_corrupt_num_buffers()
|
||||
{
|
||||
yr_initialize();
|
||||
|
||||
// Test num_buffers = 0
|
||||
uint8_t data0[] = {'Y', 'A', 'R', 'A', YR_ARENA_FILE_VERSION, 0, 4, 0};
|
||||
FILE* fh = fopen("test-corrupt-num0.yarc", "wb");
|
||||
assert_true_expr(fh != NULL);
|
||||
assert_true_expr(fwrite(data0, 1, sizeof(data0), fh) == sizeof(data0));
|
||||
fclose(fh);
|
||||
|
||||
YR_RULES* rules = NULL;
|
||||
int result = yr_rules_load("test-corrupt-num0.yarc", &rules);
|
||||
if (result != ERROR_CORRUPT_FILE)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"test_load_rules_corrupt_num_buffers (num_buffers=0): expecting "
|
||||
"ERROR_CORRUPT_FILE, got %d\n",
|
||||
result);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Test num_buffers = 1 (fewer than YR_NUM_SECTIONS)
|
||||
uint8_t data1[6 + 12];
|
||||
memset(data1, 0, sizeof(data1));
|
||||
memcpy(data1, "YARA", 4);
|
||||
data1[4] = YR_ARENA_FILE_VERSION;
|
||||
data1[5] = 1;
|
||||
|
||||
fh = fopen("test-corrupt-num1.yarc", "wb");
|
||||
assert_true_expr(fh != NULL);
|
||||
assert_true_expr(fwrite(data1, 1, sizeof(data1), fh) == sizeof(data1));
|
||||
fclose(fh);
|
||||
|
||||
result = yr_rules_load("test-corrupt-num1.yarc", &rules);
|
||||
if (result != ERROR_CORRUPT_FILE)
|
||||
{
|
||||
fprintf(
|
||||
stderr,
|
||||
"test_load_rules_corrupt_num_buffers (num_buffers=1): expecting "
|
||||
"ERROR_CORRUPT_FILE, got %d\n",
|
||||
result);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
yr_finalize();
|
||||
}
|
||||
|
||||
void test_scanner()
|
||||
{
|
||||
const char* buf = "dummy";
|
||||
@@ -1521,6 +1570,7 @@ int main(int argc, char** argv)
|
||||
test_load_rules_corrupt_summary();
|
||||
test_load_rules_bad_external_type();
|
||||
test_load_rules_corrupt_ac_transition();
|
||||
test_load_rules_corrupt_num_buffers();
|
||||
test_scanner();
|
||||
test_xor_key_string_in_atom();
|
||||
test_ast_callback();
|
||||
|
||||
+49
-1
@@ -39,11 +39,19 @@ static void basic_tests()
|
||||
|
||||
yr_initialize();
|
||||
|
||||
// Create arena with 1 buffers of 10 bytes of initial size
|
||||
assert_true_expr(yr_arena_create(0, 10, &arena) == ERROR_INVALID_ARGUMENT);
|
||||
assert_true_expr(
|
||||
yr_arena_create(YR_MAX_ARENA_BUFFERS + 1, 10, &arena) ==
|
||||
ERROR_INVALID_ARGUMENT);
|
||||
|
||||
// Create arena with 2 buffers of 10 bytes of initial size
|
||||
assert_true_expr(yr_arena_create(2, 10, &arena) == ERROR_SUCCESS);
|
||||
|
||||
YR_ARENA_REF ref;
|
||||
|
||||
assert_true_expr(
|
||||
yr_arena_allocate_memory(arena, 2, 5, &ref) == ERROR_INVALID_ARGUMENT);
|
||||
|
||||
// Allocate 5 bytes.
|
||||
assert_true_expr(
|
||||
yr_arena_allocate_memory(arena, 0, 5, &ref) == ERROR_SUCCESS);
|
||||
@@ -330,6 +338,45 @@ static void corrupt_reloc_target_tests()
|
||||
yr_finalize();
|
||||
}
|
||||
|
||||
static void corrupt_num_buffers_tests()
|
||||
{
|
||||
yr_initialize();
|
||||
|
||||
// Test loading with num_buffers = 0
|
||||
uint8_t data[6] = {'Y', 'A', 'R', 'A', YR_ARENA_FILE_VERSION, 0};
|
||||
FILE* fh = fopen("test-arena-corrupt-num0", "w+b");
|
||||
assert_true_expr(fh != NULL);
|
||||
fwrite(data, 1, sizeof(data), fh);
|
||||
fflush(fh);
|
||||
fseek(fh, 0, SEEK_SET);
|
||||
|
||||
YR_STREAM stream;
|
||||
stream.user_data = fh;
|
||||
stream.read = (YR_STREAM_READ_FUNC) fread;
|
||||
stream.write = (YR_STREAM_WRITE_FUNC) fwrite;
|
||||
|
||||
YR_ARENA* arena = NULL;
|
||||
assert_true_expr(
|
||||
yr_arena_load_stream(&stream, &arena) == ERROR_CORRUPT_FILE);
|
||||
|
||||
fclose(fh);
|
||||
|
||||
// Test loading with num_buffers > YR_MAX_ARENA_BUFFERS
|
||||
data[5] = YR_MAX_ARENA_BUFFERS + 1;
|
||||
fh = fopen("test-arena-corrupt-num-max", "w+b");
|
||||
assert_true_expr(fh != NULL);
|
||||
fwrite(data, 1, sizeof(data), fh);
|
||||
fflush(fh);
|
||||
fseek(fh, 0, SEEK_SET);
|
||||
|
||||
stream.user_data = fh;
|
||||
assert_true_expr(
|
||||
yr_arena_load_stream(&stream, &arena) == ERROR_CORRUPT_FILE);
|
||||
|
||||
fclose(fh);
|
||||
yr_finalize();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -342,6 +389,7 @@ int main(int argc, char** argv)
|
||||
corrupt_stream_tests();
|
||||
corrupt_reloc_offset_tests();
|
||||
corrupt_reloc_target_tests();
|
||||
corrupt_num_buffers_tests();
|
||||
|
||||
YR_DEBUG_FPRINTF(
|
||||
1, stderr, "} = %d // %s() in %s\n", result, __FUNCTION__, argv[0]);
|
||||
|
||||
Reference in New Issue
Block a user