diff --git a/libyara/arena.c b/libyara/arena.c index 20ddf9d1..749e56d7 100644 --- a/libyara/arena.c +++ b/libyara/arena.c @@ -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]; diff --git a/libyara/rules.c b/libyara/rules.c index 84e8ce07..63dda704 100644 --- a/libyara/rules.c +++ b/libyara/rules.c @@ -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); diff --git a/tests/test-api.c b/tests/test-api.c index 59d7829e..ccc6ab57 100644 --- a/tests/test-api.c +++ b/tests/test-api.c @@ -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(); diff --git a/tests/test-arena.c b/tests/test-arena.c index be5439f8..b70d6d32 100644 --- a/tests/test-arena.c +++ b/tests/test-arena.c @@ -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]);