diff options
-rw-r--r-- | src/filegen.c | 59 | ||||
-rw-r--r-- | src/filegen.h | 96 |
2 files changed, 115 insertions, 40 deletions
diff --git a/src/filegen.c b/src/filegen.c index 3be2b2f9..a780a61d 100644 --- a/src/filegen.c +++ b/src/filegen.c @@ -46,6 +46,9 @@ #include "filegen.h" #include "log.h" +uint64_t gpls_nbr=0; +static uint64_t offset_skipped_header=0; + static file_check_t file_check_plist={ .list = TD_LIST_HEAD_INIT(file_check_plist.list) }; @@ -54,8 +57,6 @@ file_check_list_t file_check_list={ .list = TD_LIST_HEAD_INIT(file_check_list.list) }; -uint64_t gpls_nbr=0; - // X requires \valid_read(b); /*@ @ requires \valid_read(a); @@ -127,11 +128,11 @@ static void file_check_add_tail(file_check_t *file_check_new, file_check_list_t td_list_add_tail(&newe->list, &pos->list); } +#ifndef __FRAMAC__ /*@ - @ requires \valid_read((const char *)value + (0 .. length-1)); - @ requires \valid_function(header_check); @ requires separation: \separated(file_stat, &file_check_plist); @*/ +#endif void register_header_check(const unsigned int offset, const void *value, const unsigned int length, int (*header_check)(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), @@ -255,6 +256,7 @@ void file_allow_nl(file_recovery_t *file_recovery, const unsigned int nl_mode) if(my_fseek(file_recovery->handle, file_recovery->file_size,SEEK_SET)<0) { /*@ assert \valid(file_recovery->handle); */ + /*@ assert valid_file_recovery(file_recovery); */ return; } taille=fread(buffer,1, 4096,file_recovery->handle); @@ -268,6 +270,7 @@ void file_allow_nl(file_recovery_t *file_recovery, const unsigned int nl_mode) else if(taille > 0 && buffer[0]=='\r' && (nl_mode&NL_BARECR)==NL_BARECR) file_recovery->file_size++; /*@ assert \valid(file_recovery->handle); */ + /*@ assert valid_file_recovery(file_recovery); */ } uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const unsigned int footer_length) @@ -387,6 +390,7 @@ file_stat_t * init_file_stats(file_enable_t *files_enable) file_enable_t *file_enable; unsigned int enable_count=1; /* Lists are terminated by NULL */ unsigned int sign_nbr; + unsigned int i; /*@ loop assigns enable_count, file_enable; */ for(file_enable=files_enable;file_enable->file_hint!=NULL;file_enable++) { @@ -397,20 +401,20 @@ file_stat_t * init_file_stats(file_enable_t *files_enable) } /*@ assert enable_count > 0; */ file_stats=(file_stat_t *)MALLOC(enable_count * sizeof(file_stat_t)); - enable_count=0; + i=0; for(file_enable=files_enable;file_enable->file_hint!=NULL;file_enable++) { if(file_enable->enable>0 && file_enable->file_hint->register_header_check!=NULL) { - file_stats[enable_count].file_hint=file_enable->file_hint; - file_stats[enable_count].not_recovered=0; - file_stats[enable_count].recovered=0; - file_enable->file_hint->register_header_check(&file_stats[enable_count]); - enable_count++; + file_stats[i].file_hint=file_enable->file_hint; + file_stats[i].not_recovered=0; + file_stats[i].recovered=0; + file_enable->file_hint->register_header_check(&file_stats[i]); + i++; } } sign_nbr=index_header_check(); - file_stats[enable_count].file_hint=NULL; + file_stats[enable_count-1].file_hint=NULL; log_info("%u first-level signatures enabled\n", sign_nbr); return file_stats; } @@ -424,6 +428,7 @@ file_stat_t * init_file_stats(file_enable_t *files_enable) @*/ static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext) { +#ifndef __FRAMAC__ char new_filename[sizeof(file_recovery->filename)]; char *dst; char *dst_dir_sep; @@ -438,7 +443,6 @@ static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext) /*@ assert len <= sizeof(file_recovery->filename); */ /*@ assert valid_read_string((char*)&file_recovery->filename); */ strcpy(new_filename, (char *)&file_recovery->filename); -#ifndef __FRAMAC__ /*@ assert valid_string((char *)&new_filename); */ dst_dir_sep=strrchr(new_filename, '/'); /*@ assert valid_string(dst_dir_sep); */ @@ -611,11 +615,13 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu /* The original filename begins at offset in buffer and is null terminated */ /*@ @ requires \valid(file_recovery); + @ requires valid_file_recovery(file_recovery); @ requires valid_read_string((char*)&file_recovery->filename); @ requires 0 <= offset < buffer_size; @ requires \valid_read((char *)buffer+(0..buffer_size-1)); @ requires new_ext==\null || valid_read_string(new_ext); - @ ensures valid_read_string((char*)&file_recovery->filename); + @ ensures valid_read_string((char*)&file_recovery->filename); + @ ensures valid_file_recovery(file_recovery); @*/ static int _file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext) { @@ -716,6 +722,7 @@ static int _file_rename_unicode(file_recovery_t *file_recovery, const void *buff free(new_filename); #endif /*@ assert valid_read_string(&file_recovery->filename[0]); */ + /*@ assert valid_file_recovery(file_recovery); */ return -1; } @@ -724,13 +731,12 @@ int file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, cons if(buffer!=NULL && 0 <= offset && offset < buffer_size && _file_rename_unicode(file_recovery, buffer, buffer_size, offset, new_ext, append_original_ext)==0) return 0; + /*@ assert valid_file_recovery(file_recovery); */ if(new_ext==NULL) return 0; return file_rename_aux(file_recovery, new_ext); } -static uint64_t offset_skipped_header=0; - /*@ @ assigns offset_skipped_header; @*/ @@ -742,15 +748,22 @@ void header_ignored_cond_reset(uint64_t start, uint64_t end) /* 0: file_recovery_new->location.start has been taken into account, offset_skipped_header may have been updated * 1: file_recovery_new->location.start has been ignored */ +/*@ + @ requires separation: \separated(file_recovery, file_recovery_new, &errno, &offset_skipped_header); + @*/ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery_t *file_recovery_new) { file_recovery_t fr_test; off_t offset; assert(file_recovery!=NULL); assert(file_recovery_new!=NULL); + /*@ assert \valid_read(file_recovery); */ + /*@ assert \valid_read(file_recovery_new); */ if(file_recovery->file_check==NULL) { log_warning("header_ignored_adv: file_check==NULL\n"); + /*@ assert \valid_read(file_recovery); */ + /*@ assert \valid_read(file_recovery_new); */ return 1; } if(file_recovery->handle==NULL) @@ -759,6 +772,8 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery { offset_skipped_header=file_recovery_new->location.start; } + /*@ assert \valid_read(file_recovery); */ + /*@ assert \valid_read(file_recovery_new); */ return 0; } @@ -774,6 +789,8 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0) { log_error("BUG in header_ignored_adv: my_fseek() failed\n"); + /*@ assert \valid_read(file_recovery); */ + /*@ assert \valid_read(file_recovery_new); */ return 1; } if(fr_test.file_size>0) @@ -782,6 +799,8 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery { offset_skipped_header=file_recovery_new->location.start; } + /*@ assert \valid_read(file_recovery); */ + /*@ assert \valid_read(file_recovery_new); */ return 0; } @@ -800,12 +819,19 @@ void header_ignored(const file_recovery_t *file_recovery_new) offset_skipped_header=file_recovery_new->location.start; } +/*@ + @ requires \separated(list_search_space, current_search_space, offset, &gpls_nbr, &offset_skipped_header); + @ assigns gpls_nbr, offset_skipped_header, *current_search_space, *offset; + @*/ void get_prev_location_smart(const alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const uint64_t prev_location) { alloc_data_t *file_space=*current_search_space; if(offset_skipped_header==0) return ; gpls_nbr++; + /*@ + @ loop assigns file_space, offset_skipped_header, *current_search_space, *offset; + @*/ while(1) { file_space=td_list_prev_entry(file_space, list); @@ -826,6 +852,9 @@ void get_prev_location_smart(const alloc_data_t *list_search_space, alloc_data_t (long long unsigned)(offset_skipped_header/512), (long long unsigned)(*offset/512)); #endif + /*@ + @ loop assigns file_space, offset_skipped_header, *current_search_space, *offset; + @*/ while(1) { file_space=td_list_prev_entry(file_space, list); diff --git a/src/filegen.h b/src/filegen.h index 6ced8ea8..0428f51f 100644 --- a/src/filegen.h +++ b/src/filegen.h @@ -40,9 +40,20 @@ extern "C" { typedef enum { DC_SCAN=0, DC_CONTINUE=1, DC_STOP=2, DC_ERROR=3} data_check_t; typedef struct file_hint_struct file_hint_t; +typedef struct file_stat_struct file_stat_t; typedef struct file_recovery_struct file_recovery_t; typedef struct file_enable_struct file_enable_t; -typedef struct file_stat_struct file_stat_t; + +struct file_hint_struct +{ + const char *extension; + const char *description; + const uint64_t max_filesize; + const int recover; + const unsigned int enable_by_default; + void (*register_header_check)(file_stat_t *file_stat); +}; + typedef struct { struct td_list_head list; @@ -80,7 +91,7 @@ struct file_recovery_struct uint64_t extra; /* extra bytes between offset_ok and offset_error */ uint64_t calculated_file_size; data_check_t (*data_check)(const unsigned char*buffer, const unsigned int buffer_size, file_recovery_t *file_recovery); - /* data_check modifies file_recovery->calculated_file_size but not must alter file_recovery->file_size */ + /* data_check modifies file_recovery->calculated_file_size, it can also update data_check, file_check, offset_error */ void (*file_check)(file_recovery_t *file_recovery); void (*file_rename)(file_recovery_t *file_recovery); uint64_t checkpoint_offset; @@ -89,16 +100,6 @@ struct file_recovery_struct unsigned int flags; }; -struct file_hint_struct -{ - const char *extension; - const char *description; - const uint64_t max_filesize; - const int recover; - const unsigned int enable_by_default; - void (*register_header_check)(file_stat_t *file_stat); -}; - typedef struct { struct td_list_head list; @@ -121,11 +122,35 @@ typedef struct #define NL_CRLF (1 << 1) #define NL_BARECR (1 << 2) +/*@ + predicate valid_file_hint(file_hint_t *file_hint) = (\valid_read(file_hint) && valid_read_string(file_hint->description)); + @*/ + +/*@ + predicate valid_file_stat(file_stat_t *file_stat) = (\valid_read(file_stat) && valid_file_hint(file_stat->file_hint)); + @*/ + +/*@ + predicate valid_file_recovery(file_recovery_t *file_recovery) = (\valid_read(file_recovery) && + valid_read_string((const char *)file_recovery->filename) && + (file_recovery->file_stat == \null || valid_file_stat(file_recovery->file_stat)) && + (file_recovery->handle == \null || \valid(file_recovery->handle)) && + (file_recovery->extension == \null || valid_read_string(file_recovery->extension)) && + (file_recovery->data_check == \null || \valid_function(file_recovery->data_check)) && + (file_recovery->file_check == \null || \valid_function(file_recovery->file_check)) && + (file_recovery->file_rename == \null || \valid_function(file_recovery->file_rename)) + ); + @*/ +/*@ + predicate valid_list_search_space(alloc_data_t *list) = (\valid_read(list) && \valid(list->list.prev) && \valid_read(list->list.next)); + @*/ + void free_header_check(void); /*@ @ requires \valid(file_recovery); @ requires \valid(file_recovery->handle); + @ requires valid_file_recovery(file_recovery); @ requires \separated(file_recovery, file_recovery->handle, &errno, &Frama_C_entropy_source); @ ensures file_recovery->handle == \old(file_recovery->handle); @ assigns *file_recovery->handle, errno, Frama_C_entropy_source, file_recovery->file_size; @@ -144,10 +169,12 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un /*@ @ requires \valid(file_recovery); @ requires \valid(file_recovery->handle); + @ requires valid_file_recovery(file_recovery); @ requires 0 < footer_length < 4096; @ requires \valid_read((char *)footer+(0..footer_length-1)); @ requires \separated(file_recovery, file_recovery->handle, file_recovery->extension, &errno, &Frama_C_entropy_source); @ ensures \valid(file_recovery->handle); + @ ensures valid_file_recovery(file_recovery); @ assigns *file_recovery->handle, errno, file_recovery->file_size; @ assigns Frama_C_entropy_source; @*/ @@ -159,29 +186,39 @@ void file_search_footer(file_recovery_t *file_recovery, const void*footer, const @ requires \valid_read((char *)buffer+(0..buffer_size-1)); @ requires \valid(file_recovery); @ requires file_recovery->data_check == &data_check_size; - @ ensures \result == DC_STOP || \result == DC_CONTINUE; - @ ensures file_recovery->data_check == &data_check_size; - @ assigns \nothing; + @ requires valid_file_recovery(file_recovery); + @ requires \initialized(&file_recovery->file_size); + @ requires \initialized(&file_recovery->calculated_file_size); + @ ensures valid_file_recovery(file_recovery); + @ ensures \result == DC_STOP || \result == DC_CONTINUE; + @ ensures file_recovery->data_check == &data_check_size; + @ assigns \nothing; @*/ data_check_t data_check_size(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery); /*@ @ requires \valid(file_recovery); @ requires file_recovery->file_check == &file_check_size; - @ assigns file_recovery->file_size; + @ requires valid_file_recovery(file_recovery); + @ ensures valid_file_recovery(file_recovery); + @ assigns file_recovery->file_size; @*/ void file_check_size(file_recovery_t *file_recovery); /*@ @ requires \valid(file_recovery); @ requires file_recovery->file_check == &file_check_size_min; - @ assigns file_recovery->file_size; + @ requires valid_file_recovery(file_recovery); + @ ensures valid_file_recovery(file_recovery); + @ assigns file_recovery->file_size; @*/ void file_check_size_min(file_recovery_t *file_recovery); /*@ @ requires \valid(file_recovery); @ requires file_recovery->file_check == &file_check_size_max; + @ requires valid_file_recovery(file_recovery); + @ ensures valid_file_recovery(file_recovery); @ assigns file_recovery->file_size; @*/ void file_check_size_max(file_recovery_t *file_recovery); @@ -231,12 +268,13 @@ void file_check_size_max(file_recovery_t *file_recovery); assigns file_recovery->flags; assigns file_recovery->extra; */ +// ensures valid_file_recovery(file_recovery); void reset_file_recovery(file_recovery_t *file_recovery); /*@ @ requires offset < 0x80000000; @ requires 0 < length <= 4096; - @ requires \valid_read((char *)value+(0..length-1)); + @ requires \valid_read((const char *)value+(0..length-1)); @ requires \valid_function(header_check); @ requires \valid(file_stat); @*/ @@ -253,10 +291,12 @@ file_stat_t * init_file_stats(file_enable_t *files_enable); /*@ @ requires \valid(file_recovery); @ requires valid_read_string((char*)&file_recovery->filename); + @ requires valid_file_recovery(file_recovery); @ requires \valid_read((char *)buffer+(0..buffer_size-1)); @ requires new_ext==\null || valid_read_string(new_ext); - @ ensures valid_read_string((char*)&file_recovery->filename); + @ ensures valid_read_string((char*)&file_recovery->filename); @*/ +// ensures valid_file_recovery(file_recovery); int file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int force_ext); /*@ @@ -264,14 +304,16 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu @ requires valid_read_string((char*)&file_recovery->filename); @ requires \valid_read((char *)buffer+(0..buffer_size-1)); @ requires new_ext==\null || valid_read_string(new_ext); + @ requires valid_file_recovery(file_recovery); @ ensures valid_read_string((char*)&file_recovery->filename); @*/ +// ensures valid_file_recovery(file_recovery); int file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int force_ext); void header_ignored_cond_reset(uint64_t start, uint64_t end); /*@ - @ requires file_recovery_new==\null || \valid_read(file_recovery_new); + @ requires file_recovery_new==\null || valid_file_recovery(file_recovery_new); @*/ void header_ignored(const file_recovery_t *file_recovery_new); @@ -279,23 +321,26 @@ void header_ignored(const file_recovery_t *file_recovery_new); @ requires separation: \separated(file_recovery, file_recovery_new, &errno); @ requires \valid_read(file_recovery); @ requires \valid_read(file_recovery_new); - @ requires file_recovery->handle == \null || \valid(file_recovery->handle); + @ requires valid_file_recovery(file_recovery); + @ requires valid_file_recovery(file_recovery_new); @ requires \valid_function(file_recovery->file_check); @ requires \initialized(&file_recovery->file_check); @ requires \initialized(&file_recovery->handle); @ requires \separated(file_recovery, file_recovery->handle); @ ensures \result == 0 || \result == 1; @*/ +// ensures valid_file_recovery(file_recovery); +// ensures valid_file_recovery(file_recovery_new); int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery_t *file_recovery_new); /*@ requires valid_stream: \valid(stream); requires whence_enum: whence == SEEK_SET || whence == SEEK_CUR || whence == SEEK_END; requires \separated(&errno, stream); - assigns *stream \from *stream, indirect:offset, indirect:whence; - assigns \result, errno \from indirect:*stream, indirect:offset, - indirect:whence; + assigns *stream, \result, errno; */ +// assigns *stream \from *stream, indirect:offset, indirect:whence; +// assigns \result, errno \from indirect:*stream, indirect:offset, indirect:whence; int my_fseek(FILE *stream, off_t offset, int whence); /*@ @@ -323,9 +368,10 @@ time_t get_time_from_YYYY_MM_DD_HHMMSS(const char *date_asc); time_t get_time_from_YYYYMMDD_HHMMSS(const char *date_asc); /*@ - @ requires \valid(list_search_space); + @ requires \valid_read(list_search_space); @ requires \valid(current_search_space); @ requires \valid(offset); + @ requires \separated(list_search_space, current_search_space, offset); @*/ void get_prev_location_smart(const alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const uint64_t prev_location); |