diff --git a/src/file_par2.c b/src/file_par2.c index 36c66620..dbe4739e 100644 --- a/src/file_par2.c +++ b/src/file_par2.c @@ -33,6 +33,7 @@ #include "common.h" #include "log.h" +/*@ requires \valid(file_stat); */ static void register_header_check_par2(file_stat_t *file_stat); const file_hint_t file_hint_par2= { @@ -48,22 +49,38 @@ static const unsigned char par2_header[8]= { 'P' , 'A' , 'R' , '2' , 0x00, 'P' , 'K' , 'T' }; +/*@ + @ requires buffer_size >= 2 && (buffer_size&1)==0; + @ requires \valid(file_recovery); + @ requires \valid_read(buffer + ( 0 .. buffer_size-1)); + @ requires file_recovery->data_check == &data_check_par2; + @ requires separation: \separated(buffer+(..), file_recovery); + @ ensures \result == DC_CONTINUE || \result == DC_STOP; + @ assigns file_recovery->calculated_file_size; + @*/ static data_check_t data_check_par2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery) { + /*@ loop assigns file_recovery->calculated_file_size; */ while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size && file_recovery->calculated_file_size + 16 < file_recovery->file_size + buffer_size/2) { - const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2; + const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size; + /*@ assert 0 <= i < buffer_size - 16; */ const uint64_t length=le64((*(const uint64_t *)(&buffer[i+8]))); if(memcmp(&buffer[i], &par2_header, sizeof(par2_header))!=0) return DC_STOP; - if(length % 4 !=0 || length < 16) + if(length % 4 !=0 || length < 16 || length > PHOTOREC_MAX_FILE_SIZE) return DC_STOP; file_recovery->calculated_file_size+=length; } return DC_CONTINUE; } +/*@ + @ requires \valid(file_recovery); + @ requires valid_file_recovery(file_recovery); + @ requires file_recovery->file_rename==&file_rename_par2; + @*/ static void file_rename_par2(file_recovery_t *file_recovery) { FILE *file; @@ -106,6 +123,16 @@ static void file_rename_par2(file_recovery_t *file_recovery) } } +/*@ + @ requires buffer_size >= 16; + @ requires \valid_read(buffer+(0..buffer_size-1)); + @ requires valid_file_recovery(file_recovery); + @ requires \valid(file_recovery_new); + @ requires file_recovery_new->blocksize > 0; + @ requires separation: \separated(&file_hint_par2, buffer+(..), file_recovery, file_recovery_new); + @ ensures \result == 0 || \result == 1; + @ ensures \result!=0 ==> valid_file_recovery(file_recovery_new); + @*/ static int header_check_par2(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new) { const uint64_t length=le64((*(const uint64_t *)(&buffer[8])));