summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Grenier <[email protected]>2021-01-29 19:29:35 +0100
committerChristophe Grenier <[email protected]>2021-01-29 19:29:35 +0100
commitc1be5b4ac21dd9270fbbcffd7fe1159a714db0e2 (patch)
tree2878f03c193ae5effbafe7e96ae7eca2adb7970f
parent5d914f2a450a17e4de74757d2a27d2ed16a4c026 (diff)
src/filegen.[ch]: update frama-c annotations
-rw-r--r--src/filegen.c59
-rw-r--r--src/filegen.h96
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);