From e198d23504d6f2a086e2ef768d9300ab94f3299e Mon Sep 17 00:00:00 2001 From: Michael Beutler Date: Thu, 23 Jul 2026 07:24:41 -0400 Subject: [PATCH 1/2] Fixed recovered index allocation range check --- libpff/libpff_recover.c | 92 +++++++++++++++------ libpff/libpff_recover.h | 6 +- tests/Makefile.am | 2 +- tests/pff_test_offsets_index.c | 143 ++++++++++++++++++++++++++++++++- 4 files changed, 214 insertions(+), 29 deletions(-) diff --git a/libpff/libpff_recover.c b/libpff/libpff_recover.c index 55739ee9..6b8b1ec5 100644 --- a/libpff/libpff_recover.c +++ b/libpff/libpff_recover.c @@ -1415,6 +1415,7 @@ int libpff_recover_check_descriptors_index_for_recovered_value( return( result ); } + /* Recovers descriptors index values * Returns 1 if successful or -1 on error */ @@ -3042,18 +3043,15 @@ int libpff_recover_index_values( uint8_t recovery_flags, libcerror_error_t **error ) { - libpff_index_node_t *index_node = NULL; - libpff_index_value_t *index_value = NULL; - uint8_t *node_entry_data = NULL; - static char *function = "libpff_recover_index_values"; - const char *index_string = NULL; - off64_t index_value_file_offset = 0; - uint64_t index_value_identifier = 0; - uint32_t maximum_data_block_data_size = 0; - uint16_t index_value_data_size = 0; - uint8_t entry_index = 0; - int recoverable = 0; - int result = 0; + libpff_index_node_t *index_node = NULL; + libpff_index_value_t *index_value = NULL; + uint8_t *node_entry_data = NULL; + static char *function = "libpff_recover_index_values"; + const char *index_string = NULL; + uint32_t maximum_data_block_data_size = 0; + uint8_t entry_index = 0; + int recoverable = 0; + int result = 0; if( io_handle == NULL ) { @@ -3314,10 +3312,9 @@ int libpff_recover_index_values( if( ( index_node->type == LIBPFF_INDEX_TYPE_OFFSET ) && ( ( recovery_flags & LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA ) == 0 ) ) { - result = libcdata_range_list_range_is_present( + result = libpff_recover_index_value_range_is_unallocated( unallocated_data_block_list, - (uint64_t) index_value_file_offset, - (uint64_t) index_value_data_size, + index_value, error ); if( result == -1 ) @@ -3341,10 +3338,10 @@ int libpff_recover_index_values( function, index_string, entry_index, - index_value_identifier, - index_value_file_offset, - index_value_file_offset + index_value_data_size, - index_value_data_size ); + index_value->identifier, + index_value->file_offset, + index_value->file_offset + index_value->data_size, + index_value->data_size ); } #endif recoverable = 0; @@ -3357,10 +3354,10 @@ int libpff_recover_index_values( function, index_string, entry_index, - index_value_identifier, - index_value_file_offset, - index_value_file_offset + index_value_data_size, - index_value_data_size ); + index_value->identifier, + index_value->file_offset, + index_value->file_offset + index_value->data_size, + index_value->data_size ); } #endif } @@ -3377,7 +3374,7 @@ int libpff_recover_index_values( function, index_string, entry_index, - index_value_identifier ); + index_value->identifier ); } #endif if( index_node->type == LIBPFF_INDEX_TYPE_DESCRIPTOR ) @@ -3403,7 +3400,7 @@ int libpff_recover_index_values( "%s: unable to insert recovered %s index value: %" PRIu64 " list.", function, index_string, - index_value_identifier ); + index_value->identifier ); goto on_error; } @@ -3466,6 +3463,50 @@ int libpff_recover_index_values( return( -1 ); } +/* Determines if the data range referenced by an offsets index value is + * unallocated. + * Returns 1 if unallocated, 0 if allocated or -1 on error. + */ +int libpff_recover_index_value_range_is_unallocated( + libcdata_range_list_t *unallocated_data_block_list, + libpff_index_value_t *index_value, + libcerror_error_t **error ) +{ + static char *function = "libpff_recover_index_value_range_is_unallocated"; + + if( unallocated_data_block_list == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid unallocated data block list.", + function ); + + return( -1 ); + } + if( index_value == NULL ) + { + libcerror_error_set( + error, + LIBCERROR_ERROR_DOMAIN_ARGUMENTS, + LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE, + "%s: invalid index value.", + function ); + + return( -1 ); + } + if( index_value->file_offset < 0 ) + { + return( 0 ); + } + return( libcdata_range_list_range_is_present( + unallocated_data_block_list, + (uint64_t) index_value->file_offset, + (uint64_t) index_value->data_size, + error ) ); +} + /* Reads the index value data * Returns 1 if successful, returns 0 if not or -1 on error */ @@ -4240,4 +4281,3 @@ int libpff_recover_analyze_local_descriptors( #endif return( result ); } - diff --git a/libpff/libpff_recover.h b/libpff/libpff_recover.h index b0adf23b..5da2ee26 100644 --- a/libpff/libpff_recover.h +++ b/libpff/libpff_recover.h @@ -132,6 +132,11 @@ int libpff_recover_index_values( uint8_t recovery_flags, libcerror_error_t **error ); +int libpff_recover_index_value_range_is_unallocated( + libcdata_range_list_t *unallocated_data_block_list, + libpff_index_value_t *index_value, + libcerror_error_t **error ); + int libpff_recover_index_value_read_data( libpff_index_value_t *index_value, libpff_io_handle_t *io_handle, @@ -160,4 +165,3 @@ int libpff_recover_analyze_local_descriptors( #endif #endif /* !defined( _LIBPFF_RECOVER_H ) */ - diff --git a/tests/Makefile.am b/tests/Makefile.am index 460483ad..dad5ff19 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -641,6 +641,7 @@ pff_test_notify_LDADD = \ @LIBCERROR_LIBADD@ pff_test_offsets_index_SOURCES = \ + pff_test_libcdata.h \ pff_test_libcerror.h \ pff_test_libpff.h \ pff_test_macros.h \ @@ -919,4 +920,3 @@ DISTCLEANFILES = \ atconfig \ Makefile \ Makefile.in - diff --git a/tests/pff_test_offsets_index.c b/tests/pff_test_offsets_index.c index f1203807..878985de 100644 --- a/tests/pff_test_offsets_index.c +++ b/tests/pff_test_offsets_index.c @@ -27,6 +27,7 @@ #include #endif +#include "pff_test_libcdata.h" #include "pff_test_libcerror.h" #include "pff_test_libpff.h" #include "pff_test_macros.h" @@ -36,6 +37,7 @@ #include "../libpff/libpff_index_value.h" #include "../libpff/libpff_io_handle.h" #include "../libpff/libpff_offsets_index.h" +#include "../libpff/libpff_recover.h" #if defined( __GNUC__ ) && !defined( LIBPFF_DLL_IMPORT ) @@ -440,6 +442,142 @@ PFF_TEST_FPRINT_ERROR( error ); return( 0 ); } +/* Tests recovered offset index allocation range validation. + * Returns 1 if successful or 0 if not. + */ +int pff_test_recover_index_value_range_is_unallocated( + void ) +{ + libcdata_range_list_t *unallocated_data_block_list = NULL; + libcerror_error_t *error = NULL; + libpff_index_value_t *index_value = NULL; + int result = 0; + + result = libcdata_range_list_initialize( + &unallocated_data_block_list, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + result = libcdata_range_list_insert_range( + unallocated_data_block_list, + 4096, + 8192, + NULL, + NULL, + NULL, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + result = libpff_index_value_initialize( + &index_value, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + index_value->file_offset = 4096; + index_value->data_size = 512; + + result = libpff_recover_index_value_range_is_unallocated( + unallocated_data_block_list, + index_value, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + PFF_TEST_ASSERT_IS_NULL( + "error", + error ); + + index_value->file_offset = 12288; + + result = libpff_recover_index_value_range_is_unallocated( + unallocated_data_block_list, + index_value, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 0 ); + + result = libpff_recover_index_value_range_is_unallocated( + NULL, + index_value, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + -1 ); + + PFF_TEST_ASSERT_IS_NOT_NULL( + "error", + error ); + + libcerror_error_free( + &error ); + + result = libpff_index_value_free( + &index_value, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + result = libcdata_range_list_free( + &unallocated_data_block_list, + NULL, + &error ); + + PFF_TEST_ASSERT_EQUAL_INT( + "result", + result, + 1 ); + + PFF_TEST_ASSERT_IS_NULL( + "error", + error ); + + return( 1 ); + +on_error: + if( error != NULL ) + { + libcerror_error_free( + &error ); + } + if( index_value != NULL ) + { + libpff_index_value_free( + &index_value, + NULL ); + } + if( unallocated_data_block_list != NULL ) + { + libcdata_range_list_free( + &unallocated_data_block_list, + NULL, + NULL ); + } + return( 0 ); +} + #endif /* defined( __GNUC__ ) && !defined( LIBPFF_DLL_IMPORT ) */ /* The main program @@ -471,6 +609,10 @@ int main( "libpff_offsets_index_get_index_value_by_identifier", pff_test_offsets_index_get_index_value_by_identifier ); + PFF_TEST_RUN( + "libpff_recover_index_value_range_is_unallocated", + pff_test_recover_index_value_range_is_unallocated ); + #endif /* defined( __GNUC__ ) && !defined( LIBPFF_DLL_IMPORT ) */ return( EXIT_SUCCESS ); @@ -482,4 +624,3 @@ int main( #endif /* defined( __GNUC__ ) && !defined( LIBPFF_DLL_IMPORT ) */ } - From 101d631e4077cca26e26223a576eb78626ad49a3 Mon Sep 17 00:00:00 2001 From: Michael Beutler Date: Sun, 26 Jul 2026 18:40:54 -0400 Subject: [PATCH 2/2] tests: link libcdata in offsets index test --- tests/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile.am b/tests/Makefile.am index dad5ff19..9c895f52 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -650,6 +650,7 @@ pff_test_offsets_index_SOURCES = \ pff_test_unused.h pff_test_offsets_index_LDADD = \ + @LIBCDATA_LIBADD@ \ ../libpff/libpff.la \ @LIBCERROR_LIBADD@