summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am57
-rw-r--r--src/addpart.h8
-rw-r--r--src/adv.c89
-rw-r--r--src/adv.h10
-rw-r--r--src/alignio.h64
-rw-r--r--src/analyse.c2
-rw-r--r--src/analyse.h2
-rw-r--r--src/askloc.h4
-rw-r--r--src/autoset.h4
-rw-r--r--src/bfs.c56
-rw-r--r--src/bfs.h15
-rw-r--r--src/bsd.c43
-rw-r--r--src/bsd.h18
-rw-r--r--src/btrfs.c2
-rw-r--r--src/btrfs.h2
-rw-r--r--src/chgarch.h5
-rw-r--r--src/common.c102
-rw-r--r--src/common.h115
-rw-r--r--src/cramfs.c2
-rw-r--r--src/cramfs.h2
-rw-r--r--src/crc.c1
-rw-r--r--src/crc.h4
-rw-r--r--src/dfxml.c24
-rw-r--r--src/dfxml.h2
-rw-r--r--src/dimage.c5
-rw-r--r--src/dir.c4
-rw-r--r--src/dir.h9
-rw-r--r--src/dirn.c14
-rw-r--r--src/ewf.c243
-rw-r--r--src/ewf.h4
-rw-r--r--src/ext2.c2
-rw-r--r--src/ext2.h2
-rw-r--r--src/ext2_dir.c10
-rw-r--r--src/ext2_inc.h4
-rw-r--r--src/ext2_sb.c2
-rw-r--r--src/ext2_sb.h2
-rw-r--r--src/ext2grp.c4
-rw-r--r--src/ext2grp.h4
-rw-r--r--src/ext2p.c7
-rw-r--r--src/fat.c201
-rw-r--r--src/fat.h114
-rw-r--r--src/fat1x.c4
-rw-r--r--src/fat_adv.c2
-rw-r--r--src/fat_cluster.c2
-rw-r--r--src/fat_cluster.h2
-rw-r--r--src/fat_common.h24
-rw-r--r--src/fat_dir.c1
-rw-r--r--src/fat_unformat.c11
-rw-r--r--src/fidentify.c67
-rw-r--r--src/file_asf.c47
-rw-r--r--src/file_bmp.c37
-rw-r--r--src/file_bz2.c2
-rw-r--r--src/file_dir.c26
-rw-r--r--src/file_doc.c507
-rw-r--r--src/file_emf.c193
-rw-r--r--src/file_exe.c39
-rw-r--r--src/file_gpg.c125
-rw-r--r--src/file_gz.c38
-rw-r--r--src/file_jpg.c456
-rw-r--r--src/file_list.c8
-rw-r--r--src/file_mov.c13
-rw-r--r--src/file_mp3.c699
-rw-r--r--src/file_pdf.c6
-rw-r--r--src/file_pf.c19
-rw-r--r--src/file_sdsk.c66
-rw-r--r--src/file_sig.c10
-rw-r--r--src/file_skp.c2
-rw-r--r--src/file_spe.c177
-rw-r--r--src/file_steuer2014.c37
-rw-r--r--src/file_swf.c187
-rw-r--r--src/file_tar.c12
-rw-r--r--src/file_tiff.c2
-rw-r--r--src/file_tiff.h25
-rw-r--r--src/file_tiff_be.c45
-rw-r--r--src/file_tiff_le.c43
-rw-r--r--src/file_txt.c3789
-rw-r--r--src/file_txt.h9
-rw-r--r--src/file_win.c5
-rw-r--r--src/file_wmf.c50
-rw-r--r--src/file_zip.c363
-rw-r--r--src/filegen.c335
-rw-r--r--src/filegen.h27
-rw-r--r--src/fnctdsk.c28
-rw-r--r--src/fnctdsk.h163
-rw-r--r--src/fuzzerfidentify.cpp6
-rw-r--r--src/geometry.c1
-rw-r--r--src/geometry.h21
-rw-r--r--src/gfs2.c4
-rw-r--r--src/gfs2.h2
-rw-r--r--src/godmode.c15
-rw-r--r--src/godmode.h2
-rw-r--r--src/guid_cmp.h4
-rw-r--r--src/guid_cpy.h9
-rw-r--r--src/hdaccess.c36
-rw-r--r--src/hdaccess.h78
-rw-r--r--src/hdcache.c91
-rw-r--r--src/hdcache.h4
-rw-r--r--src/hfs.c4
-rw-r--r--src/hfs.h26
-rw-r--r--src/hfsp.c5
-rw-r--r--src/hfsp.h4
-rw-r--r--src/hpa_dco.c14
-rw-r--r--src/hpfs.c4
-rw-r--r--src/hpfs.h2
-rw-r--r--src/intrf.c4
-rw-r--r--src/intrf.h11
-rw-r--r--src/intrfn.c13
-rw-r--r--src/intrfn.h2
-rw-r--r--src/iso.h11
-rw-r--r--src/jfs.c77
-rw-r--r--src/jfs.h14
-rw-r--r--src/list.h59
-rw-r--r--src/log.c11
-rw-r--r--src/log.h21
-rw-r--r--src/luks.c55
-rw-r--r--src/luks.h2
-rw-r--r--src/lvm.c128
-rw-r--r--src/lvm.h30
-rw-r--r--src/md.c362
-rw-r--r--src/md.h22
-rw-r--r--src/memmem.h8
-rw-r--r--src/misc.c16
-rw-r--r--src/misc.h5
-rw-r--r--src/msdos.c16
-rw-r--r--src/netware.c2
-rw-r--r--src/netware.h14
-rw-r--r--src/nodisk.c8
-rw-r--r--src/ntfs.c11
-rw-r--r--src/ntfs_adv.c85
-rw-r--r--src/ntfs_dir.c12
-rw-r--r--src/ntfs_io.c7
-rw-r--r--src/ntfs_udl.c21
-rw-r--r--src/ntfs_utl.c6
-rw-r--r--src/ntfsp.c10
-rw-r--r--src/partauto.c14
-rw-r--r--src/partauto.h5
-rw-r--r--src/partgpt.c75
-rw-r--r--src/partgpt.h15
-rw-r--r--src/parthumax.c70
-rw-r--r--src/parthumax.h2
-rw-r--r--src/parti386.c208
-rw-r--r--src/parti386.h21
-rw-r--r--src/partmac.c67
-rw-r--r--src/partmac.h2
-rw-r--r--src/partnone.c72
-rw-r--r--src/partsun.c78
-rw-r--r--src/partsun.h2
-rw-r--r--src/partxbox.c73
-rw-r--r--src/partxbox.h2
-rw-r--r--src/partxboxn.c6
-rw-r--r--src/pdiskseln.c34
-rw-r--r--src/pdiskseln.h8
-rw-r--r--src/phbf.c5
-rw-r--r--src/phbs.c8
-rw-r--r--src/phcfg.c33
-rw-r--r--src/phcfg.h2
-rw-r--r--src/phcli.c8
-rw-r--r--src/phcli.h6
-rw-r--r--src/phmain.c76
-rw-r--r--src/phnc.h6
-rw-r--r--src/photorec.c33
-rw-r--r--src/photorec.h28
-rw-r--r--src/photorec_check_header.h55
-rw-r--r--src/phrecn.c8
-rw-r--r--src/pnext.h8
-rw-r--r--src/poptions.c1
-rw-r--r--src/poptions.h10
-rw-r--r--src/ppartseln.c3
-rw-r--r--src/psearch.h2
-rw-r--r--src/psearchn.c61
-rw-r--r--src/qphotorec.cpp12
-rw-r--r--src/qpsearch.cpp56
-rw-r--r--src/rfs.c2
-rw-r--r--src/rfs.h16
-rw-r--r--src/savehdr.c6
-rw-r--r--src/savehdr.h4
-rw-r--r--src/sessionp.c14
-rw-r--r--src/setdate.c7
-rw-r--r--src/sudo.c5
-rw-r--r--src/sun.c2
-rw-r--r--src/sun.h16
-rw-r--r--src/swap.h11
-rw-r--r--src/sysv.c2
-rw-r--r--src/sysv.h2
-rw-r--r--src/tdisksel.c8
-rw-r--r--src/testdisk.c56
-rw-r--r--src/texfat.c2
-rw-r--r--src/thfs.c2
-rw-r--r--src/tntfs.c2
-rw-r--r--src/ufs.c2
-rw-r--r--src/ufs.h15
-rw-r--r--src/vmfs.c46
-rw-r--r--src/vmfs.h2
-rw-r--r--src/wbfs.c34
-rw-r--r--src/wbfs.h2
-rw-r--r--src/win32.c6
-rw-r--r--src/xfs.c112
-rw-r--r--src/xfs.h17
-rw-r--r--src/zfs.c47
-rw-r--r--src/zfs.h17
200 files changed, 8998 insertions, 2976 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index a7c2a2b..aea1b3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,24 @@
+.PRECIOUS: session_%.framac
+FRAMA_C_FLAGS=-machdep x86_64 \
+ -warn-left-shift-negative \
+ -warn-right-shift-negative \
+ -warn-signed-downcast \
+ -warn-signed-overflow \
+ -warn-unsigned-downcast \
+ -warn-unsigned-overflow \
+ -rte \
+ -eva \
+ -eva-slevel 6 \
+ -eva-warn-undefined-pointer-comparison none \
+ -eva-ignore-recursive-calls \
+ -then \
+ -wp \
+ -wp-dynamic \
+ -wp-steps 100000 \
+ -wp-split -wp-literals \
+ -wp-timeout 10 -pp-annot \
+ -kernel-msg-key pp
+
.rc.o:
$(WINDRES) --include-dir $(srcdir) $< $@
@@ -285,6 +306,7 @@ file_C = filegen.c \
file_rw2.c \
file_rx2.c \
file_save.c \
+ file_sdsk.c \
file_ses.c \
file_sgcta.c \
file_shn.c \
@@ -362,12 +384,12 @@ file_C = filegen.c \
file_H = ext2.h ext2_common.h filegen.h file_doc.h file_jpg.h file_gz.h file_sp3.h file_tar.h file_tiff.h file_txt.h ole.h pe.h suspend.h
-photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c geometry.c ntfs_dir.c ntfsp.c pdisksel.c phcli.c poptions.c sessionp.c setdate.c dfxml.c
+photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c geometry.c ntfs_dir.c ntfsp.c pdisksel.c poptions.c sessionp.c setdate.c dfxml.c
-photorec_H = photorec.h phcfg.h addpart.h chgarch.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h geometry.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h pdisksel.h phcli.h poptions.h sessionp.h setdate.h dfxml.h
+photorec_H = photorec.h phcfg.h addpart.h chgarch.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h geometry.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h pdisksel.h poptions.h sessionp.h setdate.h dfxml.h
-photorec_ncurses_C = addpartn.c askloc.c chgarchn.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometryn.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdiskseln.c pfree_whole.c phbf.c phbs.c phnc.c phrecn.c ppartseln.c psearchn.c
-photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h photorec_check_header.h
+photorec_ncurses_C = addpartn.c askloc.c chgarchn.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometryn.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdiskseln.c pfree_whole.c phbf.c phbs.c phcli.c phnc.c phrecn.c ppartseln.c psearchn.c
+photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phcli.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h photorec_check_header.h
QT_TS = \
lang/qphotorec.ca.ts \
@@ -404,6 +426,33 @@ small: $(sbin_PROGRAMS) $(bin_PROGRAMS)
extras: $(EXTRA_PROGRAMS)
+frama-c-%: session_%.framac
+ frama-c-gui -load $^
+
+session_doc.framac: file_doc.c common.c filegen.c log.c setdate.c
+ gcc $(CFLAGS) -DMAIN_doc -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_doc -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_jpg.framac: file_jpg.c file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c suspend_no.c setdate.c
+ gcc $(CFLAGS) -DMAIN_jpg -DHAVE_CONFIG_H -O -o demo -I.. $^ -ljpeg
+ frama-c $^ -cpp-extra-args="-DMAIN_jpg -DHAVE_CONFIG_H -D__x86_64__ -I/usr/include -I.. -I $(frama-c -print-path)/libc" $(FRAMA_C_FLAGS) -save $@ 2>&1 | tee session_jpg.log
+
+session_tiff_be.framac: file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_tiff_le -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_tiff_be -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_tiff_le.framac: file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_tiff_le -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_tiff_le -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_%.framac: file_%.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_$* -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_$* -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_fidentify.framac: fidentify.c common.c misc.c filegen.c log.c setdate.c file_bmp.c file_list.c
+ gcc $(CFLAGS) -DMAIN_fidentify -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_fidentify -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
moc_qphotorec.cpp: qphotorec.h
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $< -o $@
diff --git a/src/addpart.h b/src/addpart.h
index ab66262..cae5f1c 100644
--- a/src/addpart.h
+++ b/src/addpart.h
@@ -20,4 +20,12 @@
*/
+/*@
+ @ requires \valid(disk);
+ @ requires list_part == \null || \valid_read(list_part);
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ requires separation: \separated(disk, list_part, current_cmd);
+ @ ensures valid_read_string(*current_cmd);
+ @*/
list_part_t *add_partition_cli(disk_t *disk, list_part_t *list_part, char **current_cmd);
diff --git a/src/adv.c b/src/adv.c
index 0d53068..163cd68 100644
--- a/src/adv.c
+++ b/src/adv.c
@@ -79,12 +79,43 @@ extern const arch_fnct_t arch_xbox;
#define DEFAULT_IMAGE_NAME "image.dd"
-static int is_exfat(const partition_t *partition);
-static int is_hfs(const partition_t *partition);
-static int is_hfsp(const partition_t *partition);
-static int is_linux(const partition_t *partition);
-static int is_part_hfs(const partition_t *partition);
-static int is_part_hfsp(const partition_t *partition);
+static int is_part_hfs(const partition_t *partition)
+{
+ if( partition->part_type_i386 == P_HFS ||
+ partition->part_type_mac == PMAC_HFS)
+ return 1;
+ if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
+ return 1;
+ return 0;
+}
+
+static int is_part_hfsp(const partition_t *partition)
+{
+ if( partition->part_type_i386 == P_HFSP ||
+ partition->part_type_mac == PMAC_HFS )
+ return 1;
+ if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
+ return 1;
+ return 0;
+}
+
+int is_part_linux(const partition_t *partition)
+{
+ if(partition->arch==&arch_i386 && partition->part_type_i386==P_LINUX)
+ return 1;
+ if(partition->arch==&arch_sun && partition->part_type_sun==PSUN_LINUX)
+ return 1;
+ if(partition->arch==&arch_mac && partition->part_type_mac==PMAC_LINUX)
+ return 1;
+ if(partition->arch==&arch_gpt &&
+ (
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_DATA)==0 ||
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_HOME)==0 ||
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_SRV)==0
+ ))
+ return 1;
+ return 0;
+}
static int is_exfat(const partition_t *partition)
{
@@ -128,46 +159,8 @@ static int is_linux(const partition_t *partition)
return 0;
}
-static int is_part_hfs(const partition_t *partition)
-{
- if( partition->part_type_i386 == P_HFS ||
- partition->part_type_mac == PMAC_HFS)
- return 1;
- if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
- return 1;
- return 0;
-}
-
-static int is_part_hfsp(const partition_t *partition)
-{
- if( partition->part_type_i386 == P_HFSP ||
- partition->part_type_mac == PMAC_HFS )
- return 1;
- if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
- return 1;
- return 0;
-}
-
-int is_part_linux(const partition_t *partition)
-{
- if(partition->arch==&arch_i386 && partition->part_type_i386==P_LINUX)
- return 1;
- if(partition->arch==&arch_sun && partition->part_type_sun==PSUN_LINUX)
- return 1;
- if(partition->arch==&arch_mac && partition->part_type_mac==PMAC_LINUX)
- return 1;
- if(partition->arch==&arch_gpt &&
- (
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_DATA)==0 ||
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_HOME)==0 ||
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_SRV)==0
- ))
- return 1;
- return 0;
-}
-
#ifdef HAVE_NCURSES
-static void interface_adv_ncurses(disk_t *disk, const int rewrite, list_part_t *list_part, list_part_t *current_element, const int offset)
+static void interface_adv_ncurses(disk_t *disk, const int rewrite, list_part_t *list_part, const list_part_t *current_element, const int offset)
{
list_part_t *element;
int i;
@@ -369,7 +362,7 @@ static int adv_menu_boot_selected(disk_t *disk, partition_t *partition, const in
return 0;
}
-static void adv_menu_image_selected(disk_t *disk, partition_t *partition, char **current_cmd)
+static void adv_menu_image_selected(disk_t *disk, const partition_t *partition, char **current_cmd)
{
char *dst_path;
#ifdef HAVE_NCURSES
@@ -398,7 +391,7 @@ static void adv_menu_image_selected(disk_t *disk, partition_t *partition, char *
}
}
-static void adv_menu_undelete_selected(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd)
+static void adv_menu_undelete_selected(disk_t *disk, const partition_t *partition, const int verbose, char **current_cmd)
{
if(partition->sb_offset!=0 && partition->sb_size>0)
{
@@ -424,7 +417,7 @@ static void adv_menu_undelete_selected(disk_t *disk, partition_t *partition, con
}
}
-static void adv_menu_list_selected(disk_t *disk, partition_t *partition, const int verbose, const int expert, char **current_cmd)
+static void adv_menu_list_selected(disk_t *disk, const partition_t *partition, const int verbose, const int expert, char **current_cmd)
{
if(partition->sb_offset!=0 && partition->sb_size>0)
{
diff --git a/src/adv.h b/src/adv.h
index 339ecf5..b62033e 100644
--- a/src/adv.h
+++ b/src/adv.h
@@ -23,7 +23,17 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(current_cmd);
+ @ requires valid_string(*current_cmd);
+ @*/
void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const unsigned int expert, char**current_cmd);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_linux(const partition_t *partition);
#ifdef __cplusplus
diff --git a/src/alignio.h b/src/alignio.h
index 8bd1344..0541f6b 100644
--- a/src/alignio.h
+++ b/src/alignio.h
@@ -19,11 +19,26 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-static int align_pread(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
+
+/*@
+ @ requires \valid_function(fnct_pread);
+ @ requires \valid(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->offset < 0x8000000000000000;
+ @ requires 0 < count < 0x8000000000000000;
+ @ requires offset < 0x8000000000000000;
+ @ requires \valid((char *)buf + (0 .. count -1));
+ @ requires disk_car->rbuffer == \null || (\freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0);
+ @ ensures disk_car->rbuffer == \null || (\freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0);
+ @*/
+static int align_pread(int (*fnct_pread)(const disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
disk_t *disk_car, void*buf, const unsigned int count, const uint64_t offset)
{
const uint64_t offset_new=offset+disk_car->offset;
const unsigned int count_new=((offset_new%disk_car->sector_size)+count+disk_car->sector_size-1)/disk_car->sector_size*disk_car->sector_size;
+ /*@ assert count_new >= count; */
+ /*@ assert count_new >= disk_car->sector_size; */
+ /*@ assert count_new > 0; */
if(count!=count_new ||
((disk_car->access_mode&TESTDISK_O_DIRECT)!=0 &&
(((size_t)(buf) & (disk_car->sector_size-1))!=0) &&
@@ -31,24 +46,44 @@ static int align_pread(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsi
)
{
int res;
- if(disk_car->rbuffer==NULL)
- disk_car->rbuffer_size=128*512;
- while(disk_car->rbuffer_size < count_new)
+ if(disk_car->rbuffer_size < count_new)
{
free(disk_car->rbuffer);
disk_car->rbuffer=NULL;
- disk_car->rbuffer_size*=2;
}
if(disk_car->rbuffer==NULL)
+ {
+ disk_car->rbuffer_size=128*512;
+ /*@ loop assigns disk_car->rbuffer_size; */
+ while(disk_car->rbuffer_size < count_new)
+ {
+ disk_car->rbuffer_size*=2;
+ }
+ /*@ assert disk_car->rbuffer_size >= count_new; */
disk_car->rbuffer=(char*)MALLOC(disk_car->rbuffer_size);
+ }
+ /*@ assert \freeable(disk_car->rbuffer); */
res=fnct_pread(disk_car, disk_car->rbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size);
memcpy(buf,(char*)disk_car->rbuffer+(offset_new%disk_car->sector_size),count);
+ /*@ assert \freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0; */
return (res < (signed)count ? res : (signed)count );
}
return fnct_pread(disk_car, buf, count, offset_new);
}
-static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
+/*@
+ @ requires \valid_function(fnct_pread);
+ @ requires \valid_function(fnct_pwrite);
+ @ requires \valid(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->offset < 0x8000000000000000;
+ @ requires 0 < count < 0x8000000000000000;
+ @ requires offset < 0x8000000000000000;
+ @ requires \valid_read((char *)buf + (0 .. count -1));
+ @ requires disk_car->wbuffer == \null || \freeable(disk_car->wbuffer);
+ @ ensures disk_car->wbuffer == \null || \freeable(disk_car->wbuffer);
+ @*/
+static int align_pwrite(int (*fnct_pread)(const disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
int (*fnct_pwrite)(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset),
disk_t *disk_car, const void*buf, const unsigned int count, const uint64_t offset)
{
@@ -60,16 +95,23 @@ static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const uns
)
{
int tmp;
- if(disk_car->wbuffer==NULL)
- disk_car->wbuffer_size=128*512;
- while(disk_car->wbuffer_size < count_new)
+ if(disk_car->wbuffer_size < count_new)
{
free(disk_car->wbuffer);
disk_car->wbuffer=NULL;
- disk_car->wbuffer_size*=2;
}
if(disk_car->wbuffer==NULL)
+ {
+ disk_car->wbuffer_size=128*512;
+ /*@ loop assigns disk_car->wbuffer_size; */
+ while(disk_car->wbuffer_size < count_new)
+ {
+ disk_car->wbuffer_size*=2;
+ }
+ /*@ assert disk_car->wbuffer_size >= count_new; */
disk_car->wbuffer=(char*)MALLOC(disk_car->wbuffer_size);
+ }
+ /*@ assert \freeable(disk_car->wbuffer); */
if(fnct_pread(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size)<0)
{
log_error("read failed but trying to write anyway");
@@ -77,8 +119,8 @@ static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const uns
}
memcpy((char*)disk_car->wbuffer+(offset_new%disk_car->sector_size),buf,count);
tmp=fnct_pwrite(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size);
+ /*@ assert \freeable(disk_car->wbuffer) && disk_car->wbuffer_size > 0; */
return (tmp < (signed)count ? tmp : (signed)count);
}
return fnct_pwrite(disk_car, buf, count, offset_new);
}
-
diff --git a/src/analyse.c b/src/analyse.c
index b121986..46cf036 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -220,7 +220,7 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
return 0;
}
-int search_type_1(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
+int search_type_1(const unsigned char *buffer, const disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
const struct disklabel *bsd_header=(const struct disklabel *)(buffer+0x200);
const struct disk_super_block *beos_block=(const struct disk_super_block*)(buffer+0x200);
diff --git a/src/analyse.h b/src/analyse.h
index 82c1b61..aaf1002 100644
--- a/src/analyse.h
+++ b/src/analyse.h
@@ -24,7 +24,7 @@ extern "C" {
#endif
int search_type_0(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
-int search_type_1(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
+int search_type_1(const unsigned char *buffer, const disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind);
int search_type_2(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
int search_type_8(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
int search_type_16(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
diff --git a/src/askloc.h b/src/askloc.h
index 7671883..5dcc8d4 100644
--- a/src/askloc.h
+++ b/src/askloc.h
@@ -24,6 +24,10 @@ extern "C" {
#endif
char *ask_location(const char*msg, const char *src_dir, const char *dst_org);
+
+/*@
+ @ ensures \result == \null || (\result != \null && \freeable(\result) && valid_string(\result));
+ @*/
char *get_default_location(void);
#ifdef __cplusplus
diff --git a/src/autoset.h b/src/autoset.h
index 8f9e150..a5b4a56 100644
--- a/src/autoset.h
+++ b/src/autoset.h
@@ -19,5 +19,9 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/*@
+ @ requires \valid(disk_car);
+ @ assigns disk_car->unit;
+ @*/
void autoset_unit(disk_t *disk_car);
diff --git a/src/bfs.c b/src/bfs.c
index 1854ee8..fb8f35d 100644
--- a/src/bfs.c
+++ b/src/bfs.c
@@ -34,8 +34,31 @@
#include "fnctdsk.h"
#include "log.h"
-static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition);
-static int test_BeFS(disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind);
+static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition)
+{
+ partition->upart_type=UP_BEOS;
+ partition->blocksize= 1 << le32(beos_block->block_shift);
+ partition->info[0]='\0';
+ snprintf(partition->info, sizeof(partition->info), "BeFS blocksize=%u", partition->blocksize);
+ set_part_name(partition,beos_block->name,B_OS_NAME_LENGTH);
+}
+
+static int test_BeFS(const disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind)
+{
+ if(beos_block->magic1!=le32(SUPER_BLOCK_MAGIC1) &&
+ beos_block->magic2!=le32(SUPER_BLOCK_MAGIC2) &&
+ beos_block->magic3!=le32(SUPER_BLOCK_MAGIC3))
+ return 1;
+ if(partition==NULL)
+ return 0;
+ if(dump_ind!=0)
+ {
+ log_info("\nBeFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
+ dump_log(beos_block,DEFAULT_SECTOR_SIZE);
+ }
+ return 0;
+}
+
int check_BeFS(disk_t *disk_car,partition_t *partition)
{
@@ -56,37 +79,14 @@ int check_BeFS(disk_t *disk_car,partition_t *partition)
return 0;
}
-int recover_BeFS(disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind)
+int recover_BeFS(const disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind)
{
if(test_BeFS(disk_car,beos_block,partition,dump_ind)!=0)
return 1;
set_BeFS_info(beos_block, partition);
partition->part_size=le64(beos_block->num_blocks) << le32(beos_block->block_shift);
partition->part_type_i386=(unsigned char)P_BEOS;
+ partition->part_type_mac=PMAC_BEOS;
+ partition->part_type_gpt=GPT_ENT_TYPE_BEOS_BFS;
return 0;
}
-
-static int test_BeFS(disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind)
-{
- if(beos_block->magic1!=le32(SUPER_BLOCK_MAGIC1) &&
- beos_block->magic2!=le32(SUPER_BLOCK_MAGIC2) &&
- beos_block->magic3!=le32(SUPER_BLOCK_MAGIC3))
- return 1;
- if(partition==NULL)
- return 0;
- if(dump_ind!=0)
- {
- log_info("\nBeFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
- dump_log(beos_block,DEFAULT_SECTOR_SIZE);
- }
- return 0;
-}
-
-static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition)
-{
- partition->upart_type=UP_BEOS;
- partition->blocksize= 1 << le32(beos_block->block_shift);
- partition->info[0]='\0';
- snprintf(partition->info, sizeof(partition->info), "BeFS blocksize=%u", partition->blocksize);
- set_part_name(partition,beos_block->name,B_OS_NAME_LENGTH);
-}
diff --git a/src/bfs.h b/src/bfs.h
index 14087a2..7117d4c 100644
--- a/src/bfs.h
+++ b/src/bfs.h
@@ -82,8 +82,21 @@ struct disk_super_block /* super block as it is on disk */
/* this is stored in the fs_byte_order field... it's kind of dumb */
#define BFS_BIG_ENDIAN 0x42494745 /* BIGE */
/* int test_beos(struct disk_super_block *,partition_t); */
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
int check_BeFS(disk_t *disk_car, partition_t *partition);
-int recover_BeFS(disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(beos_block);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, beos_block, partition);
+ @*/
+int recover_BeFS(const disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/bsd.c b/src/bsd.c
index e67d9b0..13dd9b9 100644
--- a/src/bsd.c
+++ b/src/bsd.c
@@ -33,28 +33,8 @@
#include "bsd.h"
#include "intrf.h"
#include "log.h"
-static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition, const int verbose, const int dump_ind, const unsigned int max_partitions);
-int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
-{
- unsigned char *buffer;
- buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
- if(disk_car->pread(disk_car, buffer, BSD_DISKLABEL_SIZE, partition->part_offset + 0x200) != BSD_DISKLABEL_SIZE)
- {
- free(buffer);
- return 1;
- }
- if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
- {
- free(buffer);
- return 1;
- }
- set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
- free(buffer);
- return 0;
-}
-
-static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
+static int test_BSD(const disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
{
unsigned int i;
const uint16_t* cp;
@@ -125,7 +105,26 @@ static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const p
return 0;
}
-int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
+int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
+{
+ unsigned char *buffer;
+ buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
+ if(disk_car->pread(disk_car, buffer, BSD_DISKLABEL_SIZE, partition->part_offset + 0x200) != BSD_DISKLABEL_SIZE)
+ {
+ free(buffer);
+ return 1;
+ }
+ if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
+ {
+ free(buffer);
+ return 1;
+ }
+ set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
+ free(buffer);
+ return 0;
+}
+
+int recover_BSD(const disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
{
int i;
int i_max_p_offset=-1;
diff --git a/src/bsd.h b/src/bsd.h
index 1a14807..4554864 100644
--- a/src/bsd.h
+++ b/src/bsd.h
@@ -168,8 +168,22 @@ struct disklabel {
#define TST_FS_VINUM 14 /* Vinum drive */
#define TST_FS_RAID 15 /* RAIDFrame drive */
#define TST_FS_JFS2 21 /* IBM JFS2 */
-int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose,const unsigned int max_partitions);
-int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
+int check_BSD(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int max_partitions);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(bsd_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, bsd_header, partition);
+ @*/
+int recover_BSD(const disk_t *disk_car, const struct disklabel*bsd_header, partition_t *partition, const int verbose, const int dump_ind);
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/btrfs.c b/src/btrfs.c
index 062b52e..4eef0bb 100644
--- a/src/btrfs.c
+++ b/src/btrfs.c
@@ -74,7 +74,7 @@ int check_btrfs(disk_t *disk_car,partition_t *partition)
Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
Group 0 begin at s_first_data_block
*/
-int recover_btrfs(disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
+int recover_btrfs(const disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_btrfs(sb)!=0)
return 1;
diff --git a/src/btrfs.h b/src/btrfs.h
index d28c590..83ad564 100644
--- a/src/btrfs.h
+++ b/src/btrfs.h
@@ -139,7 +139,7 @@ struct btrfs_super_block {
} __attribute__ ((gcc_struct, __packed__));
int check_btrfs(disk_t *disk_car,partition_t *partition);
-int recover_btrfs(disk_t *disk_car, const struct btrfs_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_btrfs(const disk_t *disk_car, const struct btrfs_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/chgarch.h b/src/chgarch.h
index 5324933..e1b459e 100644
--- a/src/chgarch.h
+++ b/src/chgarch.h
@@ -24,6 +24,11 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk);
+ @ requires current_cmd == \null || valid_read_string(*current_cmd);
+ @ ensures current_cmd == \null || valid_read_string(*current_cmd);
+ @*/
int change_arch_type_cli(disk_t *disk, const int verbose, char**current_cmd);
#ifdef __cplusplus
diff --git a/src/common.c b/src/common.c
index afcf387..04ed1aa 100644
--- a/src/common.c
+++ b/src/common.c
@@ -24,6 +24,11 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_POSIX_MEMALIGN
+#undef HAVE_MEMALIGN
+#endif
#include <stdio.h>
#include <ctype.h>
@@ -51,8 +56,6 @@
static int32_t secwest=0;
-static unsigned int up2power_aux(const unsigned int number);
-
/* coverity[+alloc] */
void *MALLOC(size_t size)
{
@@ -61,7 +64,7 @@ void *MALLOC(size_t size)
/* Warning, memory leak checker must be posix_memalign/memalign aware, otherwise *
* reports may look strange. Aligned memory is required if the buffer is *
* used for read/write operation with a file opened with O_DIRECT */
-#if defined(HAVE_POSIX_MEMALIGN) && !defined(__FRAMAC__)
+#if defined(HAVE_POSIX_MEMALIGN)
if(size>=512)
{
if(posix_memalign(&res,4096,size)==0)
@@ -70,7 +73,7 @@ void *MALLOC(size_t size)
return res;
}
}
-#elif defined(HAVE_MEMALIGN) && !defined(__FRAMAC__)
+#elif defined(HAVE_MEMALIGN)
if(size>=512)
{
if((res=memalign(4096, size))!=NULL)
@@ -167,21 +170,16 @@ char * strcasestr (const char *haystack, const char *needle)
}
#endif
-#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__)
+#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__) && !defined(__FRAMAC__)
struct tm *localtime_r(const time_t *timep, struct tm *result)
{
return localtime(timep);
}
#endif
-unsigned int up2power(const unsigned int number)
-{
- /* log_trace("up2power(%u)=>%u\n",number, (1<<up2power_aux(number-1))); */
- if(number==0)
- return 1;
- return (1<<up2power_aux(number-1));
-}
-
+/*@
+ @ assigns \nothing;
+ @*/
static unsigned int up2power_aux(const unsigned int number)
{
if(number==0)
@@ -190,6 +188,13 @@ static unsigned int up2power_aux(const unsigned int number)
return(1+up2power_aux(number/2));
}
+unsigned int up2power(const unsigned int number)
+{
+ if(number==0)
+ return 1;
+ return (1<<up2power_aux(number-1));
+}
+
void set_part_name(partition_t *partition, const char *src, const unsigned int max_size)
{
unsigned int i;
@@ -225,29 +230,60 @@ char* strip_dup(char* str)
}
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
+/*
+ * The epoch of FAT timestamp is 1980.
+ * : bits : value
+ * date: 0 - 4: day (1 - 31)
+ * date: 5 - 8: month (1 - 12)
+ * date: 9 - 15: year (0 - 127) from 1980
+ * time: 0 - 4: sec (0 - 29) 2sec counts
+ * time: 5 - 10: min (0 - 59)
+ * time: 11 - 15: hour (0 - 23)
+ */
+#define SECS_PER_MIN 60
+#define SECS_PER_HOUR (60 * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+/* days between 1.1.70 and 1.1.80 (2 leap days) */
+#define DAYS_DELTA (365 * 10 + 2)
+/* 120 (2100 - 1980) isn't leap year */
+#define YEAR_2100 120
+#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100)
time_t date_dos2unix(const unsigned short f_time, const unsigned short f_date)
{
- static const unsigned int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
+ static const unsigned int days_in_year[] = { 0, 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0 };
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
- unsigned int month,year,secs;
+ unsigned long int day,leap_day,month,year,days;
+ unsigned long int secs;
+ year = f_date >> 9;
+ month = td_max(1, (f_date >> 5) & 0xf);
+ day = td_max(1, f_date & 0x1f) - 1;
+
+ leap_day = (year + 3) / 4;
+ if (year > YEAR_2100) /* 2100 isn't leap year */
+ {
+ /*@ assert year > YEAR_2100 && leap_day > (YEAR_2100 + 3)/4; */
+ leap_day--;
+ }
+ if (IS_LEAP_YEAR(year) && month > 2)
+ leap_day++;
+ days = days_in_year[month];
+ /*@ assert days <= 334; */
+ days += year * 365 + leap_day + day + DAYS_DELTA;
+
+ secs = (f_time & 0x1f)<<1;
+ secs += ((f_time >> 5) & 0x3f) * SECS_PER_MIN;
+ secs += (f_time >> 11)* SECS_PER_HOUR;
+ secs += days * SECS_PER_DAY;
- /* first subtract and mask after that... Otherwise, if
- f_date == 0, bad things happen */
- month = ((f_date >> 5) - 1) & 15;
- year = f_date >> 9;
- secs = (f_time & 31)*2+60*((f_time >> 5) & 63)+(f_time >> 11)*3600+86400*
- ((f_date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
- month < 2 ? 1 : 0)+3653);
- /* days since 1.1.70 plus 80's leap day */
return secs+secwest;
}
void set_secwest(void)
{
const time_t t = time(NULL);
-#if defined(__MINGW32__) || defined(__FRAMAC__)
+#if defined(__MINGW32__)
const struct tm *tmptr = localtime(&t);
#else
struct tm tmp;
@@ -287,23 +323,39 @@ time_t td_ntfs2utc (int64_t ntfstime)
return (ntfstime - (NTFS_TIME_OFFSET)) / 10000000;
}
-int check_command(char **current_cmd, const char *cmd, size_t n)
+int check_command(char **current_cmd, const char *cmd, const size_t n)
{
const int res=strncmp(*current_cmd, cmd, n);
if(res==0)
+ {
(*current_cmd)+=n;
+ /*@ assert valid_read_string(*current_cmd); */
+ return 0;
+ }
+ /*@ assert valid_read_string(*current_cmd); */
return res;
}
void skip_comma_in_command(char **current_cmd)
{
+ /*@
+ loop invariant valid_read_string(*current_cmd);
+ loop assigns *current_cmd;
+ */
while(*current_cmd[0]==',')
+ {
(*current_cmd)++;
+ }
+ /*@ assert valid_read_string(*current_cmd); */
}
uint64_t get_int_from_command(char **current_cmd)
{
uint64_t tmp=0;
+ /*@
+ loop invariant valid_read_string(*current_cmd);
+ loop assigns *current_cmd, tmp;
+ */
while(*current_cmd[0] >='0' && *current_cmd[0] <= '9')
{
tmp = tmp * 10 + *current_cmd[0] - '0';
diff --git a/src/common.h b/src/common.h
index 8a5e5ea..886d4dd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -24,6 +24,12 @@
#ifdef __cplusplus
extern "C" {
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_NCURSES
+#endif
+#if defined(__FRAMAC__) && defined(HAVE_STRING_H)
+#include <string.h>
+#endif
typedef struct efi_guid_s efi_guid_t;
struct efi_guid_s
@@ -105,6 +111,7 @@ struct efi_guid_s
#define PMAC_FWDRIVER 5
#define PMAC_SWAP 0x82
#define PMAC_LINUX 0x83
+#define PMAC_BEOS 0xEB
#define PMAC_HFS 0xAF
#define PMAC_MAP 6
#define PMAC_PATCHES 7
@@ -146,62 +153,66 @@ struct efi_guid_s
((const efi_guid_t){le32(0x516e7cb8),le16(0x6ecf),le16(0x11d6),0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}})
-#define GPT_ENT_TYPE_MS_RESERVED \
- ((const efi_guid_t){le32(0xe3c9e316),le16(0x0b5c),le16(0x4db8),0x81,0x7d,{0xf9,0x2d,0xf0,0x02,0x15,0xae}})
#define GPT_ENT_TYPE_MS_BASIC_DATA \
((const efi_guid_t){le32(0xebd0a0a2),le16(0xb9e5),le16(0x4433),0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}})
-#define GPT_ENT_TYPE_MS_LDM_METADATA \
- ((const efi_guid_t){le32(0x5808c8aa),le16(0x7e8f),le16(0x42e0),0x85,0xd2,{0xe1,0xe9,0x04,0x34,0xcf,0xb3}})
#define GPT_ENT_TYPE_MS_LDM_DATA \
((const efi_guid_t){le32(0xaf9b60a0),le16(0x1431),le16(0x4f62),0xbc,0x68,{0x33,0x11,0x71,0x4a,0x69,0xad}})
+#define GPT_ENT_TYPE_MS_LDM_METADATA \
+ ((const efi_guid_t){le32(0x5808c8aa),le16(0x7e8f),le16(0x42e0),0x85,0xd2,{0xe1,0xe9,0x04,0x34,0xcf,0xb3}})
#define GPT_ENT_TYPE_MS_RECOVERY \
((const efi_guid_t){le32(0xde94bba4),le16(0x06d1),le16(0x4d40),0xa1,0x6a,{0xbf,0xd5,0x01,0x79,0xd6,0xac}})
+#define GPT_ENT_TYPE_MS_RESERVED \
+ ((const efi_guid_t){le32(0xe3c9e316),le16(0x0b5c),le16(0x4db8),0x81,0x7d,{0xf9,0x2d,0xf0,0x02,0x15,0xae}})
+#define GPT_ENT_TYPE_MS_SPACES \
+ ((const efi_guid_t){le32(0xe75caf8f),le16(0xf680),le16(0x4cee),0xaf,0xa3,{0xb0,0x01,0xe5,0x6e,0xfc,0x2d}})
-#define GPT_ENT_TYPE_LINUX_RAID \
- ((const efi_guid_t){le32(0xa19d880f),le16(0x05fc),le16(0x4d3b),0xa0,0x06,{0x74,0x3f,0x0f,0x84,0x91,0x1e}})
-#define GPT_ENT_TYPE_LINUX_SWAP \
- ((const efi_guid_t){le32(0x0657fd6d),le16(0xa4ab),le16(0x43c4),0x84,0xe5,{0x09,0x33,0xc8,0x4b,0x4f,0x4f}})
-#define GPT_ENT_TYPE_LINUX_LVM \
- ((const efi_guid_t){le32(0xe6d6d379),le16(0xf507),le16(0x44c2),0xa2,0x3c,{0x23,0x8f,0x2a,0x3d,0xf9,0x28}})
-#define GPT_ENT_TYPE_LINUX_RESERVED \
- ((const efi_guid_t){le32(0x8da63339),le16(0x0007),le16(0x60c0),0xc4,0x36,{0x08,0x3a,0xc8,0x23,0x09,0x08}})
#define GPT_ENT_TYPE_LINUX_DATA \
((const efi_guid_t){le32(0x0fc63daf),le16(0x8483),le16(0x4772),0x8e,0x79,{0x3d,0x69,0xd8,0x47,0x7d,0xe4}})
#define GPT_ENT_TYPE_LINUX_HOME \
((const efi_guid_t){le32(0x933ac7e1),le16(0x2eb4),le16(0x4f13),0xb8,0x44,{0x0e,0x14,0xe2,0xae,0xf9,0x15}})
+#define GPT_ENT_TYPE_LINUX_LVM \
+ ((const efi_guid_t){le32(0xe6d6d379),le16(0xf507),le16(0x44c2),0xa2,0x3c,{0x23,0x8f,0x2a,0x3d,0xf9,0x28}})
+#define GPT_ENT_TYPE_LINUX_RAID \
+ ((const efi_guid_t){le32(0xa19d880f),le16(0x05fc),le16(0x4d3b),0xa0,0x06,{0x74,0x3f,0x0f,0x84,0x91,0x1e}})
+#define GPT_ENT_TYPE_LINUX_RESERVED \
+ ((const efi_guid_t){le32(0x8da63339),le16(0x0007),le16(0x60c0),0xc4,0x36,{0x08,0x3a,0xc8,0x23,0x09,0x08}})
#define GPT_ENT_TYPE_LINUX_SRV \
((const efi_guid_t){le32(0x3b8f8425),le16(0x20e0),le16(0x4f3b),0x90,0x7f,{0x1a,0x25,0xa7,0x6f,0x98,0xe8}})
+#define GPT_ENT_TYPE_LINUX_SWAP \
+ ((const efi_guid_t){le32(0x0657fd6d),le16(0xa4ab),le16(0x43c4),0x84,0xe5,{0x09,0x33,0xc8,0x4b,0x4f,0x4f}})
#define GPT_ENT_TYPE_HPUX_DATA \
((const efi_guid_t){le32(0x75894c1e),le16(0x3aeb),le16(0x11d3),0xb7,0xc1,{0x7b,0x03,0xa0,0x00,0x00,0x00}})
#define GPT_ENT_TYPE_HPUX_SERVICE \
((const efi_guid_t){le32(0xe2a1e728),le16(0x32e3),le16(0x11d6),0xa6,0x82,{0x7b,0x03,0xa0,0x00,0x00,0x00}})
-#define GPT_ENT_TYPE_MAC_AFS \
+#define GPT_ENT_TYPE_APPLE_CORE_STORAGE \
+ ((const efi_guid_t){le32(0x53746F72),le16(0x6167),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_APFS \
((const efi_guid_t){le32(0x7c3457ef),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_BOOT \
+ ((const efi_guid_t){le32(0x426f6f74),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_HFS \
((const efi_guid_t){le32(0x48465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_UFS \
- ((const efi_guid_t){le32(0x55465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_LABEL \
+ ((const efi_guid_t){le32(0x4c616265),le16(0x6c00),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_RAID \
((const efi_guid_t){le32(0x52414944),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_RAID_OFFLINE \
((const efi_guid_t){le32(0x52414944),le16(0x5f4f),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_BOOT \
- ((const efi_guid_t){le32(0x426f6f74),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_LABEL \
- ((const efi_guid_t){le32(0x4c616265),le16(0x6c00),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_TV_RECOVERY \
((const efi_guid_t){le32(0x5265636f),le16(0x7665),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_UFS \
+ ((const efi_guid_t){le32(0x55465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_SOLARIS_BACKUP \
+ ((const efi_guid_t){le32(0x6a8b642b),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_BOOT \
((const efi_guid_t){le32(0x6a82cb45),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_ROOT \
((const efi_guid_t){le32(0x6a85cf4d),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_SWAP \
((const efi_guid_t){le32(0x6a87c46f),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
-#define GPT_ENT_TYPE_SOLARIS_BACKUP \
- ((const efi_guid_t){le32(0x6a8b642b),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_USR \
((const efi_guid_t){le32(0x6a898cc3),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_MAC_ZFS GPT_ENT_TYPE_SOLARIS_USR
@@ -222,6 +233,9 @@ struct efi_guid_s
#define GPT_ENT_TYPE_SOLARIS_RESERVED5 \
((const efi_guid_t){le32(0x6a8d2ac7),le16(0x1dd2),le16(0x11b2),0x96,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
+#define GPT_ENT_TYPE_BEOS_BFS \
+ ((const efi_guid_t){le32(0x42465331),le16(0x3ba3),le16(0x10f1),0x80,0x2a,{0x48,0x61,0x69,0x6b,0x75,0x21}})
+
#define TESTDISK_O_RDONLY 00
#define TESTDISK_O_RDWR 02
#define TESTDISK_O_DIRECT 040000
@@ -353,7 +367,7 @@ struct arch_fnct_struct
int (*write_MBR_code)(disk_t *disk);
void (*set_prev_status)(const disk_t *disk, partition_t *partition);
void (*set_next_status)(const disk_t *disk, partition_t *partition);
- int (*test_structure)(list_part_t *list_part);
+ int (*test_structure)(const list_part_t *list_part);
unsigned int (*get_part_type)(const partition_t *partition);
int (*set_part_type)(partition_t *partition, unsigned int part_type);
void (*init_structure)(const disk_t *disk,list_part_t *list_part, const int verbose);
@@ -445,12 +459,35 @@ struct my_data_struct
@*/
void *MALLOC(size_t size);
+/*@
+ @ assigns \nothing;
+ @*/
unsigned int up2power(const unsigned int number);
+
+/*@
+ @ requires \valid(partition);
+ @ requires \valid_read(src + (0 .. max_size-1));
+ @*/
void set_part_name(partition_t *partition, const char *src, const unsigned int max_size);
+
+/*@
+ @ requires \valid(partition);
+ @ requires \valid_read(src + (0 .. max_size-1));
+ @*/
void set_part_name_chomp(partition_t *partition, const unsigned char *src, const unsigned int max_size);
+
+/*@
+ @ requires valid_read_string(str);
+ @ ensures \result == \null || valid_read_string(\result);
+ @*/
char* strip_dup(char* str);
+
+/*@ assigns \nothing; */
time_t date_dos2unix(const unsigned short f_time,const unsigned short f_date);
+
void set_secwest(void);
+
+/*@ assigns \nothing; */
time_t td_ntfs2utc (int64_t ntfstime);
#ifndef BSD_MAXPARTITIONS
#define BSD_MAXPARTITIONS 8
@@ -514,7 +551,11 @@ int strncasecmp(const char * s1, const char * s2, size_t len);
#ifndef HAVE_STRCASESTR
char * strcasestr (const char *haystack, const char *needle);
#endif
-#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__)
+#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__) && !defined(__FRAMAC__)
+/*@
+ @ requires valid_timer: \valid_read(timep);
+ @ requires \valid(result);
+ @*/
struct tm *localtime_r(const time_t *timep, struct tm *result);
#endif
/*
@@ -535,8 +576,34 @@ struct tm *localtime_r(const time_t *timep, struct tm *result);
(void) (&_x == &_y); \
_x > _y ? _x : _y; })
-int check_command(char **current_cmd, const char *cmd, size_t n);
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ requires valid_read_string(cmd);
+ @ requires \separated(cmd+(..), current_cmd);
+ @ requires strlen(cmd) == n;
+ @ assigns *current_cmd;
+ @ assigns \result \from indirect:(*current_cmd)[0 .. n-1], indirect:cmd[0 ..n-1], indirect:n;
+ @ ensures valid_read_string(*current_cmd);
+ @ ensures \result == 0 ==> *current_cmd == \old(*current_cmd) + n;
+ @ ensures \result != 0 ==> *current_cmd == \old(*current_cmd);
+ @*/
+int check_command(char **current_cmd, const char *cmd, const size_t n);
+
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ assigns *current_cmd;
+ @ ensures valid_read_string(*current_cmd);
+ @*/
void skip_comma_in_command(char **current_cmd);
+
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ assigns *current_cmd;
+ @ ensures valid_read_string(*current_cmd);
+ @*/
uint64_t get_int_from_command(char **current_cmd);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/cramfs.c b/src/cramfs.c
index c547fb5..e5afeb0 100644
--- a/src/cramfs.c
+++ b/src/cramfs.c
@@ -76,7 +76,7 @@ static int test_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, co
return 0;
}
-int recover_cramfs(disk_t *disk_car, const struct cramfs_super *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_cramfs(disk_car, sb, partition, verbose)!=0)
return 1;
diff --git a/src/cramfs.h b/src/cramfs.h
index c525234..4b9b57f 100644
--- a/src/cramfs.h
+++ b/src/cramfs.h
@@ -83,7 +83,7 @@ struct cramfs_super {
int check_cramfs(disk_t *disk_car,partition_t *partition,const int verbose);
-int recover_cramfs(disk_t *disk_car, const struct cramfs_super *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, partition_t *partition, const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/crc.c b/src/crc.c
index 0d1b268..58a01e6 100644
--- a/src/crc.c
+++ b/src/crc.c
@@ -91,6 +91,7 @@ unsigned int get_crc32(const void*buf, const unsigned int len, const uint32_t se
register uint32_t crc32val;
const unsigned char *s=(const unsigned char *)buf;
crc32val = seed;
+ /*@ loop assigns crc32val; */
for (i = 0; i < len; i ++)
{
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
diff --git a/src/crc.h b/src/crc.h
index 50b6667..b49084b 100644
--- a/src/crc.h
+++ b/src/crc.h
@@ -28,6 +28,10 @@ extern "C" {
uint32_t* make_crc32_table(uint32_t poly);
unsigned int get_crc32_gen(const unsigned char *s, const unsigned int len, const uint32_t seed, const uint32_t *crctab);
#endif
+/*@
+ @ requires \valid_read((const char *)s + (0 .. len-1));
+ @ assigns \nothing;
+ @*/
unsigned int get_crc32(const void *s, const unsigned int len, const uint32_t seed);
#ifdef __cplusplus
diff --git a/src/dfxml.c b/src/dfxml.c
index c9da693..947436e 100644
--- a/src/dfxml.c
+++ b/src/dfxml.c
@@ -24,6 +24,11 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__)
+#undef HAVE_LIBEWF
+#undef HAVE_SYS_UTSNAME_H
+#endif
+
#ifdef ENABLE_DFXML
#include <stdio.h>
#ifdef HAVE_STDLIB_H
@@ -200,11 +205,13 @@ void xml_add_DFXML_creator(const char *package, const char *version)
#ifdef RECORD_COMPILATION_DATE
xml_out2s("compilation_date", get_compilation_date());
#endif
+#ifndef MAIN_photorec
xml_printf("<library name='libext2fs' version='%s'/>\n", td_ext2fs_version());
xml_printf("<library name='libewf' version='%s'/>\n", td_ewf_version());
xml_printf("<library name='libjpeg' version='%s'/>\n", td_jpeg_version());
xml_printf("<library name='libntfs' version='%s'/>\n", td_ntfs_version());
xml_printf("<library name='zlib' version='%s'/>\n", td_zlib_version());
+#endif
xml_pop("build_environment");
xml_push("execution_environment","");
#if defined(__CYGWIN__) || defined(__MINGW32__)
@@ -238,18 +245,8 @@ void xml_add_DFXML_creator(const char *package, const char *version)
#endif
#ifdef HAVE_GETEUID
xml_out2i("uid", geteuid());
-#if 0
-#ifdef HAVE_GETPWUID
- {
- struct passwd *tmp=getpwuid(getuid());
- if(tmp != NULL)
- {
- xml_out2s("username", tmp->pw_name);
- }
- }
-#endif
-#endif
#endif
+#if !defined(__FRAMAC__)
{
char outstr[200];
const time_t t = time(NULL);
@@ -261,11 +258,12 @@ void xml_add_DFXML_creator(const char *package, const char *version)
xml_out2s("start_time", outstr);
}
}
+#endif
xml_pop("execution_environment");
xml_pop("creator");
}
-void xml_setup(disk_t *disk, const partition_t *partition)
+void xml_setup(const disk_t *disk, const partition_t *partition)
{
if(xml_handle==NULL)
return;
@@ -319,7 +317,7 @@ static const char *relative_name(const char *fname)
/* See filegen.h for the definition of file_recovery_struct */
void xml_log_file_recovered(const file_recovery_t *file_recovery)
{
- struct td_list_head *tmp;
+ const struct td_list_head *tmp;
uint64_t file_size=0;
if(xml_handle==NULL)
return;
diff --git a/src/dfxml.h b/src/dfxml.h
index 9f0b16c..c6cd34b 100644
--- a/src/dfxml.h
+++ b/src/dfxml.h
@@ -35,7 +35,7 @@ void xml_push(const char *tag, const char *attribute);
void xml_pop(const char *tag);
void xml_out2s(const char *tag, const char *value);
void xml_out2i(const char *tag, const uint64_t value);
-void xml_setup(disk_t *disk, const partition_t *partition);
+void xml_setup(const disk_t *disk, const partition_t *partition);
void xml_set_command_line(const int argc, char **argv);
void xml_clear_command_line(void);
void xml_add_DFXML_creator(const char *package, const char *version);
diff --git a/src/dimage.c b/src/dimage.c
index d1f3483..6e65118 100644
--- a/src/dimage.c
+++ b/src/dimage.c
@@ -41,6 +41,9 @@
#include <assert.h>
#include <string.h>
#include <errno.h>
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
#include "types.h"
#include "common.h"
#include "intrf.h"
@@ -123,6 +126,7 @@ int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd)
free(buffer);
return -1;
}
+#if !defined(__FRAMAC__)
if(fstat(disk_dst, &stat_buf)==0)
{
int res=1;
@@ -136,6 +140,7 @@ int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd)
src_offset+=dst_offset;
}
}
+#endif
src_offset_old=src_offset;
#ifdef HAVE_NCURSES
window=newwin(LINES, COLS, 0, 0); /* full screen */
diff --git a/src/dir.c b/src/dir.c
index f1f0fdf..06bd544 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -22,6 +22,10 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_CHMOD
+#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
diff --git a/src/dir.h b/src/dir.h
index b2d4f7a..0a78ae4 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -75,8 +75,17 @@ struct dir_data
#define FILE_STATUS_MARKED 2
#define FILE_STATUS_ADS 4
+/*@
+ @ requires \valid(datestr);
+ @*/
int set_datestr(char *datestr, size_t n, const time_t timev);
+
+/*@
+ @ requires \valid_read(dir_data);
+ @ requires \valid_read(dir_list);
+ @*/
int dir_aff_log(const dir_data_t *dir_data, const file_info_t*dir_list);
+
void log_list_file(const disk_t *disk_car, const partition_t *partition, const dir_data_t *dir_data, const file_info_t*list);
unsigned int delete_list_file(file_info_t *list);
int dir_whole_partition_log(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int inode);
diff --git a/src/dirn.c b/src/dirn.c
index ab18db9..050129f 100644
--- a/src/dirn.c
+++ b/src/dirn.c
@@ -202,7 +202,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"h");
+ waddstr(window,"'h'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((dir_data->param&FLAG_LIST_DELETED)==0)
@@ -215,7 +215,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"h");
+ waddstr(window,"'h'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((dir_data->param&FLAG_LIST_ADS)==0)
@@ -226,7 +226,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
wmove(window,LINES-2,4);
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"q");
+ waddstr(window,"'q'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to quit");
@@ -235,13 +235,13 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,":");
+ waddstr(window,"':'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to select the current file, ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"a");
+ waddstr(window,"'a'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED)
@@ -250,13 +250,13 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window," to deselect all files");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- mvwaddstr(window,LINES-1,4,"C");
+ mvwaddstr(window,LINES-1,4,"'C'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to copy the selected files, ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"c");
+ waddstr(window,"'c'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to copy the current file");
diff --git a/src/ewf.c b/src/ewf.c
index 7bf502c..e7c6391 100644
--- a/src/ewf.c
+++ b/src/ewf.c
@@ -23,6 +23,10 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEWF
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -96,34 +100,30 @@ struct info_fewf_struct
unsigned int buffer_size;
};
+#if defined( HAVE_LIBEWF_V2_API )
disk_t *fewf_init(const char *device, const int mode)
{
unsigned int num_files=0;
char **filenames= NULL;
disk_t *disk=NULL;
struct info_fewf_struct *data;
-#if !defined( HAVE_LIBEWF_V2_API ) && defined( HAVE_GLOB_H )
- glob_t globbuf;
-#endif
-#if defined( HAVE_LIBEWF_V2_API )
libewf_error_t *ewf_error = NULL;
-#endif
data=(struct info_fewf_struct *)MALLOC(sizeof(struct info_fewf_struct));
- memset(data, 0, sizeof(struct info_fewf_struct));
+ memset(data, 0, sizeof(struct info_fewf_struct));
data->file_name = strdup(device);
+ if(data->file_name==NULL)
+ {
+ free(data);
+ return NULL;
+ }
data->handle=NULL;
data->mode = mode;
#ifdef DEBUG_EWF
-#if defined( HAVE_LIBEWF_V2_API )
libewf_notify_set_stream( stderr, NULL );
libewf_notify_set_verbose( 1 );
-#else
- libewf_set_notify_values( stderr, 1 );
-#endif
#endif
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_glob(
data->file_name,
strlen(data->file_name),
@@ -140,36 +140,9 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
-#elif defined( HAVE_GLOB_H )
- {
- globbuf.gl_offs = 0;
- glob(data->file_name, GLOB_DOOFFS, NULL, &globbuf);
- if(globbuf.gl_pathc>0)
- {
- filenames=(char **)MALLOC(globbuf.gl_pathc * sizeof(*filenames));
- for (num_files=0; num_files<globbuf.gl_pathc; num_files++) {
- filenames[num_files]=globbuf.gl_pathv[num_files];
- }
- }
- }
- if(filenames==NULL)
- {
- globfree(&globbuf);
- free(data->file_name);
- free(data);
- return NULL;
- }
-#else
- {
- filenames=(char **)MALLOC(1*sizeof(*filenames));
- filenames[num_files] = data->file_name;
- num_files++;
- }
-#endif
if((mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR)
{
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_handle_initialize(
&( data->handle ),
&ewf_error) != 1 )
@@ -209,18 +182,10 @@ disk_t *fewf_init(const char *device, const int mode)
NULL );
data->handle=NULL;
}
-#else
- data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ_WRITE);
- if(data->handle==NULL)
- {
- log_error("libewf_open(%s) in RW mode failed\n", device);
- }
-#endif /* defined( HAVE_LIBEWF_V2_API ) */
}
if(data->handle==NULL)
{
data->mode&=~TESTDISK_O_RDWR;
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_handle_initialize(
&( data->handle ),
&ewf_error) != 1 )
@@ -261,7 +226,140 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
+ }
+ if( libewf_handle_set_header_values_date_format(
+ data->handle,
+ LIBEWF_DATE_FORMAT_DAYMONTH,
+ NULL ) != 1 )
+ {
+ log_error("%s Unable to set header values date format\n", device);
+ }
+ disk=(disk_t *)MALLOC(sizeof(*disk));
+ init_disk(disk);
+ disk->arch=&arch_none;
+ disk->device=strdup(device);
+ if(disk->device==NULL)
+ {
+ free(disk);
+ libewf_glob_free(
+ filenames,
+ num_files,
+ NULL );
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
+ disk->data=data;
+ disk->description=&fewf_description;
+ disk->description_short=&fewf_description_short;
+ disk->pread=&fewf_pread;
+ disk->pwrite=((data->mode&TESTDISK_O_RDWR)?&fewf_pwrite:&fewf_nopwrite);
+ disk->sync=&fewf_sync;
+ disk->access_mode=(data->mode&TESTDISK_O_RDWR);
+ disk->clean=&fewf_clean;
+ {
+ uint32_t bytes_per_sector = 0;
+ if( libewf_handle_get_bytes_per_sector(
+ data->handle,
+ &bytes_per_sector,
+ NULL ) != 1 )
+ {
+ disk->sector_size=DEFAULT_SECTOR_SIZE;
+ }
+ else
+ {
+ disk->sector_size=bytes_per_sector;
+ }
+ }
+// printf("libewf_get_bytes_per_sector %u\n",disk->sector_size);
+ if(disk->sector_size==0)
+ disk->sector_size=DEFAULT_SECTOR_SIZE;
+ /* Set geometry */
+ disk->geom.cylinders=0;
+ disk->geom.heads_per_cylinder=1;
+ disk->geom.sectors_per_head=1;
+ disk->geom.bytes_per_sector=disk->sector_size;
+ {
+ size64_t media_size = 0;
+ if( libewf_handle_get_media_size(
+ data->handle,
+ &media_size,
+ NULL ) != 1 )
+ {
+ disk->disk_real_size=0;
+ }
+ disk->disk_real_size=media_size;
+ }
+ update_disk_car_fields(disk);
+ libewf_glob_free(
+ filenames,
+ num_files,
+ NULL );
+ return disk;
+}
+#else
+disk_t *fewf_init(const char *device, const int mode)
+{
+ unsigned int num_files=0;
+ char **filenames= NULL;
+ disk_t *disk=NULL;
+ struct info_fewf_struct *data;
+#if defined( HAVE_GLOB_H )
+ glob_t globbuf;
+#endif
+ data=(struct info_fewf_struct *)MALLOC(sizeof(struct info_fewf_struct));
+ memset(data, 0, sizeof(struct info_fewf_struct));
+ data->file_name = strdup(device);
+ if(data->file_name==NULL)
+ {
+ free(data);
+ return NULL;
+ }
+ data->handle=NULL;
+ data->mode = mode;
+
+#ifdef DEBUG_EWF
+ libewf_set_notify_values( stderr, 1 );
+#endif
+
+#if defined( HAVE_GLOB_H )
+ {
+ globbuf.gl_offs = 0;
+ glob(data->file_name, GLOB_DOOFFS, NULL, &globbuf);
+ if(globbuf.gl_pathc>0)
+ {
+ filenames=(char **)MALLOC(globbuf.gl_pathc * sizeof(*filenames));
+ for (num_files=0; num_files<globbuf.gl_pathc; num_files++) {
+ filenames[num_files]=globbuf.gl_pathv[num_files];
+ }
+ }
+ }
+ if(filenames==NULL)
+ {
+ globfree(&globbuf);
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
#else
+ {
+ filenames=(char **)MALLOC(1*sizeof(*filenames));
+ filenames[num_files] = data->file_name;
+ num_files++;
+ }
+#endif
+
+ if((mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR)
+ {
+ data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ_WRITE);
+ if(data->handle==NULL)
+ {
+ log_error("libewf_open(%s) in RW mode failed\n", device);
+ }
+ }
+ if(data->handle==NULL)
+ {
+ data->mode&=~TESTDISK_O_RDWR;
data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ);
if(data->handle==NULL)
{
@@ -274,27 +372,27 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
-#endif /* defined( HAVE_LIBEWF_V2_API ) */
}
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_set_header_values_date_format(
- data->handle,
- LIBEWF_DATE_FORMAT_DAYMONTH,
- NULL ) != 1 )
- {
- log_error("%s Unable to set header values date format\n", device);
- }
-#else
if( libewf_parse_header_values( data->handle, LIBEWF_DATE_FORMAT_DAYMONTH) != 1 )
{
log_error("%s Unable to parse EWF header values\n", device);
}
-#endif
disk=(disk_t *)MALLOC(sizeof(*disk));
init_disk(disk);
disk->arch=&arch_none;
disk->device=strdup(device);
+ if(disk->device==NULL)
+ {
+ free(disk);
+#if defined( HAVE_GLOB_H )
+ globfree(&globbuf);
+#endif
+ free(filenames);
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
disk->data=data;
disk->description=&fewf_description;
disk->description_short=&fewf_description_short;
@@ -303,18 +401,10 @@ disk_t *fewf_init(const char *device, const int mode)
disk->sync=&fewf_sync;
disk->access_mode=(data->mode&TESTDISK_O_RDWR);
disk->clean=&fewf_clean;
-#if defined( HAVE_LIBEWF_V2_API ) || defined( LIBEWF_GET_BYTES_PER_SECTOR_HAVE_TWO_ARGUMENTS )
+#if defined( LIBEWF_GET_BYTES_PER_SECTOR_HAVE_TWO_ARGUMENTS )
{
uint32_t bytes_per_sector = 0;
-
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_get_bytes_per_sector(
- data->handle,
- &bytes_per_sector,
- NULL ) != 1 )
-#else
if( libewf_get_bytes_per_sector(data->handle, &bytes_per_sector)<0)
-#endif
{
disk->sector_size=DEFAULT_SECTOR_SIZE;
}
@@ -326,7 +416,6 @@ disk_t *fewf_init(const char *device, const int mode)
#else
disk->sector_size=libewf_get_bytes_per_sector(data->handle);
#endif
-
// printf("libewf_get_bytes_per_sector %u\n",disk->sector_size);
if(disk->sector_size==0)
disk->sector_size=DEFAULT_SECTOR_SIZE;
@@ -335,19 +424,10 @@ disk_t *fewf_init(const char *device, const int mode)
disk->geom.heads_per_cylinder=1;
disk->geom.sectors_per_head=1;
disk->geom.bytes_per_sector=disk->sector_size;
- /* Get disk_real_size */
-#if defined( HAVE_LIBEWF_V2_API ) || defined( LIBEWF_GET_MEDIA_SIZE_HAVE_TWO_ARGUMENTS )
+#if defined( LIBEWF_GET_MEDIA_SIZE_HAVE_TWO_ARGUMENTS )
{
size64_t media_size = 0;
-
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_get_media_size(
- data->handle,
- &media_size,
- NULL ) != 1 )
-#else
if(libewf_get_media_size(data->handle, &media_size)<0)
-#endif
{
disk->disk_real_size=0;
}
@@ -360,19 +440,13 @@ disk_t *fewf_init(const char *device, const int mode)
disk->disk_real_size=libewf_get_media_size(data->handle);
#endif
update_disk_car_fields(disk);
-#if defined( HAVE_LIBEWF_V2_API )
- libewf_glob_free(
- filenames,
- num_files,
- NULL );
-#else
#if defined( HAVE_GLOB_H )
globfree(&globbuf);
#endif
free(filenames);
-#endif
return disk;
}
+#endif
static const char *fewf_description(disk_t *disk)
{
@@ -529,4 +603,3 @@ const char*td_ewf_version(void)
return "none";
}
#endif /* defined(HAVE_LIBEWF_H) && defined(HAVE_LIBEWF) */
-
diff --git a/src/ewf.h b/src/ewf.h
index 2bcf4cc..16d2bad 100644
--- a/src/ewf.h
+++ b/src/ewf.h
@@ -23,6 +23,10 @@
extern "C" {
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEWF
+#endif
+
#if defined(HAVE_LIBEWF_H) && defined(HAVE_LIBEWF)
disk_t *fewf_init(const char *device, const int testdisk_mode);
#endif
diff --git a/src/ext2.c b/src/ext2.c
index 2cd6a07..cb81316 100644
--- a/src/ext2.c
+++ b/src/ext2.c
@@ -109,7 +109,7 @@ static void set_EXT2_info(const struct ext2_super_block *sb, partition_t *partit
Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
Group 0 begin at s_first_data_block
*/
-int recover_EXT2(disk_t *disk, const struct ext2_super_block *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_EXT2(const disk_t *disk, const struct ext2_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_EXT2(sb, partition)!=0)
return 1;
diff --git a/src/ext2.h b/src/ext2.h
index 68bffea..47ef0a7 100644
--- a/src/ext2.h
+++ b/src/ext2.h
@@ -202,7 +202,7 @@ struct ext2_super_block {
uint32_t s_checksum; /* crc32c(superblock) */
};
int check_EXT2(disk_t *disk_car,partition_t *partition,const int verbose);
-int recover_EXT2(disk_t *disk_car, const struct ext2_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_EXT2(const disk_t *disk_car, const struct ext2_super_block *sb, partition_t *partition, const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2_dir.c b/src/ext2_dir.c
index f3dc4a2..efc19a3 100644
--- a/src/ext2_dir.c
+++ b/src/ext2_dir.c
@@ -23,6 +23,10 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
@@ -31,12 +35,14 @@
#include <errno.h>
#endif
+#if defined(HAVE_LIBEXT2FS)
#ifdef HAVE_EXT2FS_EXT2_FS_H
#include "ext2fs/ext2_fs.h"
#endif
#ifdef HAVE_EXT2FS_EXT2FS_H
#include "ext2fs/ext2fs.h"
#endif
+#endif
#include "types.h"
#include "common.h"
@@ -67,7 +73,6 @@ static errcode_t my_flush(io_channel channel);
static errcode_t my_read_blk64(io_channel channel, unsigned long long block, int count, void *buf);
static errcode_t my_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf);
-static io_channel alloc_io_channel(disk_t *disk_car,my_data_t *my_data);
static void dir_partition_ext2_close(dir_data_t *dir_data);
static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
@@ -91,7 +96,6 @@ static struct struct_io_manager my_struct_manager = {
.write_blk64=&my_write_blk64,
#endif
};
-static int ext2_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int cluster, file_info_t *dir_list);
static io_channel shared_ioch=NULL;
/*
@@ -105,7 +109,7 @@ static io_channel shared_ioch=NULL;
/*
* Allocate libext2fs structures associated with I/O manager
*/
-static io_channel alloc_io_channel(disk_t *disk_car,my_data_t *my_data)
+static io_channel alloc_io_channel(const disk_t *disk_car,my_data_t *my_data)
{
io_channel ioch;
#ifdef DEBUG_EXT2
diff --git a/src/ext2_inc.h b/src/ext2_inc.h
index ca2421b..e3cf9f5 100644
--- a/src/ext2_inc.h
+++ b/src/ext2_inc.h
@@ -19,6 +19,10 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
#if defined(HAVE_LIBEXT2FS)
struct ext2_dir_struct {
file_info_t *dir_list;
diff --git a/src/ext2_sb.c b/src/ext2_sb.c
index 8a72ed3..e0e9763 100644
--- a/src/ext2_sb.c
+++ b/src/ext2_sb.c
@@ -38,7 +38,7 @@
#include "guid_cmp.h"
#include "ext2_sb.h"
-int interface_superblock(disk_t *disk_car,list_part_t *list_part, char**current_cmd)
+int interface_superblock(disk_t *disk_car, const list_part_t *list_part, char**current_cmd)
{
const list_part_t *parts;
const partition_t *old_part=NULL;
diff --git a/src/ext2_sb.h b/src/ext2_sb.h
index fae7c31..b527b8e 100644
--- a/src/ext2_sb.h
+++ b/src/ext2_sb.h
@@ -23,7 +23,7 @@
extern "C" {
#endif
-int interface_superblock(disk_t *disk_car,list_part_t *list_part,char**current_cmd);
+int interface_superblock(disk_t *disk_car, const list_part_t *list_part, char**current_cmd);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2grp.c b/src/ext2grp.c
index c48ec2b..96db73f 100644
--- a/src/ext2grp.c
+++ b/src/ext2grp.c
@@ -36,7 +36,7 @@
#include "log.h"
#include "photorec.h"
-unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition)
+unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition)
{
struct td_list_head *search_walker = NULL;
unsigned char *buffer;
@@ -73,7 +73,7 @@ unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, parti
return blocksize;
}
-unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition)
+unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition)
{
struct td_list_head *search_walker = NULL;
unsigned char *buffer;
diff --git a/src/ext2grp.h b/src/ext2grp.h
index ad854fe..ed5e9db 100644
--- a/src/ext2grp.h
+++ b/src/ext2grp.h
@@ -23,8 +23,8 @@
extern "C" {
#endif
-unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition);
-unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition);
+unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition);
+unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2p.c b/src/ext2p.c
index 6cbb0f7..2e57e43 100644
--- a/src/ext2p.c
+++ b/src/ext2p.c
@@ -22,6 +22,12 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
+#if defined(HAVE_LIBEXT2FS)
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -48,7 +54,6 @@
#include "log.h"
#include "log_part.h"
-#ifdef HAVE_LIBEXT2FS
unsigned int ext2_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space)
{
dir_data_t dir_data;
diff --git a/src/fat.c b/src/fat.c
index f1f3a65..70c78bf 100644
--- a/src/fat.c
+++ b/src/fat.c
@@ -50,14 +50,117 @@
extern const arch_fnct_t arch_i386;
extern const arch_fnct_t arch_mac;
-static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition);
-static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header);
static int log_fat_info(const struct fat_boot_sector*fh1, const upart_type_t upart_type, const unsigned int sector_size);
static int test_OS2MB(const disk_t *disk, const struct fat_boot_sector *fat_header, const partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat12(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat16(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat32(const partition_t *partition);
+static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header)
+{
+ partition->fsname[0]='\0';
+ if((fat_header->sectors_per_cluster>0)&&(fat_header->sectors_per_cluster<=128))
+ {
+ const unsigned int cluster_size=fat_header->sectors_per_cluster*disk_car->sector_size;
+ unsigned char *buffer=(unsigned char*)MALLOC(cluster_size);
+ if((unsigned)disk_car->pread(disk_car, buffer, cluster_size,
+ partition->part_offset + (le16(fat_header->reserved) + fat_header->fats * le32(fat_header->fat32_length) + (uint64_t)(le32(fat_header->root_cluster) - 2) * fat_header->sectors_per_cluster) * disk_car->sector_size) != cluster_size)
+ {
+ log_error("fat32_set_part_name() cannot read FAT32 root cluster.\n");
+ }
+ else
+ {
+ int i;
+ int stop=0;
+ for(i=0;(i<16*fat_header->sectors_per_cluster)&&(stop==0);i++)
+ { /* Test attribut volume name and check if the volume name is erased or not */
+ if(((buffer[i*0x20+0xB] & ATTR_EXT) !=ATTR_EXT) && ((buffer[i*0x20+0xB] & ATTR_VOLUME) !=0) && (buffer[i*0x20]!=0xE5))
+ {
+ set_part_name_chomp(partition,&buffer[i*0x20],11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ if(buffer[i*0x20]==0)
+ {
+ stop=1;
+ }
+ }
+ }
+ free(buffer);
+ }
+ if(partition->fsname[0]=='\0')
+ {
+ log_info("set_FAT_info: name from BS used\n");
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT32_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ return 0;
+}
+
+static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition)
+{
+ uint64_t start_fat1;
+ uint64_t start_data;
+ uint64_t part_size;
+ unsigned long int no_of_cluster;
+ unsigned long int fat_length;
+ const char *buffer=(const char*)fat_header;
+ partition->fsname[0]='\0';
+ partition->blocksize=fat_sector_size(fat_header)* fat_header->sectors_per_cluster;
+ fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
+ part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
+ start_fat1=le16(fat_header->reserved);
+ start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header);
+ no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
+ if(no_of_cluster<4085)
+ {
+ partition->upart_type=UP_FAT12;
+ snprintf(partition->info, sizeof(partition->info), "FAT12, blocksize=%u", partition->blocksize);
+ if(buffer[38]==0x29) /* BS_BootSig */
+ {
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ }
+ else if(no_of_cluster<65525)
+ {
+ partition->upart_type=UP_FAT16;
+ snprintf(partition->info, sizeof(partition->info), "FAT16, blocksize=%u", partition->blocksize);
+ if(buffer[38]==0x29) /* BS_BootSig */
+ {
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ }
+ else
+ {
+ partition->upart_type=UP_FAT32;
+ if(partition->sb_offset==0)
+ snprintf(partition->info, sizeof(partition->info), "FAT32, blocksize=%u", partition->blocksize);
+ else
+ snprintf(partition->info, sizeof(partition->info), "FAT32 found using backup sector, blocksize=%u", partition->blocksize);
+ fat32_set_part_name(disk_car,partition,fat_header);
+ }
+}
+
static int log_fat_info(const struct fat_boot_sector*fh1, const upart_type_t upart_type, const unsigned int sector_size)
{
log_info("sector_size %u\n", fat_sector_size(fh1));
@@ -150,7 +253,7 @@ int log_fat2_info(const struct fat_boot_sector*fh1, const struct fat_boot_sector
return 0;
}
-int check_FAT(disk_t *disk_car,partition_t *partition,const int verbose)
+int check_FAT(disk_t *disk_car, partition_t *partition, const int verbose)
{
unsigned char *buffer;
buffer=(unsigned char *)MALLOC(3*disk_car->sector_size);
@@ -178,54 +281,6 @@ int check_FAT(disk_t *disk_car,partition_t *partition,const int verbose)
return 0;
}
-static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition)
-{
- uint64_t start_fat1;
- uint64_t start_data;
- uint64_t part_size;
- unsigned long int no_of_cluster;
- unsigned long int fat_length;
- const char *buffer=(const char*)fat_header;
- partition->fsname[0]='\0';
- partition->blocksize=fat_sector_size(fat_header)* fat_header->sectors_per_cluster;
- fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
- part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
- start_fat1=le16(fat_header->reserved);
- start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header);
- no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
- if(no_of_cluster<4085)
- {
- partition->upart_type=UP_FAT12;
- snprintf(partition->info, sizeof(partition->info), "FAT12, blocksize=%u", partition->blocksize);
- if(buffer[38]==0x29) /* BS_BootSig */
- {
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- }
- else if(no_of_cluster<65525)
- {
- partition->upart_type=UP_FAT16;
- snprintf(partition->info, sizeof(partition->info), "FAT16, blocksize=%u", partition->blocksize);
- if(buffer[38]==0x29) /* BS_BootSig */
- {
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- }
- else
- {
- partition->upart_type=UP_FAT32;
- if(partition->sb_offset==0)
- snprintf(partition->info, sizeof(partition->info), "FAT32, blocksize=%u", partition->blocksize);
- else
- snprintf(partition->info, sizeof(partition->info), "FAT32 found using backup sector, blocksize=%u", partition->blocksize);
- fat32_set_part_name(disk_car,partition,fat_header);
- }
-}
-
static unsigned int get_next_cluster_fat12(disk_t *disk, const partition_t *partition, const int offset, const unsigned int cluster)
{
unsigned int next_cluster;
@@ -764,7 +819,7 @@ unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const uns
return le32(fsinfo->nextfree);
}
-static int fat_has_EFI_entry(disk_t *disk, partition_t *partition, const int verbose)
+static int fat_has_EFI_entry(disk_t *disk, const partition_t *partition, const int verbose)
{
dir_data_t dir_data;
struct td_list_head *file_walker = NULL;
@@ -866,48 +921,6 @@ int recover_FAT(disk_t *disk_car, const struct fat_boot_sector*fat_header, parti
return 0;
}
-static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header)
-{
- partition->fsname[0]='\0';
- if((fat_header->sectors_per_cluster>0)&&(fat_header->sectors_per_cluster<=128))
- {
- const unsigned int cluster_size=fat_header->sectors_per_cluster*disk_car->sector_size;
- unsigned char *buffer=(unsigned char*)MALLOC(cluster_size);
- if((unsigned)disk_car->pread(disk_car, buffer, cluster_size,
- partition->part_offset + (le16(fat_header->reserved) + fat_header->fats * le32(fat_header->fat32_length) + (uint64_t)(le32(fat_header->root_cluster) - 2) * fat_header->sectors_per_cluster) * disk_car->sector_size) != cluster_size)
- {
- log_error("fat32_set_part_name() cannot read FAT32 root cluster.\n");
- }
- else
- {
- int i;
- int stop=0;
- for(i=0;(i<16*fat_header->sectors_per_cluster)&&(stop==0);i++)
- { /* Test attribut volume name and check if the volume name is erased or not */
- if(((buffer[i*0x20+0xB] & ATTR_EXT) !=ATTR_EXT) && ((buffer[i*0x20+0xB] & ATTR_VOLUME) !=0) && (buffer[i*0x20]!=0xE5))
- {
- set_part_name_chomp(partition,&buffer[i*0x20],11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- if(buffer[i*0x20]==0)
- {
- stop=1;
- }
- }
- }
- free(buffer);
- }
- if(partition->fsname[0]=='\0')
- {
- log_info("set_FAT_info: name from BS used\n");
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT32_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- return 0;
-}
-
int check_OS2MB(disk_t *disk, partition_t *partition, const int verbose)
{
unsigned char *buffer=(unsigned char *)MALLOC(disk->sector_size);
diff --git a/src/fat.h b/src/fat.h
index 11d0871..b6a043f 100644
--- a/src/fat.h
+++ b/src/fat.h
@@ -113,21 +113,89 @@ struct msdos_dir_slot {
uint8_t name11_12[4]; /* 1C last 2 characters in name */
};
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+int comp_FAT(disk_t *disk, const partition_t *partition, const unsigned long int fat_size, const unsigned long int sect_res);
-int comp_FAT(disk_t *disk,const partition_t *partition, const unsigned long int fat_size, const unsigned long int sect_res);
+/*@
+ @ requires \valid_read(fh1);
+ @ requires \valid_read(fh2);
+ @*/
int log_fat2_info(const struct fat_boot_sector*fh1, const struct fat_boot_sector*fh2, const upart_type_t upart_type, const unsigned int sector_size);
-unsigned int get_next_cluster(disk_t *disk,const partition_t *partition, const upart_type_t upart_type,const int offset, const unsigned int cluster);
-int set_next_cluster(disk_t *disk,const partition_t *partition, const upart_type_t upart_type,const int offset, const unsigned int cluster, const unsigned int next_cluster);
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+unsigned int get_next_cluster(disk_t *disk, const partition_t *partition, const upart_type_t upart_type, const int offset, const unsigned int cluster);
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+int set_next_cluster(disk_t *disk, const partition_t *partition, const upart_type_t upart_type, const int offset, const unsigned int cluster, const unsigned int next_cluster);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_fat(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat12(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat16(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat32(const partition_t *partition);
-unsigned int fat32_get_prev_cluster(disk_t *disk,const partition_t *partition, const unsigned int fat_offset, const unsigned int cluster, const unsigned int no_of_cluster);
-int fat32_free_info(disk_t *disk,const partition_t *partition, const unsigned int fat_offset, const unsigned int no_of_cluster, unsigned int *next_free, unsigned int*free_count);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+unsigned int fat32_get_prev_cluster(disk_t *disk, const partition_t *partition, const unsigned int fat_offset, const unsigned int cluster, const unsigned int no_of_cluster);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @ requires \valid(next_free);
+ @ requires \valid(free_count);
+ @*/
+int fat32_free_info(disk_t *disk, const partition_t *partition, const unsigned int fat_offset, const unsigned int no_of_cluster, unsigned int *next_free, unsigned int *free_count);
+
+/*@
+ @ requires \valid_read(boot_fat32 + (0 .. sector_size-1));
+ @ assigns \nothing;
+ @*/
unsigned long int fat32_get_free_count(const unsigned char *boot_fat32, const unsigned int sector_size);
+
+/*@
+ @ requires \valid_read(boot_fat32 + (0 .. sector_size-1));
+ @ assigns \nothing;
+ @*/
unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const unsigned int sector_size);
#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
@@ -153,11 +221,47 @@ unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const uns
#define FAT32_EOC 0x0FFFFFF8
#define FAT1x_BOOT_SECTOR_SIZE 0x200
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int recover_FAT(disk_t *disk, const struct fat_boot_sector*fat_header, partition_t *partition, const int verbose, const int dump_ind, const int backup);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
int check_FAT(disk_t *disk, partition_t *partition, const int verbose);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int test_FAT(disk_t *disk, const struct fat_boot_sector *fat_header, const partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int recover_OS2MB(const disk_t *disk, const struct fat_boot_sector*fat_header, partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
int check_OS2MB(disk_t *disk, partition_t *partition, const int verbose);
+
+/*@
+ @ requires \valid_read(name);
+ @*/
int check_VFAT_volume_name(const char *name, const unsigned int max_size);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/fat1x.c b/src/fat1x.c
index 90ab49b..43d8950 100644
--- a/src/fat1x.c
+++ b/src/fat1x.c
@@ -43,7 +43,7 @@
#include "fat1x.h"
#ifdef HAVE_NCURSES
-static void dump_fat1x_ncurses(disk_t *disk_car, partition_t *partition, const unsigned char *buffer_bs)
+static void dump_fat1x_ncurses(disk_t *disk_car, const partition_t *partition, const unsigned char *buffer_bs)
{
WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */
keypad(window, TRUE); /* Need it to get arrow key */
@@ -62,7 +62,7 @@ static void dump_fat1x_ncurses(disk_t *disk_car, partition_t *partition, const u
}
#endif
-static void dump_fat1x(disk_t *disk_car, partition_t *partition, const unsigned char *buffer_bs, char **current_cmd)
+static void dump_fat1x(disk_t *disk_car, const partition_t *partition, const unsigned char *buffer_bs, char **current_cmd)
{
log_info("Boot sector\n");
dump_log(buffer_bs, FAT1x_BOOT_SECTOR_SIZE);
diff --git a/src/fat_adv.c b/src/fat_adv.c
index 5fcfe77..c6f6790 100644
--- a/src/fat_adv.c
+++ b/src/fat_adv.c
@@ -173,7 +173,7 @@ static unsigned long int get_subdirectory(disk_t *disk_car,const uint64_t hd_off
#ifdef HAVE_NCURSES
#define INTER_DIR 16
-static int ask_root_directory(disk_t *disk_car, const partition_t *partition, const file_info_t*dir_list, const unsigned long int cluster)
+static int ask_root_directory(const disk_t *disk_car, const partition_t *partition, const file_info_t*dir_list, const unsigned long int cluster)
{
/* Return value
* -1: quit
diff --git a/src/fat_cluster.c b/src/fat_cluster.c
index 1384202..a009e7f 100644
--- a/src/fat_cluster.c
+++ b/src/fat_cluster.c
@@ -42,7 +42,7 @@
/* Using a couple of inodes of "." directory entries, get the cluster size and where the first cluster begins.
* */
-int find_sectors_per_cluster(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset_org, const upart_type_t upart_type)
+int find_sectors_per_cluster(disk_t *disk_car, const partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset_org, const upart_type_t upart_type)
{
unsigned int nbr_subdir=0;
sector_cluster_t sector_cluster[10];
diff --git a/src/fat_cluster.h b/src/fat_cluster.h
index a5b3d2f..9bc53fe 100644
--- a/src/fat_cluster.h
+++ b/src/fat_cluster.h
@@ -42,7 +42,7 @@ struct cluster_offset_struct
unsigned int first_sol;
};
-int find_sectors_per_cluster(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset, const upart_type_t upart_type);
+int find_sectors_per_cluster(disk_t *disk_car, const partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset, const upart_type_t upart_type);
upart_type_t no_of_cluster2part_type(const unsigned long int no_of_cluster);
int find_sectors_per_cluster_aux(const sector_cluster_t *sector_cluster, const unsigned int nbr_sector_cluster,unsigned int *sectors_per_cluster, uint64_t *offset, const int verbose, const unsigned long int part_size_in_sectors, const upart_type_t upart_type);
diff --git a/src/fat_common.h b/src/fat_common.h
index 471c4e8..780b5cc 100644
--- a/src/fat_common.h
+++ b/src/fat_common.h
@@ -24,10 +24,34 @@
#ifdef __cplusplus
extern "C" {
#endif
+/*@
+ @ requires \valid_read(entry);
+ @ assigns \nothing;
+ @ */
unsigned int fat_get_cluster_from_entry(const struct msdos_dir_entry *entry);
+
+/*@
+ @ requires \valid_read(buffer + (0 .. 0x40-1));
+ @ assigns \nothing;
+ @ */
int is_fat_directory(const unsigned char *buffer);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int get_dir_entries(const struct fat_boot_sector *fat_header);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int fat_sector_size(const struct fat_boot_sector *fat_header);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int fat_sectors(const struct fat_boot_sector *fat_header);
#ifdef __cplusplus
diff --git a/src/fat_dir.c b/src/fat_dir.c
index 3c9c171..02a327b 100644
--- a/src/fat_dir.c
+++ b/src/fat_dir.c
@@ -57,7 +57,6 @@ struct fat_dir_struct
static int fat1x_rootdir(disk_t *disk_car, const partition_t *partition, const dir_data_t *dir_data, const struct fat_boot_sector*fat_header, file_info_t *dir_list);
-static int fat_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_cluster, file_info_t *dir_list);
static inline void fat16_towchar(wchar_t *dst, const uint8_t *src, size_t len);
static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static void dir_partition_fat_close(dir_data_t *dir_data);
diff --git a/src/fat_unformat.c b/src/fat_unformat.c
index 4cf6a83..885ecda 100644
--- a/src/fat_unformat.c
+++ b/src/fat_unformat.c
@@ -55,8 +55,10 @@
#include "fat_common.h"
#include <assert.h>
+extern int need_to_stop;
+
#define READ_SIZE 4*1024*1024
-static int pfind_sectors_per_cluster(disk_t *disk, partition_t *partition, const int verbose, unsigned int *sectors_per_cluster, uint64_t *offset_org, alloc_data_t *list_search_space)
+static int pfind_sectors_per_cluster(disk_t *disk, const partition_t *partition, const int verbose, unsigned int *sectors_per_cluster, uint64_t *offset_org, alloc_data_t *list_search_space)
{
uint64_t offset=0;
uint64_t next_offset=0;
@@ -386,6 +388,13 @@ static pstatus_t fat_unformat_aux(struct ph_param *params, const struct ph_optio
}
}
#endif
+ if(need_to_stop!=0)
+ {
+ log_info("PhotoRec has been stopped\n");
+ params->offset=offset;
+ offset = offset_end;
+ ind_stop=PSTATUS_STOP;
+ }
}
}
free(buffer_start);
diff --git a/src/fidentify.c b/src/fidentify.c
index 24b9544..883e76a 100644
--- a/src/fidentify.c
+++ b/src/fidentify.c
@@ -24,6 +24,11 @@
#include <config.h>
#endif
+#ifdef __FRAMAC__
+#undef HAVE_FTELLO
+#undef HAVE_DUP2
+#endif
+
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -52,14 +57,20 @@
#include "misc.h"
#include "file_jpg.h"
#include "file_gz.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
-extern file_enable_t list_file_enable[];
+extern file_enable_t array_file_enable[];
extern file_check_list_t file_check_list;
#define READ_SIZE 1024*512
#define OPT_CHECK 1
#define OPT_TIME 2
+/*@
+ @ requires valid_read_string(filename);
+ @*/
static int file_identify(const char *filename, const unsigned int options)
{
const unsigned int blocksize=65536;
@@ -81,21 +92,31 @@ static int file_identify(const char *filename, const unsigned int options)
}
if(fread(buffer, 1, READ_SIZE, file) >0)
{
- struct td_list_head *tmpl;
+ const struct td_list_head *tmpl;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, READ_SIZE);
+#endif
reset_file_recovery(&file_recovery);
+ reset_file_recovery(&file_recovery_new);
file_recovery.blocksize=blocksize;
file_recovery_new.blocksize=blocksize;
- file_recovery_new.file_stat=NULL;
+ /*@ assert file_recovery_new.file_stat==NULL; */
td_list_for_each(tmpl, &file_check_list.list)
{
- struct td_list_head *tmp;
+ const struct td_list_head *tmp;
const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list);
- td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list)
+ const struct td_list_head *tmp_list=&pos->file_checks[buffer[pos->offset]].list;
+ td_list_for_each(tmp, tmp_list)
{
+ /*TODO assert tmp!=tmp_list; */
const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list);
- if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) &&
+ if(
+#ifdef __FRAMAC__
+ file_check->header_check!=NULL &&
+#endif
+ (file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) &&
file_check->header_check(buffer, blocksize, 0, &file_recovery, &file_recovery_new)!=0)
{
file_recovery_new.file_stat=file_check->file_stat;
@@ -111,13 +132,15 @@ static int file_identify(const char *filename, const unsigned int options)
((options&OPT_CHECK)!=0 || ((options&OPT_TIME)!=0 && file_recovery_new.time==0))
)
{
+ off_t file_size;
file_recovery_new.handle=file;
my_fseek(file_recovery_new.handle, 0, SEEK_END);
-#ifdef HAVE_FTELLO
- file_recovery_new.file_size=ftello(file_recovery_new.handle);
+#if defined(HAVE_FTELLO)
+ file_size=ftello(file_recovery_new.handle);
#else
- file_recovery_new.file_size=ftell(file_recovery_new.handle);
+ file_size=ftell(file_recovery_new.handle);
#endif
+ file_recovery_new.file_size=(file_size==-1?0:file_size);
file_recovery_new.calculated_file_size=file_recovery_new.file_size;
(file_recovery_new.file_check)(&file_recovery_new);
if(file_recovery_new.file_size < file_recovery_new.min_filesize)
@@ -147,7 +170,7 @@ static int file_identify(const char *filename, const unsigned int options)
return 0;
}
-#ifndef __AFL_COMPILER
+#if !defined(__AFL_COMPILER) && !defined(MAIN_fidentify)
static void file_identify_dir(const char *current_dir, const unsigned int options)
{
DIR *dir;
@@ -200,20 +223,27 @@ static void display_version(void)
#ifdef RECORD_COMPILATION_DATE
printf("Compilation date: %s\n", get_compilation_date());
#endif
+#ifndef MAIN_fidentify
printf("libjpeg: %s, zlib: %s\n", td_jpeg_version(), td_zlib_version());
printf("OS: %s\n" , get_os());
+#endif
}
int main(int argc, char **argv)
{
int i;
+#ifdef MAIN_fidentify
+ unsigned int options=OPT_CHECK|OPT_TIME;
+#else
unsigned int options=0;
+#endif
FILE *log_handle=NULL;
int log_errno=0;
int enable_all_formats=1;
int scan_dir=1;
file_stat_t *file_stats;
log_set_levels(LOG_LEVEL_DEBUG|LOG_LEVEL_TRACE|LOG_LEVEL_QUIET|LOG_LEVEL_INFO|LOG_LEVEL_VERBOSE|LOG_LEVEL_PROGRESS|LOG_LEVEL_WARNING|LOG_LEVEL_ERROR|LOG_LEVEL_PERROR|LOG_LEVEL_CRITICAL);
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
if( strcmp(argv[i], "/check")==0 || strcmp(argv[i], "-check")==0 || strcmp(argv[i], "--check")==0)
@@ -238,28 +268,32 @@ int main(int argc, char **argv)
return 0;
}
}
+#endif
#ifndef __AFL_COMPILER
log_handle=log_open("fidentify.log", TD_LOG_CREATE, &log_errno);
if(log_handle!=NULL)
{
time_t my_time;
-#ifdef HAVE_DUP2
+#if defined(HAVE_DUP2)
dup2(fileno(log_handle),2);
#endif
my_time=time(NULL);
log_info("\n\n%s",ctime(&my_time));
log_info("Command line: fidentify");
+#ifndef MAIN_fidentify
for(i=1;i<argc;i++)
log_info(" %s", argv[i]);
+#endif
log_info("\n\n");
log_flush();
}
log_info("fidentify %s, Data Recovery Utility, %s\nChristophe GRENIER <grenier@cgsecurity.org>\nhttps://www.cgsecurity.org\n", VERSION, TESTDISKDATE);
#endif
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
file_enable_t *file_enable;
- for(file_enable=list_file_enable;file_enable->file_hint!=NULL;file_enable++)
+ for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++)
if(argv[i][0]=='+' &&
file_enable->file_hint->extension!=NULL &&
strcmp(file_enable->file_hint->extension,&argv[i][1])==0)
@@ -268,14 +302,16 @@ int main(int argc, char **argv)
enable_all_formats=0;
}
}
+#endif
if(enable_all_formats)
{
/* Enable all file formats */
file_enable_t *file_enable;
- for(file_enable=list_file_enable;file_enable->file_hint!=NULL;file_enable++)
+ for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++)
file_enable->enable=1;
}
- file_stats=init_file_stats(list_file_enable);
+ file_stats=init_file_stats(array_file_enable);
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
if(strcmp(argv[i], "/check")==0 || strcmp(argv[i], "-check")==0 || strcmp(argv[i], "--check")==0 ||
@@ -306,6 +342,9 @@ int main(int argc, char **argv)
if(scan_dir)
file_identify_dir(".", options);
#endif
+#else
+ file_identify("demo", options);
+#endif
free_header_check();
free(file_stats);
log_close();
diff --git a/src/file_asf.c b/src/file_asf.c
index 8f96d2a..a9a7650 100644
--- a/src/file_asf.c
+++ b/src/file_asf.c
@@ -66,24 +66,29 @@ struct asf_stream_prop_s {
unsigned char stream_type[16];
} __attribute__ ((gcc_struct, __packed__));
+static const char *extension_wma="wma";
+static const char *extension_wmv="wmv";
+
static int header_check_asf(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 struct asf_header_obj_s *hdr=(const struct asf_header_obj_s*)buffer;
- unsigned int i;
- const struct asf_file_prop_s *prop=(const struct asf_file_prop_s*)(hdr+1);
+ const char *extension=file_hint_asf.extension;
+ const unsigned int nbr_header_obj=le32(hdr->nbr_header_obj);
uint64_t size=0;
time_t time=0;
- const char *extension=file_hint_asf.extension;
+ unsigned int i;
+ uint64_t offset_prop=sizeof(struct asf_header_obj_s);
/* Header + File Properties + Stream Properties + Header Extension */
if(le64(hdr->object_size)<30 ||
le64(hdr->object_size)>buffer_size ||
- le32(hdr->nbr_header_obj)<4)
+ nbr_header_obj<4)
return 0;
for(i=0;
- i<le32(hdr->nbr_header_obj) &&
- (const unsigned char *)prop+0x28 < buffer + buffer_size;
- i++, prop=(const struct asf_file_prop_s *)((const char *)prop + le64(prop->object_size)))
+ i < nbr_header_obj && offset_prop + 0x28 < buffer_size;
+ i++)
{
+ const struct asf_file_prop_s *prop=(const struct asf_file_prop_s*)&buffer[offset_prop];
+ const uint64_t object_size=le64(prop->object_size);
// ASF_File_Properties_Object // 8CABDCA1-A947-11CF-8EE4-00C00C205365
// ASF_Stream_Properties_Object // B7DC0791-A9B7-11CF-8EE6-00C00C205365
static const unsigned char asf_file_prop_id[16]= {
@@ -94,18 +99,20 @@ static int header_check_asf(const unsigned char *buffer, const unsigned int buff
0x91, 0x07, 0xdc, 0xb7, 0xb7, 0xa9, 0xcf, 0x11,
0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
- if(le64(prop->object_size) < 0x18)
+ if(object_size < 0x18)
{
- log_info("header_check_asf object_size too small %llu\n", (long long unsigned)le64(prop->object_size));
+ log_info("header_check_asf object_size too small %llu\n", (long long unsigned)object_size);
return 0;
}
+ if(object_size > 0x8000000000000000)
+ return 0;
if(memcmp(prop->object_id, asf_file_prop_id, sizeof(asf_file_prop_id))==0)
{
- if(le64(prop->object_size) < 0x28)
- return 0;
- if(le64(prop->file_size) < sizeof(struct asf_header_obj_s) + sizeof(struct asf_file_prop_s))
+ if(object_size < 0x28)
return 0;
size=le64(prop->file_size);
+ if(size < sizeof(struct asf_header_obj_s) + sizeof(struct asf_file_prop_s))
+ return 0;
time=td_ntfs2utc(le64(prop->file_date));
}
else if(memcmp(prop->object_id, asf_stream_prop_s, sizeof(asf_stream_prop_s))==0)
@@ -117,25 +124,27 @@ static int header_check_asf(const unsigned char *buffer, const unsigned int buff
const char wmv[16]={
0xc0, 0xef, 0x19, 0xbc, 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b
};
- if(le64(prop->object_size) < 0x28)
+ if(object_size < 0x28)
return 0;
if(memcmp(stream->stream_type, wma, sizeof(wma))==0)
- extension="wma";
+ extension=extension_wma;
else if(memcmp(stream->stream_type, wmv, sizeof(wmv))==0)
- extension="wmv";
+ extension=extension_wmv;
}
- if(le64(prop->object_size) > buffer_size)
- break;
+ offset_prop+=object_size;
}
+ if(size > 0 && size < offset_prop)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=extension;
+ file_recovery_new->min_filesize=offset_prop;
+ file_recovery_new->time=time;
if(size > 0)
{
- file_recovery_new->calculated_file_size=le64(size);
+ file_recovery_new->calculated_file_size=size;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
}
- file_recovery_new->time=time;
return 1;
}
diff --git a/src/file_bmp.c b/src/file_bmp.c
index 42209d2..afef52b 100644
--- a/src/file_bmp.c
+++ b/src/file_bmp.c
@@ -63,15 +63,45 @@ struct bmp_header
@ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_bmp, buffer+(..), file_recovery, file_recovery_new);
+ @ assigns file_recovery_new->filename[0];
+ @ assigns file_recovery_new->time;
+ @ assigns file_recovery_new->file_stat;
+ @ assigns file_recovery_new->handle;
+ @ assigns file_recovery_new->file_size;
+ @ assigns file_recovery_new->location.list.prev;
+ @ assigns file_recovery_new->location.list.next;
+ @ assigns file_recovery_new->location.end;
+ @ assigns file_recovery_new->location.data;
+ @ assigns file_recovery_new->extension;
+ @ assigns file_recovery_new->min_filesize;
+ @ assigns file_recovery_new->calculated_file_size;
+ @ assigns file_recovery_new->data_check;
+ @ assigns file_recovery_new->file_check;
+ @ assigns file_recovery_new->file_rename;
+ @ assigns file_recovery_new->offset_error;
+ @ assigns file_recovery_new->offset_ok;
+ @ assigns file_recovery_new->checkpoint_status;
+ @ assigns file_recovery_new->checkpoint_offset;
+ @ assigns file_recovery_new->flags;
+ @ assigns file_recovery_new->extra;
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_bmp.extension);
@ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= 65);
@ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
@ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 65);
@ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
@ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @ ensures *buffer==\old(*buffer);
@*/
+ /* TODO ensures *file_recovery==\old(*file_recovery); */
static int header_check_bmp(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 struct bmp_header *bm=(const struct bmp_header *)buffer;
@@ -100,6 +130,8 @@ static int header_check_bmp(const unsigned char *buffer, const unsigned int buff
/*@ assert file_recovery_new->min_filesize == 65; */
/*@ assert file_recovery_new->data_check == &data_check_size; */
/*@ assert file_recovery_new->file_check == &file_check_size; */
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ /*@ assert \initialized(&file_recovery_new->time); */
return 1;
}
return 0;
@@ -115,11 +147,10 @@ static void register_header_check_bmp(file_stat_t *file_stat)
#if defined(MAIN_bmp)
#define BLOCKSIZE 65536u
-int main()
+int main(void)
{
const char fn[] = "recup_dir.1/f0000000.bmp";
unsigned char buffer[BLOCKSIZE];
- int res;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
file_stat_t file_stats;
diff --git a/src/file_bz2.c b/src/file_bz2.c
index 05914f2..191bcd6 100644
--- a/src/file_bz2.c
+++ b/src/file_bz2.c
@@ -51,7 +51,7 @@ static void register_header_check_bz2(file_stat_t *file_stat)
static int header_check_bz2(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)
{
- if(buffer[0]=='B' && buffer[1]=='Z' && buffer[2]=='h' && buffer[3]>='0' && buffer[4]=='1' && buffer[5]=='A' && buffer[6]=='Y' && buffer[7]=='&' && buffer[8]=='S' && buffer[9]=='Y')
+ if(buffer[0]=='B' && buffer[1]=='Z' && buffer[2]=='h' && buffer[3]>='0' && buffer[3]<='9' && buffer[4]=='1' && buffer[5]=='A' && buffer[6]=='Y' && buffer[7]=='&' && buffer[8]=='S' && buffer[9]=='Y')
{
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_bz2.extension;
diff --git a/src/file_dir.c b/src/file_dir.c
index 09a5b96..a91bdaa 100644
--- a/src/file_dir.c
+++ b/src/file_dir.c
@@ -50,6 +50,11 @@ const file_hint_t file_hint_dir= {
.register_header_check=&register_header_check_dir
};
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((char*)&file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_fatdir;
+ @*/
static void file_rename_fatdir(file_recovery_t *file_recovery)
{
unsigned char buffer[512];
@@ -68,6 +73,15 @@ static void file_rename_fatdir(file_recovery_t *file_recovery)
file_rename(file_recovery, buffer_cluster, strlen(buffer_cluster), 0, NULL, 1);
}
+/*@
+ @ requires buffer_size >= 2;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_fatdir;
+ @ ensures \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_fatdir(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
/* Save only one cluster */
@@ -75,6 +89,15 @@ static data_check_t data_check_fatdir(const unsigned char *buffer, const unsigne
return DC_STOP;
}
+/*@
+ @ requires buffer_size >= sizeof(struct msdos_dir_entry);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_dir, buffer+(..), file_recovery, file_recovery_new);
+ @*/
static int header_check_dir(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 struct msdos_dir_entry *de=(const struct msdos_dir_entry*)buffer;
@@ -89,6 +112,9 @@ static int header_check_dir(const unsigned char *buffer, const unsigned int buff
return 1;
}
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_dir(file_stat_t *file_stat)
{
register_header_check(0, ". ", 8+3, &header_check_dir, file_stat);
diff --git a/src/file_doc.c b/src/file_doc.c
index 67b24ac..a0361f9 100644
--- a/src/file_doc.c
+++ b/src/file_doc.c
@@ -134,6 +134,7 @@ static int OLE_read_block(FILE *IN, unsigned char *buf, const unsigned int uSect
/*@
@ requires \valid_read(dir_entry);
+ @ requires \initialized(dir_entry);
@ ensures \result == \null || valid_read_string(\result);
@*/
static const char *entry2ext(const struct OLE_DIR *dir_entry)
@@ -595,6 +596,7 @@ void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset)
/*@
@ requires \valid(file_recovery);
@ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_doc;
@ ensures \valid(file_recovery->handle);
@*/
static void file_check_doc(file_recovery_t *file_recovery)
@@ -656,16 +658,19 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const
unsigned int block;
unsigned int i;
const unsigned int uSectorShift=le16(header->uSectorShift);
- if(le32(header->csectMiniFat)==0)
+ /*@ assert uSectorShift==9 || uSectorShift==12; */
+ const unsigned int csectMiniFat=le32(header->csectMiniFat);
+ if(csectMiniFat==0)
return NULL;
- /*@ assert le32(header->csectMiniFat)!=0; */
+ /*@ assert 0 < csectMiniFat; */
+ /*@ assert 0 < csectMiniFat <= 2048; */
#ifdef __FRAMAC__
minifat=(uint32_t*)MALLOC(2048 << 12);
#else
- minifat=(uint32_t*)MALLOC(le32(header->csectMiniFat) << uSectorShift);
+ minifat=(uint32_t*)MALLOC(csectMiniFat << uSectorShift);
#endif
block=le32(header->MiniFat_block);
- for(i=0; i < le32(header->csectMiniFat); i++)
+ for(i=0; i < csectMiniFat; i++)
{
unsigned char*minifat_pos=(unsigned char*)minifat + (i << uSectorShift);
if(block >= fat_entries)
@@ -686,6 +691,7 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const
/*@
@ requires \valid_read((char *)buffer + (offset .. offset + 4 - 1));
@ requires \initialized((char *)buffer + (offset .. offset + 4 - 1));
+ @ assigns \nothing;
@*/
static uint32_t get32u(const void *buffer, const unsigned int offset)
{
@@ -696,6 +702,7 @@ static uint32_t get32u(const void *buffer, const unsigned int offset)
/*@
@ requires \valid_read((char *)buffer + (offset .. offset + 8 - 1));
@ requires \initialized((char *)buffer + (offset .. offset + 8 - 1));
+ @ assigns \nothing;
@*/
static uint64_t get64u(const void *buffer, const unsigned int offset)
{
@@ -708,78 +715,115 @@ static uint64_t get64u(const void *buffer, const unsigned int offset)
@ requires *ext == \null || valid_read_string(*ext);
@ requires count > 0;
@ requires \valid_read(software + (0 .. count-1));
- @ requires \initialized(software + (0 .. count-1));
- @ ensures *ext != \null || valid_read_string(*ext);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
@*/
static void software2ext(const char **ext, const unsigned char *software, const unsigned int count)
{
- if(count>=12 && memcmp(software, "MicroStation", 12)==0)
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ if(count>=12)
{
- *ext=extension_dgn;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "MicroStation", 12)==0)
+ {
+ *ext=extension_dgn;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=14 && memcmp(software, "Microsoft Word", 14)==0)
+ if(count>=14)
{
- *ext=file_hint_doc.extension;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Word", 14)==0)
+ {
+ *ext=file_hint_doc.extension;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=15 && memcmp(software, "Microsoft Excel", 15)==0)
+ if(count>=15)
{
- if(*ext==NULL || strcmp(*ext,"sldprt")!=0)
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Excel", 15)==0)
{
- *ext=extension_xls;
- /*@ assert valid_read_string(*ext); */
+ if(*ext==NULL || strcmp(*ext,"sldprt")!=0)
+ {
+ *ext=extension_xls;
+ /*@ assert valid_read_string(*ext); */
+ }
+ return;
}
- return;
}
- if(count>=20 && memcmp(software, "Microsoft PowerPoint", 20)==0)
+ if(count>=20)
{
- *ext=extension_ppt;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft PowerPoint", 20)==0)
+ {
+ *ext=extension_ppt;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=21 && memcmp(software, "Microsoft Office Word", 21)==0)
+ if(count>=21)
{
- *ext=file_hint_doc.extension;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Office Word", 21)==0)
+ {
+ *ext=file_hint_doc.extension;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count==21 && memcmp(software, "TurboCAD for Windows", 21)==0)
+ if(count==21)
{
- *ext=extension_tcw;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "TurboCAD for Windows", 21)==0)
+ {
+ *ext=extension_tcw;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count==22 && memcmp(software, "TurboCAD pour Windows", 22)==0)
+ if(count==22)
{
- *ext=extension_tcw;
- /*@ assert valid_read_string(*ext); */
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "TurboCAD pour Windows", 22)==0)
+ {
+ *ext=extension_tcw;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- /*@ assert *ext != \null || valid_read_string(*ext); */
+ /*@ assert *ext == \null || valid_read_string(*ext); */
return ;
}
/*@
@ requires count > 0;
@ requires \valid_read(software + (0 .. 2*count-1));
- @ requires \initialized(software + (0 .. 2*count-1));
@ ensures \result == \null || \result == extension_et || \result == extension_psmodel;
@ ensures \result == \null || valid_read_string(\result);
+ @ assigns \nothing;
@*/
static const char *software_uni2ext(const unsigned char *software, const unsigned int count)
{
- if(count>=15 && memcmp(software, "M\0i\0c\0r\0o\0s\0o\0f\0t\0 \0E\0x\0c\0e\0l\0", 30)==0)
+ if(count>=15)
{
- /*@ assert valid_read_string(extension_et); */
- return extension_et;
+ /*@ assert \valid_read(software + (0 .. 2*count-1)); */
+ if(memcmp(software, "M\0i\0c\0r\0o\0s\0o\0f\0t\0 \0E\0x\0c\0e\0l\0", 30)==0)
+ {
+ /*@ assert valid_read_string(extension_et); */
+ return extension_et;
+ }
}
- if(count>=17 && memcmp(software, "D\0e\0l\0c\0a\0m\0 \0P\0o\0w\0e\0r\0S\0H\0A\0P\0E\0", 34)==0)
+ if(count>=17)
{
- /*@ assert valid_read_string(extension_psmodel); */
- return extension_psmodel;
+ /*@ assert \valid_read(software + (0 .. 2*count-1)); */
+ if(memcmp(software, "D\0e\0l\0c\0a\0m\0 \0P\0o\0w\0e\0r\0S\0H\0A\0P\0E\0", 34)==0)
+ {
+ /*@ assert valid_read_string(extension_psmodel); */
+ return extension_psmodel;
+ }
}
return NULL;
}
@@ -797,6 +841,7 @@ struct summary_entry
@ requires \valid(ext);
@ requires *ext == \null || valid_read_string(*ext);
@ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
@*/
static void OLE_parse_software_entry(const unsigned char *buffer, const unsigned int size, const unsigned int offset, const char **ext)
{
@@ -822,20 +867,25 @@ static void OLE_parse_software_entry(const unsigned char *buffer, const unsigned
return ;
}
/*@ assert offset_soft + count <= size; */
+ /*@ assert count <= size - offset_soft; */
+ /*@ assert \valid_read(buffer + (0 .. size-1)); */
+ /*@ assert \valid_read(buffer + (0 .. offset_soft + count -1)); */
#ifdef DEBUG_OLE
{
unsigned int j;
log_info("Software ");
for(j=0; j<count; j++)
{
- log_info("%c", buffer[offset_soft + j]);
+ /*@ assert 0 <= j < count; */
+ /*@ assert offset_soft + count <= size; */
+ const unsigned int tmp=offset_soft+j;
+ /*@ assert tmp < size; */
+ log_info("%c", buffer[tmp]);
}
log_info("\n");
}
#endif
-#ifndef MAIN_doc
software2ext(ext, &buffer[offset_soft], count);
-#endif
/*@ assert *ext == \null || valid_read_string(*ext); */
}
/*@ assert *ext == \null || valid_read_string(*ext); */
@@ -848,6 +898,7 @@ static void OLE_parse_software_entry(const unsigned char *buffer, const unsigned
@ requires \valid(ext);
@ requires *ext == \null || valid_read_string(*ext);
@ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
@*/
static void OLE_parse_uni_software_entry(const unsigned char *buffer, const unsigned int size, const unsigned int offset, const char **ext)
{
@@ -858,8 +909,8 @@ static void OLE_parse_uni_software_entry(const unsigned char *buffer, const unsi
}
/*@ assert offset < size - 8; */
{
- const unsigned int offset8=offset + 8;
- /*@ assert offset8 < size; */
+ const unsigned int offset_soft=offset + 8;
+ /*@ assert offset_soft < size; */
const unsigned int count=get32u(buffer, offset + 4);
unsigned int count2;
if(count == 0 || count > size/2)
@@ -870,27 +921,31 @@ static void OLE_parse_uni_software_entry(const unsigned char *buffer, const unsi
/*@ assert 0 < count <= size/2; */
count2=2*count;
/*@ assert 0 < count2 <= size; */
- if(count2 > size - offset8)
+ if(count2 > size - offset_soft)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
return ;
}
- /*@ assert count2 <= size - offset8; */
+ /*@ assert count2 <= size - offset_soft; */
+ /*@ assert offset_soft + count2 <= size; */
/*@ assert \valid_read(buffer + (0 .. size - 1)) && \initialized(buffer + (0 .. size - 1)); */
- /*@ assert \valid_read(buffer + (0 .. offset8 + count2 - 1)); */
+ /*@ assert \valid_read(buffer + (0 .. offset_soft + count2 - 1)); */
#ifdef DEBUG_OLE
- unsigned int j;
- log_info("Software ");
- for(j=0; j < 2 * count; j+=2)
{
- log_info("%c", buffer[offset + 8 + j]);
+ unsigned int j;
+ log_info("Software ");
+ for(j=0; j < count2; j+=2)
+ {
+ /*@ assert 0 <= j < count2; */
+ /*@ assert offset_soft + count2 <= size; */
+ const unsigned int tmp=offset_soft + j;
+ /*@ assert tmp < size; */
+ log_info("%c", buffer[tmp]);
+ }
+ log_info("\n");
}
- log_info("\n");
-#endif
-#ifndef __FRAMAC__
- /*@ assert \initialized(buffer + (0 .. offset8 + count2 - 1)); */
- *ext=software_uni2ext(&buffer[offset8], count);
#endif
+ *ext=software_uni2ext(&buffer[offset_soft], count);
}
/*@ assert *ext == \null || valid_read_string(*ext); */
}
@@ -898,66 +953,74 @@ static void OLE_parse_uni_software_entry(const unsigned char *buffer, const unsi
/*@
@ requires 8 <= size <= 1024*1024;
@ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \valid(title + (0 .. 1024-1));
+ @ requires valid_string(title);
@ requires \initialized(buffer+ (0 .. size-1));
- @ requires \valid(title);
- @ requires *title == \null || valid_read_string(*title);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
+ @ assigns *(title + (0 .. 1023));
@*/
-static void OLE_parse_title_entry(const unsigned char *buffer, const unsigned int size, const unsigned int offset, char **title)
+static void OLE_parse_title_entry(const unsigned char *buffer, const unsigned int size, const unsigned int offset, char *title)
{
if(offset + 8 > size)
{
- /*@ assert *title == \null || valid_read_string(*title); */
- return ;
+ return;
}
/*@ assert offset + 8 <= size; */
{
/*@ assert \valid_read(buffer + (0 .. size - 1)); */
const unsigned int count=get32u(buffer, offset + 4);
const unsigned int offset_tmp=offset + 8;
- char *tmp;
+ const char *src=(const char *)buffer;
if(count <= 1 || count > size)
{
- /*@ assert *title == \null || valid_read_string(*title); */
- return ;
+ return;
}
/*@ assert 1 < count <= size; */
+ /*@ assert 1 < count <= 1024*1024; */
if(offset_tmp + count > size)
{
- /*@ assert *title == \null || valid_read_string(*title); */
- return ;
+ return;
}
/*@ assert offset_tmp + count <= size; */
-#ifndef MAIN_doc
- tmp=(char*)MALLOC(count+1);
- /*@ assert \valid_read(buffer + (0 .. size - 1)); */
+ /*@ assert \valid_read(src + (0 .. size - 1)); */
/*@ assert offset_tmp + count <= size; */
- /*@ assert \valid_read(buffer + (0 .. offset_tmp + count - 1)); */
- /*@ assert \valid_read((char*)buffer + (0 .. offset_tmp + count - 1)); */
- /*@ assert \valid_read((buffer + offset_tmp) + (0 .. count - 1)); */
- /*@ assert \valid_read((buffer + offset_tmp) + (1 .. count - 1)); */
- /*@ assert \valid_read(((char*)(buffer+offset_tmp))+(0..count-1)); */
- /*@ assert \valid_read(((char*)(buffer+offset_tmp))+(1..count-1)); */
- /*@ assert \valid_read((char*)(buffer + offset_tmp)); */
- /*@ assert \valid_read((char*)(buffer + offset_tmp)) && \valid_read(((char*)(buffer+offset_tmp))+(1..count-1)); */
- /*@ assert valid_read_or_empty((void const *)(buffer + offset_tmp), count); */
- memcpy(tmp, &buffer[offset_tmp], count);
- tmp[count]='\0';
- /*@ assert valid_read_string(tmp); */
-#ifdef DEBUG_OLE
- log_info("Title %s\n", tmp);
+ /*@ assert \valid_read(src + (0 .. offset_tmp + count - 1)); */
+ /*@ assert \valid_read((src + offset_tmp) + (0 .. count - 1)); */
+ /*@ assert \valid_read((src + offset_tmp) + (1 .. count - 1)); */
+ /*@ assert \valid_read((char*)src + (0 .. offset_tmp + count - 1)); */
+ /*@ assert \valid_read(((char*)(src+offset_tmp))+(0..count-1)); */
+ /*@ assert \valid_read(((char*)(src+offset_tmp))+(1..count-1)); */
+ /*@ assert \valid_read((char*)(src + offset_tmp)); */
+ /*@ assert \valid_read((char*)(src + offset_tmp)) && \valid_read(((char*)(src+offset_tmp))+(1..count-1)); */
+ /*@ assert valid_read_or_empty((void const *)(src + offset_tmp), count); */
+ /*@ assert valid_read_or_empty((void const *)(src + offset_tmp), count); */
+#ifndef __FRAMAC__
+ if(count < 1024)
+ {
+ memcpy(title, &src[offset_tmp], count);
+ title[count]='\0';
+ /*@ assert valid_string(title); */
+ }
+ else
+ {
+ memcpy(title, &src[offset_tmp], 1023);
+ title[1023]='\0';
+ /*@ assert valid_string(title); */
+ }
#endif
- *title=tmp;
- /*@ assert valid_read_string(*title); */
+#ifdef DEBUG_OLE
+ log_info("Title %s\n", title);
#endif
}
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
}
+
/*@
@ requires 8 <= size <= 1024*1024;
@ requires \valid_read(buffer+ (0 .. size-1));
@ requires \initialized(buffer+ (0 .. size-1));
@ requires \valid(file_time);
+ @ assigns *file_time;
@*/
static void OLE_parse_filetime_entry(const unsigned char *buffer, const unsigned int size, const unsigned int offset, time_t *file_time)
{
@@ -981,14 +1044,94 @@ static void OLE_parse_filetime_entry(const unsigned char *buffer, const unsigned
@ requires \valid_read(buffer+ (0 .. size-1));
@ requires \initialized(buffer+ (0 .. size-1));
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires \valid_read(entry);
@ requires *ext == \null || valid_read_string(*ext);
+ @ requires valid_string(title);
+ @ requires separation: \separated(buffer+(..), ext, title + ( 0 .. 1023), file_time);
@ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
+ @ assigns *ext, *(title + (0..1023)), *file_time;
@*/
-static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned int size, const char **ext, char **title, time_t *file_time)
+static void OLE_parse_PropertySet_entry(const unsigned char *buffer, const unsigned int size, const struct summary_entry *entry, const char **ext, char *title, time_t *file_time)
+{
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_read_string(title); */
+ const unsigned int tag=le32(entry->tag);
+ const unsigned int offset=le32(entry->offset);
+ unsigned int type;
+ if(offset >= size - 4)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /*@ assert offset < size - 4; */
+ /*@ assert \valid_read(buffer + (0 .. offset + 4 - 1)); */
+ type=get32u(buffer, offset);
+#ifdef DEBUG_OLE
+ log_info("entry 0x%x, tag 0x%x, offset 0x%x, offset + 4 0x%x, type 0x%x\n",
+ entry_offset, tag, offset, offset + 4, type);
+#endif
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ /* tag: Software, type: VT_LPSTR */
+ if(tag==0x12 && type==30)
+ {
+ /*@ assert valid_string(title); */
+ OLE_parse_software_entry(buffer, size, offset, ext);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /* tag: Software, type: VT_LPWSTR */
+ if(tag==0x12 && type==31)
+ {
+ /*@ assert valid_string(title); */
+ OLE_parse_uni_software_entry(buffer, size, offset, ext);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /* tag: title, type: VT_LPSTR */
+ if(tag==0x02 && type==30 && title[0]=='\0')
+ {
+ OLE_parse_title_entry(buffer, size, offset, title);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return ;
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ /* ModifyDate, type=VT_FILETIME */
+ if(tag==0x0d && type==64)
+ {
+ OLE_parse_filetime_entry(buffer, size, offset, file_time);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \valid(ext);
+ @ requires \valid(title + (0 .. 1024-1));
+ @ requires \valid(file_time);
+ @ requires valid_string(title);
+ @ requires *ext == \null || valid_read_string(*ext);
+ @ requires separation: \separated(buffer+(..), ext, title + (0 .. 1023), file_time);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ ensures valid_string(title);
+ @*/
+/*X TODO assigns *ext, *(title + (0..1023)), *file_time; */
+/*X TODO requires \initialized(buffer+ (0 .. size-1)); */
+static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned int size, const char **ext, char *title, time_t *file_time)
{
const struct summary_entry *entries=(const struct summary_entry *)&buffer[8];
const unsigned int numEntries=get32u(buffer, 4);
@@ -997,18 +1140,18 @@ static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned in
log_info("Property Info %u entries - %u bytes\n", numEntries, size);
#endif
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
if(numEntries == 0 || numEntries > 1024*1024)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert 0 < numEntries <= 1024*1024; */
if(8 + numEntries * 8 > size)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert 8 + numEntries * 8 <= size; */
@@ -1017,76 +1160,42 @@ static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned in
if((const unsigned char *)&entries[numEntries] > &buffer[size])
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
/*@ assert \valid_read(buffer + (0 .. size - 1)); */
/*@ assert \valid_read((buffer+8) + (8 .. size - 8 - 1)); */
/*@
@ loop invariant *ext == \null || valid_read_string(*ext);
- @ loop invariant *title == \null || valid_read_string(*title);
+ @ loop invariant valid_string(title);
@ loop invariant 0 <= i <= numEntries;
@ loop variant numEntries-i;
@*/
+ /*X TODO loop assigns *ext, *(title + (0..1023)), *file_time; */
for(i=0; i<numEntries; i++)
{
+ const struct summary_entry *entry;
const unsigned int entry_offset=8+8*i;
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
if(entry_offset + 8 > size)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert entry_offset + 8 <= size; */
- {
- const struct summary_entry *entry=(const struct summary_entry *)&buffer[entry_offset];
- const unsigned int tag=le32(entry->tag);
- const unsigned int offset=le32(entry->offset);
- unsigned int type;
- if(offset >= size - 4)
- {
- /*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
- return ;
- }
- /*@ assert offset < size - 4; */
- /*@ assert \valid_read(buffer + (0 .. offset + 4 - 1)); */
- type=get32u(buffer, offset);
-#ifdef DEBUG_OLE
- log_info("entry 0x%x, tag 0x%x, offset 0x%x, offset + 4 0x%x, type 0x%x\n",
- entry, tag, offset, offset + 4, type);
-#endif
- /* tag: Software, type: VT_LPSTR */
- if(tag==0x12 && type==30)
- {
- OLE_parse_software_entry(buffer, size, offset, ext);
- /*@ assert *ext == \null || valid_read_string(*ext); */
- }
- /* tag: Software, type: VT_LPWSTR */
- if(tag==0x12 && type==31)
- {
- OLE_parse_uni_software_entry(buffer, size, offset, ext);
- /*@ assert *ext == \null || valid_read_string(*ext); */
- }
- /* tag: title, type: VT_LPSTR */
- if(tag==0x02 && type==30 && *title==NULL)
- {
- OLE_parse_title_entry(buffer, size, offset, title);
- /*@ assert *title == \null || valid_read_string(*title); */
- }
- /* ModifyDate, type=VT_FILETIME */
- if(tag==0x0d && type==64)
- {
- OLE_parse_filetime_entry(buffer, size, offset, file_time);
- }
- }
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
+ entry=(const struct summary_entry *)&buffer[entry_offset];
+ OLE_parse_PropertySet_entry(buffer, size, entry, ext, title, file_time);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
}
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
}
/*@
@@ -1094,19 +1203,21 @@ static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned in
@ requires \valid_read(dataPt + (0 .. dirLen-1));
@ requires \initialized(dataPt + (0 .. dirLen-1));
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires valid_string(title);
@ requires *ext == \null || valid_read_string(*ext);
+ @ requires separation: \separated(dataPt+(..), ext, title + (0 .. 1023), file_time);
@ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
@*/
-static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned int dirLen, const char **ext, char **title, time_t *file_time)
+/*X TODO assigns *ext, *(title + (0..1023)), *file_time; */
+static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned int dirLen, const char **ext, char *title, time_t *file_time)
{
unsigned int pos;
assert(dirLen >= 48 && dirLen<=1024*1024);
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
#ifdef DEBUG_OLE
dump_log(dataPt, dirLen);
#endif
@@ -1116,7 +1227,7 @@ static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned in
if(pos > dirLen - 8)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert pos <= dirLen - 8; */
@@ -1126,7 +1237,7 @@ static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned in
if(size <= 8 || size > dirLen || pos + size > dirLen)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert 8 < size; */
@@ -1135,14 +1246,15 @@ static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned in
/*@ assert \valid_read(dataPt + (0 .. dirLen-1)); */
/*@ assert pos + size <= dirLen; */
/*@ assert \valid_read(dataPt + (0 .. pos+size-1)); */
+ /*@ assert \initialized(dataPt + (0 .. dirLen-1)); */
+ /*@ assert pos + size <= dirLen; */
+ /*X TODO assert \initialized(dataPt + (0 .. pos+size-1)); */
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
-#ifndef __FRAMAC__
+ /*@ assert valid_string(title); */
OLE_parse_PropertySet(&dataPt[pos], size, ext, title, file_time);
-#endif
}
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
}
/*@
@@ -1152,7 +1264,7 @@ static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned in
@ requires 48 <= len <= 1024*1024;
@ ensures \result!=\null ==> \valid((char *)\result + (0 .. len-1));
@*/
-static void *OLE_read_ministream(unsigned char *ministream,
+static void *OLE_read_ministream(const unsigned char *ministream,
const uint32_t *minifat, const unsigned int minifat_entries, const unsigned int uMiniSectorShift,
const unsigned int miniblock_start, const unsigned int len, const unsigned int ministream_size)
{
@@ -1196,24 +1308,27 @@ static void *OLE_read_ministream(unsigned char *ministream,
@ requires 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift);
@ requires 6 == le16(header->uMiniSectorShift);
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
@ requires *ext == \null || valid_read_string(*ext);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires valid_string(title);
+ @ requires separation: \separated(file,fat+(..), header, ext, title + (0 .. 1023), file_time);
@ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
@*/
static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned int fat_entries,
const struct OLE_HDR *header, const unsigned int ministream_block, const unsigned int ministream_size,
- const unsigned int block, const unsigned int len, const char **ext, char **title, time_t *file_time,
+ const unsigned int block, const unsigned int len, const char **ext, char *title, time_t *file_time,
const uint64_t offset)
{
const unsigned int uSectorShift=le16(header->uSectorShift);
unsigned char *summary=NULL;
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
if(len < 48 || len>1024*1024)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert 48 <= len <= 1024*1024; */
@@ -1222,13 +1337,13 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in
if(le32(header->csectMiniFat)==0 || ministream_size == 0)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
if(ministream_size > 1024*1024 || le32(header->csectMiniFat) > 2048)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
/*@ assert 0 < le32(header->csectMiniFat) <= 2048; */
@@ -1239,7 +1354,7 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in
if((minifat=OLE_load_MiniFAT(file, header, fat, fat_entries, offset))==NULL)
{
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
return ;
}
ministream=(unsigned char *)OLE_read_stream(file,
@@ -1265,9 +1380,13 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in
summary=MALLOC(4096);
Frama_C_make_unknown((char *)summary, 4096);
/*@ assert \initialized((char *)summary + (0 .. 4096 - 1)); */
-// OLE_parse_summary_aux(summary, 4096, ext, title, file_time);
- /*@ assert *title == \null || valid_read_string(*title); */
+#if 0
+ OLE_parse_summary_aux(summary, 4096, ext, title, file_time);
+ /*@ assert valid_string(title); */
+#else
OLE_parse_PropertySet(summary, 4096, ext, title, file_time);
+#endif
+ /*@ assert valid_string(title); */
free(summary);
}
#else
@@ -1278,17 +1397,18 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in
}
#endif
/*@ assert *ext == \null || valid_read_string(*ext); */
- /*@ assert *title == \null || valid_read_string(*title); */
+ /*@ assert valid_string(title); */
}
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_doc;
@*/
static void file_rename_doc(file_recovery_t *file_recovery)
{
const char *ext=NULL;
- char *title=NULL;
+ char title[1024];
FILE *file;
unsigned char buffer_header[512];
uint32_t *fat;
@@ -1297,6 +1417,8 @@ static void file_rename_doc(file_recovery_t *file_recovery)
unsigned int fat_entries;
unsigned int uSectorShift;
unsigned int num_FAT_blocks;
+ title[0]='\0';
+ /*@ assert valid_string(&title[0]); */
if(strstr(file_recovery->filename, ".sdd")!=NULL)
ext=extension_sdd;
if((file=fopen(file_recovery->filename, "rb"))==NULL)
@@ -1358,10 +1480,15 @@ static void file_rename_doc(file_recovery_t *file_recovery)
#ifdef DEBUG_OLE
log_info("file_rename_doc root_start_block=%u, fat_entries=%u\n", le32(header->root_start_block), fat_entries);
#endif
+#ifndef __FRAMAC__
for(block=le32(header->root_start_block), i=0;
block<fat_entries && block!=0xFFFFFFFE && i<fat_entries;
block=le32(fat[block]), i++)
+#else
+ block=le32(header->root_start_block), i=0;
+#endif
{
+ /*@ assert valid_string(&title[0]); */
struct OLE_DIR *dir_entries;
#ifdef __FRAMAC__
dir_entries=(struct OLE_DIR *)MALLOC(1<<12);
@@ -1373,12 +1500,12 @@ static void file_rename_doc(file_recovery_t *file_recovery)
free(fat);
free(dir_entries);
fclose(file);
- free(title);
return ;
}
#ifdef DEBUG_OLE
log_info("Root Directory block=%u (0x%x)\n", block, block);
#endif
+ /*@ assert valid_string(&title[0]); */
{
unsigned int sid;
int is_db=0;
@@ -1388,10 +1515,12 @@ static void file_rename_doc(file_recovery_t *file_recovery)
ministream_block=le32(dir_entry->start_block);
ministream_size=le32(dir_entry->size);
}
+ /*@ assert valid_string(&title[0]); */
for(sid=0;
sid<(1<<uSectorShift)/sizeof(struct OLE_DIR);
sid++)
{
+ /*@ assert valid_string(&title[0]); */
const struct OLE_DIR *dir_entry=&dir_entries[sid];
if(dir_entry->type!=NO_ENTRY)
{
@@ -1403,9 +1532,10 @@ static void file_rename_doc(file_recovery_t *file_recovery)
'r', '\0', 'm', '\0', 'a', '\0', 't', '\0',
'i', '\0', 'o', '\0', 'n', '\0', '\0', '\0'
};
+ const unsigned int namsiz=le16(dir_entry->namsiz);
#ifdef DEBUG_OLE
unsigned int j;
- for(j=0;j<64 && j<le16(dir_entry->namsiz) && dir_entry->name[j]!='\0';j+=2)
+ for(j=0;j<64 && j<namsiz && dir_entry->name[j]!='\0';j+=2)
{
log_info("%c",dir_entry->name[j]);
}
@@ -1422,13 +1552,15 @@ static void file_rename_doc(file_recovery_t *file_recovery)
ext=tmp;
/*@ assert ext == \null || valid_read_string(ext); */
}
- switch(le16(dir_entry->namsiz))
+ /*@ assert valid_string(&title[0]); */
+ switch(namsiz)
{
case 4:
if(sid==1 && memcmp(&dir_entry->name, "1\0\0\0", 4)==0)
is_db=1;
else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "2\0\0\0", 4)==0)
is_db=2;
+ /*@ assert valid_string(&title[0]); */
break;
case 16:
if(sid==1 && memcmp(dir_entry->name, "d\0o\0c\0.\0d\0e\0t\0\0\0", 16)==0)
@@ -1438,6 +1570,7 @@ static void file_rename_doc(file_recovery_t *file_recovery)
ext=extension_snt;
else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "C\0a\0t\0a\0l\0o\0g\0\0\0", 16)==0)
is_db=2;
+ /*@ assert valid_string(&title[0]); */
break;
case 18:
/* MS Excel
@@ -1445,36 +1578,50 @@ static void file_rename_doc(file_recovery_t *file_recovery)
if(ext==NULL &&
memcmp(dir_entry->name, "W\0o\0r\0k\0b\0o\0o\0k\0\0\0",18)==0)
ext=extension_xls;
+ /*@ assert valid_string(&title[0]); */
break;
case 36:
/* sda=StarDraw, sdd=StarImpress */
if(ext!=extension_sdd &&
memcmp(dir_entry->name, "S\0t\0a\0r\0D\0r\0a\0w\0D\0o\0c\0u\0m\0e\0n\0t\0003\0\0\0", 36)==0)
ext=extension_sda;
+ /*@ assert valid_string(&title[0]); */
break;
case 40:
if(memcmp(dir_entry->name, SummaryInformation, 40)==0)
{
+ /*@ assert ext == \null || valid_read_string(ext); */
+ /*@ assert valid_string(&title[0]); */
OLE_parse_summary(file, fat, fat_entries, header,
ministream_block, ministream_size,
le32(dir_entry->start_block), le32(dir_entry->size),
- &ext, &title, &file_time, 0);
+ &ext, &title[0], &file_time, 0);
+ /*@ assert valid_string(&title[0]); */
+ /*@ assert ext == \null || valid_read_string(ext); */
}
+ /*@ assert valid_string(&title[0]); */
+ break;
+ default:
+ /*@ assert valid_string(&title[0]); */
break;
}
- if(sid==1 && le16(dir_entry->namsiz) >=6 &&
+ /*@ assert valid_string(&title[0]); */
+ if(sid==1 && namsiz >=6 &&
memcmp(dir_entry->name, "D\0g\0n", 6)==0)
ext=extension_dgn;
#ifdef DEBUG_OLE
if(ext!=NULL)
- log_info("Found %s %u\n", ext, le16(dir_entry->namsiz));
+ log_info("Found %s %u\n", ext, namsiz);
#endif
+ /*@ assert valid_string(&title[0]); */
}
+ /*@ assert valid_string(&title[0]); */
}
if(ext==NULL && is_db==2)
ext=extension_db;
}
free(dir_entries);
+ /*@ assert valid_string(&title[0]); */
}
}
free(fat);
@@ -1483,8 +1630,7 @@ static void file_rename_doc(file_recovery_t *file_recovery)
set_date(file_recovery->filename, file_time, file_time);
if(title!=NULL)
{
- file_rename(file_recovery, (const unsigned char*)title, strlen(title), 0, ext, 1);
- free(title);
+ file_rename(file_recovery, &title, strlen((const char *)title), 0, ext, 1);
}
else
file_rename(file_recovery, NULL, 0, 0, ext, 1);
@@ -1501,12 +1647,16 @@ static void file_rename_doc(file_recovery_t *file_recovery)
@ ensures \result == 0 || \result == 1;
@ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
@ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
@ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
@ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_doc);
@ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_doc);
@ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
@ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
+ // TODO ensures *buffer == \old(*buffer);
+ // TODO ensures *file_recovery == \old(*file_recovery);
static int header_check_doc(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)
{
/*@ assert file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename); */
@@ -1677,6 +1827,7 @@ int main()
memcpy(file_recovery_new.filename, fn, sizeof(fn));
/*@ assert valid_read_string((char *)&file_recovery_new.filename); */
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*X TODO assert valid_read_string(file_recovery_new.extension); */
file_recovery_new.file_stat=&file_stats;
if(file_recovery_new.file_stat!=NULL)
{
diff --git a/src/file_emf.c b/src/file_emf.c
index db02070..b4a10d0 100644
--- a/src/file_emf.c
+++ b/src/file_emf.c
@@ -30,10 +30,11 @@
#include "filegen.h"
#include "log.h"
#include "common.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
static void register_header_check_emf(file_stat_t *file_stat);
-static int header_check_emf(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);
-static data_check_t data_check_emf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
const file_hint_t file_hint_emf= {
.extension="emf",
@@ -201,37 +202,30 @@ struct EMF_HDR
#define EMR_COLORMATCHTOTARGETW 121
#define EMR_CREATECOLORSPACEW 122
-static int header_check_emf(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)
-{
- static const unsigned char emf_header[4]= { 0x01, 0x00, 0x00, 0x00};
- const struct EMF_HDR *hdr=(const struct EMF_HDR *)buffer;
- const unsigned int atom_size=le32(hdr->emr.nSize);
- if(memcmp(buffer,emf_header,sizeof(emf_header))==0 &&
- le32(hdr->nBytes) >= 88 &&
- le16(hdr->sReserved)==0 &&
- atom_size>=0x34 && atom_size%4==0)
- {
- reset_file_recovery(file_recovery_new);
- file_recovery_new->extension=file_hint_emf.extension;
- if(file_recovery_new->blocksize >= 8)
- {
- file_recovery_new->data_check=&data_check_emf;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->calculated_file_size=atom_size;
- }
- return 1;
- }
- return 0;
-}
-
+/*@
+ @ requires buffer_size >= 2;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_emf;
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP || \result == DC_ERROR;
+ @ ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8);
+ @ ensures file_recovery->data_check==&data_check_emf;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_emf(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 + 8 < 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 itype=buffer[i]+(buffer[i+1]<<8)+(buffer[i+2]<<16)+(buffer[i+3]<<24);
- const unsigned int atom_size=buffer[i+4]+(buffer[i+5]<<8)+(buffer[i+6]<<16)+(buffer[i+7]<<24);
+ const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
+ /*@ assert 0 <= i < buffer_size - 8 ; */
+ const U_EMR *hdr=(const U_EMR *)&buffer[i];
+ const unsigned int itype=le32(hdr->iType);
+ const unsigned int atom_size=le32(hdr->nSize);
#ifdef DEBUG_EMF
log_trace("0x%llx ", (long long unsigned)file_recovery->calculated_file_size);
switch(itype)
@@ -362,15 +356,158 @@ static data_check_t data_check_emf(const unsigned char *buffer, const unsigned i
#endif
if(atom_size<8 || atom_size%4!=0 || atom_size>1024*1024)
return DC_ERROR;
+ /*@ assert 8 <= atom_size <= 1024*1024; */
file_recovery->calculated_file_size+=(uint64_t)atom_size;
if(itype==EMR_EOF)
return DC_STOP;
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size + buffer_size/2 - 8 + 1024*1024; */
}
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8; */
+ /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8; */
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_emf.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= 0x34);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_emf);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_emf(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)
+{
+ static const unsigned char emf_header[4]= { 0x01, 0x00, 0x00, 0x00};
+ const struct EMF_HDR *hdr=(const struct EMF_HDR *)buffer;
+ const unsigned int atom_size=le32(hdr->emr.nSize);
+ if(buffer_size < sizeof(struct EMF_HDR))
+ return 0;
+ if(memcmp(buffer,emf_header,sizeof(emf_header))==0 &&
+ le32(hdr->nBytes) >= 88 &&
+ le16(hdr->sReserved)==0 &&
+ atom_size>=0x34 && atom_size%4==0)
+ {
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_emf.extension;
+ if(file_recovery_new->blocksize >= 8)
+ {
+ file_recovery_new->data_check=&data_check_emf;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->calculated_file_size=atom_size;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_emf(file_stat_t *file_stat)
{
static const unsigned char emf_sign[4]= { ' ','E', 'M','F'};
register_header_check(0x28, emf_sign,sizeof(emf_sign), &header_check_emf, file_stat);
}
+
+#if defined(MAIN_emf)
+#define BLOCKSIZE 65536u
+int main()
+{
+ const char fn[] = "recup_dir.1/f0000000.emf";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_emf;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+ register_header_check_emf(&file_stats);
+ if(header_check_emf(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.calculated_file_size > 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_emf; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == \null; */
+ /*@ assert file_recovery_new.extension == file_hint_emf.extension; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert \separated(&file_recovery_new, file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ /*@ assert valid_read_string((char *)&file_recovery_new.filename); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*X TODO assert valid_read_string(file_recovery_new.extension); */
+ file_recovery_new.file_stat=&file_stats;
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_emf; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_emf(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_emf(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ /* Test when another file of the same is detected in the next block */
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+ header_check_emf(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ {
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ }
+ return 0;
+}
+#endif
diff --git a/src/file_exe.c b/src/file_exe.c
index ade58b0..2050e21 100644
--- a/src/file_exe.c
+++ b/src/file_exe.c
@@ -58,11 +58,19 @@ static const unsigned char exe_header[2] = {'M','Z'};
@ requires buffer_size >= 2;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_exe, buffer+(..), file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_exe.extension || file_recovery_new->extension == extension_dll);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || file_recovery_new->file_rename == &file_rename_pe_exe);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_exe(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)
{
@@ -285,6 +293,7 @@ static char InternalName[24]={
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_String(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -300,12 +309,16 @@ static int parse_String(file_recovery_t *file_recovery, const char*buffer, const
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
type=le16(PE_index->type);
+#ifdef DEBUG_EXE
log_info("parse_String len=%u val_len=%u type=%u\n", len, val_len, type);
+#endif
if(len > end)
return -1;
if(6 + 2 * val_len > len)
return -1;
+#ifdef DEBUG_EXE
dump_log(buffer, len);
+#endif
// type=1 => text
if(6+needle_len < end && type==1 && memcmp(&buffer[6], needle, needle_len)==0)
{
@@ -322,11 +335,14 @@ static int parse_String(file_recovery_t *file_recovery, const char*buffer, const
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringArray(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
unsigned int pos=0;
+#ifdef DEBUG_EXE
log_info("parse_StringArray end=%u\n", end);
+#endif
/*@
@ loop variant end - pos;
@*/
@@ -350,6 +366,7 @@ static int parse_StringArray(file_recovery_t *file_recovery, const char*buffer,
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -365,7 +382,9 @@ static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer,
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_StringTable len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len > end)
return -1;
/* szKey: language identifier + code page */
@@ -385,6 +404,7 @@ static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer,
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -401,7 +421,9 @@ static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffe
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_StringFileInfo len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len > end)
return -1;
if(6 + sizeof(StringFileInfo) > end)
@@ -427,6 +449,8 @@ static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffe
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(vs_version_info+(..), file_recovery, buffer+(..), needle+(..));
+ @ behavior types: requires \separated(vs_version_info+(..), \union(file_recovery, buffer+(..), needle+(..)));
@*/
static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -444,7 +468,9 @@ static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffe
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_VS_VERSIONINFO len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len==0 && val_len==0)
{
return -1;
@@ -488,7 +514,9 @@ static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffe
static void PEVersion(FILE *file, const unsigned int offset, const unsigned int length, file_recovery_t *file_recovery)
{
char buffer[1024*1024];
+#ifdef DEBUG_EXE
log_info("PEVersion(file, %u, %u, file_recovery)\n", offset, length);
+#endif
if(length==0 || length > 1024*1024)
return;
if(fseek(file, offset, SEEK_SET)<0)
@@ -586,7 +614,9 @@ static void pe_resource_language(FILE *file, const unsigned int base, const unsi
idEntries = buffer[14]+(buffer[15]<<8);
count = nameEntries + idEntries;
}
+#ifdef DEBUG_EXE
log_info("pe_resource_language count=%u\n", count);
+#endif
if(count==0 || count > 1024)
return ;
/*@ assert 0 < count <= 1024; */
@@ -765,6 +795,7 @@ static void pe_resource_type(FILE *file, const unsigned int base, const unsigned
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)&file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_pe_exe;
@*/
static void file_rename_pe_exe(file_recovery_t *file_recovery)
{
@@ -954,17 +985,19 @@ int main()
}
if(file_recovery_new.file_check!=NULL)
{
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
file_recovery_new.handle=fopen(fn, "rb");
if(file_recovery_new.handle!=NULL)
{
- (file_recovery_new.file_check)(&file_recovery_new);
+ file_check_size(&file_recovery_new);
fclose(file_recovery_new.handle);
}
}
if(file_recovery_new.file_rename!=NULL)
{
/*@ assert valid_read_string((char *)&file_recovery_new.filename); */
- (file_recovery_new.file_rename)(&file_recovery_new);
+ /*@ assert file_recovery_new.file_rename == &file_rename_pe_exe; */
+ file_rename_pe_exe(&file_recovery_new);
}
return 0;
}
diff --git a/src/file_gpg.c b/src/file_gpg.c
index 84a5587..6492aed 100644
--- a/src/file_gpg.c
+++ b/src/file_gpg.c
@@ -87,6 +87,7 @@ static const unsigned char pgp_header[5]= {0xa8, 0x03, 'P', 'G', 'P'};
/*@
@ ensures 0 <= \result <= 0x3f;
+ @ assigns \nothing;
@*/
static unsigned int openpgp_packet_tag(const unsigned char buf)
{
@@ -100,6 +101,7 @@ static unsigned int openpgp_packet_tag(const unsigned char buf)
@ requires \valid(length_type);
@ requires \valid(indeterminate_length);
@ ensures (*length_type == 1) || (*length_type == 2) || (*length_type==3)|| (*length_type==5);
+ @ assigns *length_type, *indeterminate_length;
*/
static unsigned int old_format_packet_length(const unsigned char *buf, unsigned int *length_type, int *indeterminate_length)
{
@@ -128,50 +130,60 @@ static unsigned int old_format_packet_length(const unsigned char *buf, unsigned
/*@ requires \valid_read(buf+(0..5));
@ requires \valid(length_type);
@ requires \valid(partial_body_length);
+ @ requires separation: \separated(buf+(0..5), length_type, partial_body_length);
@ ensures (*length_type == 1) || (*length_type == 2) || (*length_type==5);
@ ensures (*partial_body_length==0) || (*partial_body_length==1);
+ @ assigns *length_type, *partial_body_length;
*/
static unsigned int new_format_packet_length(const unsigned char *buf, unsigned int *length_type, int *partial_body_length)
{
+ const unsigned char buf0=buf[0];
*partial_body_length=0;
/* One-Octet Body Length */
- if(buf[0]<=191)
+ if(buf0<=191)
{
*length_type=1;
- /*@ assert 0 <= buf[0] <= 191; */
- return buf[0];
+ /*@ assert buf0 <= 191; */
+ return buf0;
}
/* Two-Octet Body Length */
- if(buf[0]<=223)
+ if(buf0<=223)
{
- /*@ assert 192 <= buf[0] <= 223; */
- unsigned int tmp=buf[0];
+ /*@ assert 192 <= buf0 <= 223; */
+ unsigned int tmp=buf0;
/*@ assert 192 <= tmp <= 223; */
tmp = ((tmp-192) << 8) + buf[1] + 192;
- /*@ assert 192 <= tmp <= ((223-192) << 8) + 255 + 192; */
*length_type=2;
+ /*@ assert 192 <= tmp <= ((223-192) << 8) + 255 + 192; */
return tmp;
}
+ /*@ assert 224 <= buf0; */
/* Five-Octet Body Length */
- if(buf[0]==255)
+ if(buf0==255)
{
const uint32_t *tmp32=(const uint32_t *)&buf[1];
const unsigned int tmp=be32(*tmp32);
*length_type=5;
+ /*@ assert tmp <= 0xffffffff; */
return tmp;
}
+ /*@ assert buf0 != 255; */
+ /*@ assert 224 <= buf0 <= 254; */
{
- /*@ assert 224 <= buf[0] <= 254; */
- const unsigned int tmp=buf[0]&0x1fu;
+ const unsigned int tmp=buf0&0x1fu;
+ /*@ assert tmp <= 30; */
+ const unsigned int tmp2=1u << tmp;
/* Partial Body Lengths */
*length_type=1;
*partial_body_length=1;
- return 1u << tmp;
+ /*@ assert tmp2 <= (1<<30); */
+ return tmp2;
}
}
/*@
@ ensures \result == -1 || 0 <= \result <= 2048;
+ @ assigns \nothing;
@*/
static int is_valid_mpi(const uint16_t size)
{
@@ -183,6 +195,7 @@ static int is_valid_mpi(const uint16_t size)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_pubkey_algo(const int algo)
{
@@ -213,6 +226,7 @@ static int is_valid_pubkey_algo(const int algo)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_sym_algo(const int algo)
{
@@ -249,6 +263,7 @@ static int is_valid_sym_algo(const int algo)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_S2K(const unsigned int algo)
{
@@ -264,8 +279,32 @@ static int is_valid_S2K(const unsigned int algo)
}
/*@
+ @ requires \valid(handle);
+ @ requires offset + tmp2 < 0x8000000000000000;
+ @*/
+static unsigned int file_check_gpg_pubkey(FILE *handle, const uint64_t offset, const uint64_t tmp2)
+{
+ int len2;
+ uint16_t mpi2;
+ if(my_fseek(handle, offset+tmp2, SEEK_SET) < 0 ||
+ fread(&mpi2, sizeof(mpi2), 1, handle) != 1)
+ return 0;
+#ifdef __FRAMAC__
+ Frama_C_make_unknown((char *)&mpi2, sizeof(mpi2));
+#endif
+ len2=is_valid_mpi(mpi2);
+#ifdef DEBUG_GPG
+ log_info(" data: [ %u bits]\n", be16(mpi2));
+#endif
+ if(len2 < 0)
+ return 0;
+ return len2;
+}
+
+/*@
@ requires \valid(file_recovery);
@ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_gpg;
@*/
static void file_check_gpg(file_recovery_t *file_recovery)
{
@@ -283,12 +322,16 @@ static void file_check_gpg(file_recovery_t *file_recovery)
unsigned int length_type=0;
unsigned int length;
const int old_partial_body_length=partial_body_length;
- if(nbr >=0xffffffff || offset + 6 >= 0x8000000000000000)
+ if(nbr >=0xffffffff || offset >= 0x7000000000000000)
return;
- /*@ assert offset < 0x8000000000000000 - 6; */
+ /*@ assert offset < 0x7000000000000000; */
if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0 ||
fread(&buffer, sizeof(buffer), 1, file_recovery->handle) != 1)
+ {
+ if(nbr>=2 && offset <= org_file_size)
+ file_recovery->file_size=org_file_size;
return;
+ }
#ifdef __FRAMAC__
Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
#endif
@@ -330,49 +373,44 @@ static void file_check_gpg(file_recovery_t *file_recovery)
i+=length_type;
/*@ assert 0 < i <= 6; */
offset+=length_type;
- /*@ assert offset < 0x8000000000000000; */
- if(offset + length >= 0x8000000000000000)
+ if(offset >= 0x7000000000000000 || offset + length >= 0x7000000000000000)
return ;
+ /*@ assert offset < 0x7000000000000000; */
+ /*@ assert offset + length < 0x7000000000000000; */
if(old_partial_body_length==0)
{
if(tag==OPENPGP_TAG_PUBKEY_ENC_SESSION_KEY)
{
const uint16_t *mpi_ptr=(const uint16_t *)&buffer[i+1+8+1];
const int len=is_valid_mpi(*mpi_ptr);
+ const int pubkey_algo=buffer[i+1+8];
/* uint8_t version must be 3
* uint64_t pub_key_id
* uint8_t pub_key_algo
* encrypted_session_key */
- if(buffer[i]==3 && is_valid_pubkey_algo(buffer[i+1+8]) &&
+ if(buffer[i]==3 && is_valid_pubkey_algo(pubkey_algo) &&
len>0)
{
+ /* assert 0 < len <=2048; */
+ const unsigned int tmp2=1+8+1+2+len;
+ /* assert 12 < tmp2 <=12+2048; */
#ifdef DEBUG_GPG
log_info("GPG :pubkey enc packet: version %u, algo %u, keyid %02X%02X%02X%02X%02X%02X%02X%02X\n",
- buffer[i], buffer[i+1+8],
+ buffer[i], pubkey_algo,
buffer[i+1], buffer[i+2], buffer[i+3], buffer[i+4],
buffer[i+5], buffer[i+6], buffer[i+7], buffer[i+8]);
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
- if((unsigned)(1+8+1+2+len) > length)
+ if(tmp2 > length)
return ;
- if(buffer[i+1+8]==16 || buffer[i+1+8]==20)
+ /*@ assert tmp2 <= length; */
+ if(pubkey_algo==16 || pubkey_algo==20)
{
- int len2;
- uint16_t mpi2;
- if(my_fseek(file_recovery->handle, offset+1+8+1+2+len, SEEK_SET) < 0 ||
- fread(&mpi2, sizeof(mpi2), 1, file_recovery->handle) != 1)
- return;
-#ifdef __FRAMAC__
- Frama_C_make_unknown((char *)&mpi2, sizeof(mpi2));
-#endif
- len2=is_valid_mpi(mpi2);
-#ifdef DEBUG_GPG
- log_info(" data: [ %u bits]\n", be16(*mpi2));
-#endif
+ const int len2=file_check_gpg_pubkey(file_recovery->handle, offset, tmp2);
if(len2 <= 0)
- return ;
+ return;
if((unsigned)(1+8+1+2+len+2+len2) > length)
- return ;
+ return;
}
}
else
@@ -466,8 +504,18 @@ static void file_check_gpg(file_recovery_t *file_recovery)
@ requires file_recovery_new->blocksize > 0;
@ requires separation: \separated(file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_gpg);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_gpg.extension || file_recovery_new->extension == extension_pgp);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_gpg);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_gpg(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)
{
@@ -512,7 +560,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
/*@ assert 0 <= length_type <= 6; */
tag=packet_tag[nbr];
#ifdef DEBUG_GPG
- log_info("GPG 0x%04x: %02u tag=%2u, size=%u + %u)\n",
+ log_info("GPG 0x%04lx: %02u tag=%2u, size=%u + %u)\n",
i, nbr, tag, length_type, length);
#endif
#if 0
@@ -543,7 +591,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
buffer[i], buffer[i+1+8],
buffer[i+1], buffer[i+2], buffer[i+3], buffer[i+4],
buffer[i+5], buffer[i+6], buffer[i+7], buffer[i+8]);
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
if(offset_mpi +2 > length)
return 0;
@@ -555,7 +603,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
mpi_ptr=(const uint16_t *)&buffer[offset_mpi];
len2=is_valid_mpi(*mpi_ptr);
#ifdef DEBUG_GPG
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
if(len2 <= 0)
return 0;
@@ -737,7 +785,6 @@ int main()
{
const char fn[] = "recup_dir.1/f0000000.gpg";
unsigned char buffer[BLOCKSIZE];
- int res;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
file_stat_t file_stats;
diff --git a/src/file_gz.c b/src/file_gz.c
index 0ef52e0..f67cb84 100644
--- a/src/file_gz.c
+++ b/src/file_gz.c
@@ -23,6 +23,11 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_LIBZ
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -157,17 +162,6 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
}
if(off >= 512 || off >= buffer_size)
return 0;
- if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_doc)
- {
- if(header_ignored_adv(file_recovery, file_recovery_new)==0)
- return 0;
- }
- if(file_recovery->file_check==&file_check_bgzf)
- {
- header_ignored(file_recovery_new);
- return 0;
- }
#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ)
{
static const unsigned char schematic_header[12]={ 0x0a, 0x00, 0x09,
@@ -207,6 +201,17 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
/* Probably too small to be a file */
if(d_stream.total_out < 16)
return 0;
+ if(file_recovery->file_stat!=NULL &&
+ file_recovery->file_stat->file_hint==&file_hint_doc)
+ {
+ if(header_ignored_adv(file_recovery, file_recovery_new)==0)
+ return 0;
+ }
+ if(file_recovery->file_check==&file_check_bgzf)
+ {
+ header_ignored(file_recovery_new);
+ return 0;
+ }
buffer_uncompr[d_stream.total_out]='\0';
if(bgzf!=0)
{
@@ -297,6 +302,17 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
}
}
#else
+ if(file_recovery->file_stat!=NULL &&
+ file_recovery->file_stat->file_hint==&file_hint_doc)
+ {
+ if(header_ignored_adv(file_recovery, file_recovery_new)==0)
+ return 0;
+ }
+ if(file_recovery->file_check==&file_check_bgzf)
+ {
+ header_ignored(file_recovery_new);
+ return 0;
+ }
reset_file_recovery(file_recovery_new);
file_recovery_new->min_filesize=22;
file_recovery_new->time=le32(gz->mtime);
diff --git a/src/file_jpg.c b/src/file_jpg.c
index 64abd7b..67c2723 100644
--- a/src/file_jpg.c
+++ b/src/file_jpg.c
@@ -23,6 +23,12 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_LIBJPEG
+#undef DEBUG_JPEG
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -53,7 +59,7 @@
#include "__fc_builtin.h"
#endif
-#ifndef MAIN_jpg
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
extern const file_hint_t file_hint_doc;
extern const file_hint_t file_hint_indd;
extern const file_hint_t file_hint_mov;
@@ -64,7 +70,7 @@ extern data_check_t data_check_avi_stream(const unsigned char *buffer, const uns
static void register_header_check_jpg(file_stat_t *file_stat);
static void file_check_jpg(file_recovery_t *file_recovery);
-data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
+static data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_size, const unsigned i, const unsigned int size);
const file_hint_t file_hint_jpg= {
@@ -112,7 +118,7 @@ struct MP_IFD_Field
uint16_t tag;
uint16_t type;
uint32_t count;
- char value[0];
+ char value[4];
} __attribute__ ((gcc_struct, __packed__));
struct MP_Entry
@@ -126,7 +132,8 @@ struct MP_Entry
/*@
@ requires size >= 8;
- @ requires \valid(mpo + ( 0 .. size-1));
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
@*/
static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset, const unsigned int size)
{
@@ -137,40 +144,55 @@ static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset
unsigned int nbr;
unsigned int NumberOfImages=0;
unsigned int MPEntry_offset=0;
- const struct MP_Entry* MPEntry;
uint64_t max_offset=0;
#ifdef DEBUG_JPEG
log_info("check_mpo_be\n");
#endif
- if(offset+2 >= size)
+ if(offset >= size - 2)
return 0;
+ /*@ assert offset < size - 2; */
tmp16=(const uint16_t*)(&mpo[offset]);
nbr=be16(*tmp16);
offset+=2;
+ /* @offset: MP Index Fields*/
+ if(offset + nbr * 12 > size)
+ return 0;
+ /*@ assert offset + nbr * 12 <= size; */
+ /*@
+ @ loop invariant 0 <= i <= nbr;
+ @ loop assigns i, NumberOfImages, MPEntry_offset;
+ @ loop variant nbr-i;
+ @*/
for(i=0; i< nbr; i++)
{
- const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)(&mpo[offset]);
- if(offset+12 > size)
- return 0;
+ /*@ assert 0 <= i < nbr; */
+ const unsigned char *field_ptr=&mpo[offset + i * 12];
+ /*@ assert \valid_read(field_ptr + ( 0 .. sizeof(struct MP_IFD_Field)-1)); */
+ const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)field_ptr;
+ const unsigned int count=be32(field->count);
+ const unsigned int type=be16(field->type);
switch(be16(field->tag))
{
case 0xb000:
/* MPFVersion, type must be undefined */
- if(be16(field->type)!=7 || be32(field->count)!=4)
+ if(type!=7 || count!=4)
return 0;
break;
case 0xb001:
/* NumberOfImages, type must be long */
- if(be16(field->type)!=4 || be32(field->count)!=1)
+ if(type!=4 || count!=1)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
NumberOfImages=be32(*tmp);
+ if(NumberOfImages >= 0x100000)
+ return 0;
+ /*@ assert NumberOfImages < 0x100000; */
}
break;
case 0xb002:
/* MPEntry, type must be undefined */
- if(be16(field->type)!=7 || be32(field->count)!=16*NumberOfImages)
+ if(type!=7 || count!=16*NumberOfImages)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
@@ -178,25 +200,34 @@ static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset
}
break;
}
- offset+=12;
}
#ifdef DEBUG_JPEG
log_info("MPEntry_offset=%u, NumberOfImages=%u\n", MPEntry_offset, NumberOfImages);
#endif
+ /*@ assert NumberOfImages < 0x100000; */
+ if(MPEntry_offset > size)
+ return 0;
if(MPEntry_offset + 16*NumberOfImages > size)
return 0;
- for(i=0, MPEntry=(const struct MP_Entry*)(&mpo[MPEntry_offset]);
- i<NumberOfImages;
- i++, MPEntry++)
+ /*@
+ @ loop invariant 0 <= i <= NumberOfImages;
+ @ loop assigns i, max_offset;
+ @ loop variant NumberOfImages-i;
+ @*/
+ for(i=0; i<NumberOfImages; i++)
{
- uint64_t tmp=be32(MPEntry->offset)+be32(MPEntry->size);
+ /*@ assert 0 <= i < NumberOfImages; */
+ const unsigned char *MPEntry_ptr=&mpo[MPEntry_offset + i * sizeof(struct MP_Entry)];
+ /*@ assert \valid_read(MPEntry_ptr+ ( 0 .. sizeof(struct MP_Entry)-1)); */
+ const struct MP_Entry *MPEntry=(const struct MP_Entry*)MPEntry_ptr;
+ uint64_t tmp=be32(MPEntry->size);
#ifdef DEBUG_JPEG
log_info("offset=%lu, size=%lu\n",
(long unsigned)be32(MPEntry->offset),
(long unsigned)be32(MPEntry->size));
#endif
if(be32(MPEntry->offset)>0)
- tmp+=mpo_offset;
+ tmp+=be32(MPEntry->offset)+mpo_offset;
if(max_offset < tmp)
max_offset = tmp;
}
@@ -205,51 +236,69 @@ static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset
/*@
@ requires size >= 8;
- @ requires \valid(mpo + ( 0 .. size-1));
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
@*/
static uint64_t check_mpo_le(const unsigned char *mpo, const uint64_t mpo_offset, const unsigned int size)
{
const uint16_t *tmp16;
+ /* Offset to first IFD */
const uint32_t *tmp32=(const uint32_t *)(&mpo[4]);
unsigned int offset=le32(*tmp32);
unsigned int i;
unsigned int nbr;
unsigned int NumberOfImages=0;
unsigned int MPEntry_offset=0;
- const struct MP_Entry* MPEntry;
uint64_t max_offset=0;
#ifdef DEBUG_JPEG
log_info("check_mpo_le\n");
#endif
- if(offset+2 >= size)
+ if(offset >= size - 2)
return 0;
+ /*@ assert offset < size - 2; */
tmp16=(const uint16_t*)(&mpo[offset]);
nbr=le16(*tmp16);
offset+=2;
+ /* @offset: MP Index Fields*/
+ if(offset + nbr * 12 > size)
+ return 0;
+ /*@ assert offset + nbr * 12 <= size; */
+ /*@
+ @ loop invariant 0 <= i <= nbr;
+ @ loop assigns i, NumberOfImages, MPEntry_offset;
+ @ loop variant nbr-i;
+ @*/
for(i=0; i< nbr; i++)
{
- const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)(&mpo[offset]);
- if(offset+12 > size)
- return 0;
+ /*@ assert 0 <= i < nbr; */
+ const unsigned char *field_ptr=&mpo[offset + i * 12];
+ /*@ assert \valid_read(field_ptr + ( 0 .. sizeof(struct MP_IFD_Field)-1)); */
+ const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)field_ptr;
+ /*@ assert \valid_read(field); */
+ const unsigned int count=le32(field->count);
+ const unsigned int type=le16(field->type);
switch(le16(field->tag))
{
case 0xb000:
/* MPFVersion, type must be undefined */
- if(le16(field->type)!=7 || le32(field->count)!=4)
+ if(type!=7 || count!=4)
return 0;
break;
case 0xb001:
/* NumberOfImages, type must be long */
- if(le16(field->type)!=4 || le32(field->count)!=1)
+ if(type!=4 || count!=1)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
NumberOfImages=le32(*tmp);
+ if(NumberOfImages >= 0x100000)
+ return 0;
+ /*@ assert NumberOfImages < 0x100000; */
}
break;
case 0xb002:
/* MPEntry, type must be undefined */
- if(le16(field->type)!=7 || le32(field->count)!=16*NumberOfImages)
+ if(type!=7 || count!=16*NumberOfImages)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
@@ -257,25 +306,34 @@ static uint64_t check_mpo_le(const unsigned char *mpo, const uint64_t mpo_offset
}
break;
}
- offset+=12;
}
#ifdef DEBUG_JPEG
log_info("MPEntry_offset=%u, NumberOfImages=%u\n", MPEntry_offset, NumberOfImages);
#endif
+ /*@ assert NumberOfImages < 0x100000; */
+ if(MPEntry_offset > size)
+ return 0;
if(MPEntry_offset + 16*NumberOfImages > size)
return 0;
- for(i=0, MPEntry=(const struct MP_Entry*)(&mpo[MPEntry_offset]);
- i<NumberOfImages;
- i++, MPEntry++)
+ /*@
+ @ loop invariant 0 <= i <= NumberOfImages;
+ @ loop assigns i, max_offset;
+ @ loop variant NumberOfImages-i;
+ @*/
+ for(i=0; i<NumberOfImages; i++)
{
- uint64_t tmp=le32(MPEntry->offset)+le32(MPEntry->size);
+ /*@ assert 0 <= i < NumberOfImages; */
+ const unsigned char *MPEntry_ptr=&mpo[MPEntry_offset + i * sizeof(struct MP_Entry)];
+ /*@ assert \valid_read(MPEntry_ptr+ ( 0 .. sizeof(struct MP_Entry)-1)); */
+ const struct MP_Entry *MPEntry=(const struct MP_Entry*)MPEntry_ptr;
+ uint64_t tmp=le32(MPEntry->size);
#ifdef DEBUG_JPEG
log_info("offset=%lu, size=%lu\n",
(long unsigned)le32(MPEntry->offset),
(long unsigned)le32(MPEntry->size));
#endif
if(le32(MPEntry->offset)>0)
- tmp+=mpo_offset;
+ tmp+=(uint64_t)le32(MPEntry->offset) + mpo_offset;
if(max_offset < tmp)
max_offset = tmp;
}
@@ -284,10 +342,15 @@ static uint64_t check_mpo_le(const unsigned char *mpo, const uint64_t mpo_offset
/*@
@ requires size >= 8;
- @ requires \valid(mpo + ( 0 .. size-1));
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
@*/
static uint64_t check_mpo(const unsigned char *mpo, const uint64_t offset, const unsigned int size)
{
+ /* MP header:
+ * - MP Endian (4Byte)
+ * - Offset to First IFD (4Byte)
+ */
if(mpo[0]=='I' && mpo[1]=='I' && mpo[2]=='*' && mpo[3]==0)
{
return check_mpo_le(mpo, offset, size);
@@ -304,6 +367,7 @@ static uint64_t check_mpo(const unsigned char *mpo, const uint64_t offset, const
@ requires \valid(fr->handle);
@ requires valid_read_string((char *)&fr->filename);
@ requires \initialized(&fr->time);
+ @ requires fr->file_check==&file_check_mpo;
@*/
static void file_check_mpo(file_recovery_t *fr)
{
@@ -322,6 +386,12 @@ static void file_check_mpo(file_recovery_t *fr)
do
{
offset+=(uint64_t)2+size;
+ if(offset >= 0x8000000000000000)
+ {
+ fr->file_size=0;
+ return ;
+ }
+ /*@ assert offset < 0x8000000000000000; */
if(my_fseek(fr->handle, offset, SEEK_SET) < 0)
{
fr->file_size=0;
@@ -354,7 +424,7 @@ static void file_check_mpo(file_recovery_t *fr)
fr->file_size=0;
return ;
}
- /*@ assert 16 <= size; */
+ /*@ assert 16 <= size <= 65535; */
{
const uint64_t max_offset=check_mpo(buffer+8, offset+8, size-8);
fr->file_size=(max_offset > fr->file_size ? 0 : max_offset);
@@ -428,25 +498,55 @@ static time_t jpg_get_date(const unsigned char *buffer, const unsigned int buffe
/*@
+ @ requires buffer_size >= 10;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
@ requires file_recovery->file_stat==\null || valid_read_string((char*)&file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_jpg, buffer+(..), file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures \result == 1 ==> file_recovery_new->extension == file_hint_jpg.extension;
- @ ensures \result == 1 ==> valid_read_string(file_recovery_new->extension);
+ @ ensures \result == 1 ==> \initialized(&file_recovery_new->time);
@ ensures \result == 1 ==> file_recovery_new->calculated_file_size == 0;
@ ensures \result == 1 ==> file_recovery_new->file_size == 0;
+ @ ensures \result == 1 ==> file_recovery_new->min_filesize > 0;
@ ensures \result == 1 ==> file_recovery_new->offset_ok == 0;
- @ ensures \result == 1 ==> file_recovery_new->file_check == file_check_jpg;
- @ ensures \result == 1 ==> \initialized(&file_recovery_new->time);
@ ensures \result == 1 && buffer_size >= 4 ==> file_recovery_new->data_check == data_check_jpg;
+ @ ensures \result == 1 ==> file_recovery_new->file_check == file_check_jpg;
+ @ ensures \result == 1 ==> file_recovery_new->file_rename == \null;
+ @ ensures \result == 1 ==> valid_read_string(file_recovery_new->extension);
@*/
static int header_check_jpg(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)
{
unsigned int i=2;
time_t jpg_time=0;
+ while(i+4<buffer_size && buffer[i]==0xff && is_marker_valid(buffer[i+1]))
+ {
+ const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
+ if(buffer[i+1]==0xff)
+ i++;
+ else
+ {
+ if(buffer[i+1]==0xe1)
+ { /* APP1 Exif information */
+ jpg_time=jpg_get_date(buffer, buffer_size, i, size);
+ }
+ else if(buffer[i+1]==0xc4)
+ {
+ /* DHT */
+ if(jpg_check_dht(buffer, buffer_size, i, 2+(buffer[i+2]<<8)+buffer[i+3])!=0)
+ return 0;
+ }
+ i+=2+size;
+ }
+ }
+ if(i+1 < file_recovery_new->blocksize && buffer[i+1]!=0xda)
+ return 0;
+ if(i+1 < 512 && buffer[i+1]!=0xda)
+ return 0;
if(file_recovery->file_stat!=NULL)
{
static const unsigned char jpg_header_app0_avi[0x0c]= {
@@ -459,7 +559,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
unsigned int width=0;
unsigned int height=0;
jpg_get_size(buffer, buffer_size, &height, &width);
-#ifndef MAIN_jpg
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
if(file_recovery->file_stat->file_hint==&file_hint_indd)
{
if(header_ignored_adv(file_recovery, file_recovery_new)==0)
@@ -505,7 +605,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
return 0;
}
}
-#ifndef MAIN_jpg
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
/* Don't extract jpg inside AVI */
if( file_recovery->file_stat->file_hint==&file_hint_riff &&
(memcmp(buffer, jpg_header_app0_avi, sizeof(jpg_header_app0_avi))==0 ||
@@ -555,30 +655,6 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
return 0;
}
}
- while(i+4<buffer_size && buffer[i]==0xff && is_marker_valid(buffer[i+1]))
- {
- const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
- if(buffer[i+1]==0xff)
- i++;
- else
- {
- if(buffer[i+1]==0xe1)
- { /* APP1 Exif information */
- jpg_time=jpg_get_date(buffer, buffer_size, i, size);
- }
- else if(buffer[i+1]==0xc4)
- {
- /* DHT */
- if(jpg_check_dht(buffer, buffer_size, i, 2+(buffer[i+2]<<8)+buffer[i+3])!=0)
- return 0;
- }
- i+=2+size;
- }
- }
- if(i+1 < file_recovery_new->blocksize && buffer[i+1]!=0xda)
- return 0;
- if(i+1 < 512 && buffer[i+1]!=0xda)
- return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->min_filesize=i;
file_recovery_new->calculated_file_size=0;
@@ -591,7 +667,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
return 1;
}
-#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H) && !defined(__FRAMAC__)
+#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
struct my_error_mgr {
struct jpeg_error_mgr pub; /* "public" fields, must be the first field */
@@ -812,13 +888,25 @@ static void jpg_term_source (j_decompress_ptr cinfo)
}
+/* WARNING: This function must be listed in clang Control Flow Integrity (CFI) function blacklist, section cfi-icall */
+static void jpeg_testdisk_alloc_src (j_decompress_ptr cinfo, const unsigned int blocksize)
+{
+ my_source_mgr *src= (my_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_source_mgr));
+ cinfo->src = (struct jpeg_source_mgr *) src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ blocksize * sizeof(JOCTET));
+}
+
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
-static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, uint64_t offset, const unsigned int blocksize)
+static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, const uint64_t offset, const unsigned int blocksize)
{
my_source_mgr * src;
@@ -830,13 +918,7 @@ static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, uint64_t o
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof(my_source_mgr));
- src = (my_source_mgr *) cinfo->src;
- src->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- blocksize * sizeof(JOCTET));
+ jpeg_testdisk_alloc_src(cinfo, blocksize);
}
src = (my_source_mgr *) cinfo->src;
@@ -1400,6 +1482,7 @@ static void jpg_check_picture(file_recovery_t *file_recovery)
/*@
@ requires i < buffer_size;
@ requires \valid_read(buffer+(0..buffer_size-1));
+ @ assigns \nothing;
@*/
static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int i, const unsigned int size)
{
@@ -1408,6 +1491,7 @@ static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_
/* DHT should not be longer than 1088 bytes, 4*(1+16+255) */
if(size<18)
return 2;
+ /*@ loop assigns j; */
while(j < buffer_size && j < i+size)
{
const unsigned int tc=buffer[j]>>4;
@@ -1421,6 +1505,12 @@ static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_
if(n > 3)
return 2;
j++;
+ /*@
+ @ loop invariant 0 <= l <= 16;
+ @ loop invariant sum <= l*255;
+ @ loop assigns l,sum;
+ @ loop variant 16-l;
+ @*/
for(l=0; l < 16; l++)
if(j+l < buffer_size)
sum+=buffer[j+l];
@@ -1449,6 +1539,7 @@ struct sof_header
/*@
@ requires \valid_read(buffer + (0..buffer_size-1));
+ @ assigns \nothing;
@*/
static int jpg_check_sof0(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int i)
{
@@ -1456,16 +1547,18 @@ static int jpg_check_sof0(const unsigned char *buffer, const unsigned int buffer
return 0;
{
const struct sof_header *h=(const struct sof_header *)&buffer[i];
- if(be16(h->length) < sizeof(struct sof_header)-2)
+ const unsigned int length=be16(h->length);
+ if(length < sizeof(struct sof_header)-2)
return 1;
}
if(i+2+8 > buffer_size)
return 0;
{
const struct sof_header *h=(const struct sof_header *)&buffer[i];
+ const unsigned int length=be16(h->length);
if(h->precision!=8 || be16(h->width)==0 || h->nbr==0)
return 1;
- if(be16(h->length) < 8+h->nbr*3)
+ if(length < 8+h->nbr*3)
return 1;
}
// if(i+2+be16(h->length) > buffer_size)
@@ -1485,43 +1578,46 @@ static void jpg_search_marker(file_recovery_t *file_recovery)
FILE* infile=file_recovery->handle;
unsigned char buffer[40*8192];
size_t nbytes;
- uint64_t offset_test=file_recovery->offset_error;
+ const uint64_t offset_error=file_recovery->offset_error;
+ uint64_t offset_test=offset_error;
uint64_t offset;
- /*@ assert offset_test == file_recovery->offset_error; */
+ /*@ assert offset_test == offset_error; */
if(file_recovery->blocksize==0)
return ;
offset=offset_test / file_recovery->blocksize * file_recovery->blocksize;
if(my_fseek(infile, offset, SEEK_SET) < 0)
return ;
- /*@ assert offset_test == file_recovery->offset_error; */
+ /*@ assert offset_test == offset_error; */
/*@
- @ loop invariant offset_test >= file_recovery->offset_error;
+ @ loop invariant offset_test >= offset_error;
@*/
while((nbytes=fread(&buffer, 1, sizeof(buffer), infile))>0)
{
unsigned int i;
/*@ assert 0 < nbytes <= sizeof(buffer); */
- /*@ assert offset_test >= file_recovery->offset_error; */
-#if defined(__FRAMAC__)
- Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
if(offset_test > 0x80000000)
return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
#endif
+ /*@ assert offset_test >= offset_error; */
offset=offset_test / file_recovery->blocksize * file_recovery->blocksize;
i=offset_test % file_recovery->blocksize;
/*@ assert offset + i == offset_test; */
/*@ assert i == offset_test - offset; */
- /*@ assert offset_test >= file_recovery->offset_error; */
+ /*@ assert offset_test >= offset_error; */
/*@
@ loop invariant offset + i >= offset_test;
- @ loop invariant offset_test >= file_recovery->offset_error;
+ @ loop invariant offset_test >= offset_error;
@ loop invariant 0 <= i < nbytes + file_recovery->blocksize;
@ loop assigns i,file_recovery->extra;
@*/
while(i+1<nbytes)
{
const uint64_t tmp=offset + i;
+ /*@ assert tmp == offset + i; */
/*@ assert tmp >= offset_test; */
+ /*@ assert offset_test >= offset_error; */
if(buffer[i]==0xff &&
(buffer[i+1]==0xd8 || /* SOI */
buffer[i+1]==0xdb || /* DQT */
@@ -1532,7 +1628,7 @@ static void jpg_search_marker(file_recovery_t *file_recovery)
buffer[i+1]==0xfe) /* COM */
)
{
- file_recovery->extra=tmp - file_recovery->offset_error;
+ file_recovery->extra=tmp - offset_error;
#ifndef __FRAMAC__
if(file_recovery->extra % file_recovery->blocksize != 0)
{
@@ -1683,40 +1779,49 @@ static int jpg_check_app1(file_recovery_t *file_recovery, const unsigned int ext
j+=2U+(buffer[j+2]<<8)+buffer[j+3];
}
if(thumb_sos_found>0 && extract_thumb>0
- && offset < nbytes && buffer[offset]==0xff)
+ && offset < nbytes && buffer[offset]==0xff &&
+ *thumb_offset+thumb_size < nbytes)
{
- char *thumbname;
+ char thumbname[2048];
+ char *sep;
+ /*@ assert sizeof(thumbname) == sizeof(file_recovery->filename); */
/*@ assert valid_read_string((char *)&file_recovery->filename); */
+ memcpy(thumbname,file_recovery->filename, sizeof(thumbname));
+ thumbname[sizeof(thumbname)-1]='\0';
+ /*@ assert valid_read_string(&thumbname[0]); */
+ sep=strrchr(thumbname,'/');
+ if(sep!=NULL
#ifndef __FRAMAC__
- thumbname=strdup(file_recovery->filename);
- if(thumbname!=NULL)
+ && *(sep+1)=='f'
+#endif
+ )
{
- char *sep;
- /*@ assert thumbname!=\null; */
- /*@ assert valid_read_string(thumbname); */
- sep=strrchr(thumbname,'/');
- if(sep!=NULL && *(sep+1)=='f' && *thumb_offset+thumb_size < nbytes)
+ FILE *out;
+#ifndef __FRAMAC__
+ *(sep+1)='t';
+#endif
+ if((out=fopen(thumbname,"wb"))!=NULL)
{
- FILE *out;
- *(sep+1)='t';
- if((out=fopen(thumbname,"wb"))!=NULL)
- {
- if(fwrite(&buffer[*thumb_offset], thumb_size, 1, out) < 1)
- {
- log_error("Can't write to %s: %s\n", thumbname, strerror(errno));
- }
- fclose(out);
- if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
- set_date(thumbname, file_recovery->time, file_recovery->time);
- }
- else
+ const char *buffer_char=(const char *)buffer;
+ /*@ assert \valid_read(buffer_char + (0 .. nbytes - 1)); */
+ /*@ assert *thumb_offset + thumb_size < nbytes; */
+ /*@ assert \valid_read(buffer_char + (0 .. *thumb_offset + thumb_size - 1)); */
+ /*@ assert \valid_read(buffer_char + *thumb_offset + (0 .. thumb_size - 1)); */
+ const char *thumb_char=&buffer_char[*thumb_offset];
+ /*@ assert \valid_read(thumb_char + (0 .. thumb_size - 1)); */
+ if(fwrite(thumb_char, thumb_size, 1, out) < 1)
{
- log_error("fopen %s failed\n", thumbname);
+ log_error("Can't write to %s: %s\n", thumbname, strerror(errno));
}
+ fclose(out);
+ if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
+ set_date(thumbname, file_recovery->time, file_recovery->time);
+ }
+ else
+ {
+ log_error("fopen %s failed\n", thumbname);
}
- free(thumbname);
}
-#endif
}
}
return 1;
@@ -1763,7 +1868,7 @@ static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsign
const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
if(buffer[i]!=0xff)
{
-#if defined(DEBUG_JPEG) && !defined(__FRAMAC__)
+#if defined(DEBUG_JPEG)
log_info("%s no marker at 0x%x\n", file_recovery->filename, i);
#endif
file_recovery->offset_error=i;
@@ -1776,7 +1881,7 @@ static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsign
offset++;
continue;
}
-#if defined(DEBUG_JPEG) && !defined(__FRAMAC__)
+#if defined(DEBUG_JPEG)
log_info("%s marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[i+1], i);
#endif
offset+=(uint64_t)2+size;
@@ -1831,6 +1936,7 @@ static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsign
@ requires \valid(file_recovery->handle);
@ requires valid_read_string((char *)&file_recovery->filename);
@ requires \initialized(&file_recovery->time);
+ @ requires file_recovery->file_check == &file_check_mpo || file_recovery->file_check == &file_check_jpg;
@*/
static void file_check_jpg(file_recovery_t *file_recovery)
{
@@ -1854,7 +1960,6 @@ static void file_check_jpg(file_recovery_t *file_recovery)
#ifdef DEBUG_JPEG
log_info("jpg_check_structure error at %llu\n", (long long unsigned)file_recovery->offset_error);
#endif
-#ifndef __FRAMAC__
#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
if(thumb_offset!=0 &&
(file_recovery->checkpoint_status==0 || thumb_error!=0) &&
@@ -1883,7 +1988,7 @@ static void file_check_jpg(file_recovery_t *file_recovery)
#endif
if(file_recovery->offset_error!=0)
return ;
-#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H) && ! defined(__FRAMAC__)
+#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
jpg_check_picture(file_recovery);
#else
file_recovery->file_size=file_recovery->calculated_file_size;
@@ -1900,34 +2005,41 @@ static void file_check_jpg(file_recovery_t *file_recovery)
return ;
}
#endif
-#endif
}
/*@
+ @ requires buffer_size >= 2 && (buffer_size&1)==0;
@ requires \valid(file_recovery);
+ @ requires file_recovery->calculated_file_size >= 2;
@ requires \valid_read(buffer + ( 0 .. buffer_size-1));
+ @ requires file_recovery->data_check == &data_check_jpg2;
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ ensures file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == \null;
+ @ ensures file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2;
+ @ ensures file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0;
+ @ assigns file_recovery->calculated_file_size;
+ @ assigns file_recovery->data_check;
+ @ assigns file_recovery->offset_error;
@*/
static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
-#if 0
- unsigned int old_marker=0;
-#endif
- if(file_recovery->calculated_file_size<2)
- {
- /* Reset to the correct file checker */
- file_recovery->data_check=&data_check_jpg;
- return data_check_jpg(buffer, buffer_size, file_recovery);
- }
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @ loop assigns file_recovery->data_check;
+ @ loop assigns file_recovery->offset_error;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 > file_recovery->file_size &&
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 file_recovery->data_check == &data_check_jpg2; */
if(buffer[i-1]==0xFF)
{
if(buffer[i]==0xd9)
{
/* JPEG_EOI */
file_recovery->calculated_file_size++;
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
return DC_STOP;
}
else if(buffer[i] >= 0xd0 && buffer[i] <= 0xd7)
@@ -1946,6 +2058,7 @@ static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned
/* TODO: store old_marker in file_recovery */
old_marker=buffer[i];
#endif
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
}
else if(buffer[i] == 0xda || buffer[i] == 0xc4)
{
@@ -1961,9 +2074,11 @@ static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned
(long long unsigned)file_recovery->calculated_file_size);
#endif
file_recovery->offset_error=file_recovery->calculated_file_size;
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
return DC_STOP;
}
}
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
file_recovery->calculated_file_size++;
}
return DC_CONTINUE;
@@ -1971,22 +2086,39 @@ static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned
/*@
@ requires buffer_size >= 8;
+ @ requires (buffer_size&1)==0;
@ requires \valid(file_recovery);
@ requires buffer_size >= 4;
@ requires \valid_read(buffer + ( 0 .. buffer_size-1));
+ @ requires file_recovery->data_check == &data_check_jpg;
@ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ ensures file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == &data_check_jpg || file_recovery->data_check == &data_check_size || file_recovery->data_check == \null;
+ @ ensures file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2;
+ @ assigns file_recovery->calculated_file_size;
+ @ assigns file_recovery->data_check;
+ @ assigns file_recovery->file_check;
+ @ assigns file_recovery->offset_error;
@*/
/* FIXME requires file_recovery->file_size == 0 || file_recovery->calculated_file_size >= file_recovery->file_size - 4; */
/* FIXME ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4); */
-data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
+static data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
/* Skip the SOI */
- if(file_recovery->calculated_file_size==0)
- file_recovery->calculated_file_size+=2;
+ if(file_recovery->calculated_file_size<2)
+ file_recovery->calculated_file_size=2;
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
/* Search SOS */
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @ loop assigns file_recovery->data_check;
+ @ loop assigns file_recovery->file_check;
+ @ loop assigns file_recovery->offset_error;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 4 < file_recovery->file_size + buffer_size/2)
{
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
/*@ assert 0 <= i < buffer_size - 4 ; */
if(buffer[i]==0xFF && buffer[i+1]==0xFF)
@@ -1994,6 +2126,7 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
else if(buffer[i]==0xFF)
{
const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
+ const uint64_t old_calculated_file_size=file_recovery->calculated_file_size;
#ifdef DEBUG_JPEG
log_info("data_check_jpg %02x%02x at %llu, next expected at %llu\n", buffer[i], buffer[i+1],
(long long unsigned)file_recovery->calculated_file_size,
@@ -2003,48 +2136,68 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
if(buffer[i+1]==0xc0) /* SOF0 */
{
if(jpg_check_sof0(buffer, buffer_size, i)!=0)
+ {
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
+ }
}
else if(buffer[i+1]==0xc4) /* DHT */
{
if(jpg_check_dht(buffer, buffer_size, i, 2+size)!=0)
+ {
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
+ }
}
else if(buffer[i+1]==0xda) /* SOS: Start Of Scan */
{
+ data_check_t tmp;
file_recovery->data_check=&data_check_jpg2;
- return data_check_jpg2(buffer, buffer_size, file_recovery);
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ tmp=data_check_jpg2(buffer, buffer_size, file_recovery);
+ /*@ assert file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == \null; */
+ /*@ assert file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2; */
+ return tmp;
}
else if(buffer[i+1]==0xe2) /* APP2 Exif information */
{
if(i+8 < buffer_size &&
buffer[i+4]=='M' && buffer[i+5]=='P' && buffer[i+6]=='F' && buffer[i+7]==0)
{
- const uint64_t offset=file_recovery->calculated_file_size-(2+size)+8;
+ const uint64_t offset=old_calculated_file_size+8;
if(i>=buffer_size/2)
{
/* Restore previous value */
- file_recovery->calculated_file_size-=2+size;
+ file_recovery->calculated_file_size=old_calculated_file_size;
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_CONTINUE;
}
/*@ assert 0 <= i < buffer_size / 2 ; */
if( i + size <= buffer_size)
{
/*@ assert i + size <= buffer_size; */
+ /*@ assert size <= buffer_size - i; */
if(size >= 16)
{
- /*@ assert 16 <= size; */
-#ifndef __FRAMAC__
- const uint64_t calculated_file_size=check_mpo(buffer+i+8, offset, size-8);
+ /*@ assert 16 <= size <= 65535; */
+ /*@ assert \valid_read(buffer + (0 .. buffer_size-1)); */
+ /*@ assert \valid_read(buffer + (0 .. i+size-1)); */
+ /*@ assert \valid_read((buffer + i ) + (0 .. size-1)); */
+ /*@ assert \valid_read((buffer + i + 8) + (0 .. size-8-1)); */
+ const unsigned char *mpo=buffer + i + 8;
+ const unsigned int size_mpo=size-8;
+ /*@ assert \valid_read(mpo + (0 .. size-8-1)); */
+ /*@ assert \valid_read(mpo + (0 .. size_mpo-1)); */
+ const uint64_t calculated_file_size=check_mpo(mpo, offset, size_mpo);
if(calculated_file_size > 0)
{
/* Multi-picture format */
file_recovery->calculated_file_size=calculated_file_size;
file_recovery->data_check=&data_check_size;
file_recovery->file_check=&file_check_mpo;
+ /*@ assert file_recovery->data_check == &data_check_size; */
return DC_CONTINUE;
}
-#endif
}
}
else
@@ -2061,6 +2214,7 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
file_recovery->calculated_file_size=calculated_file_size;
file_recovery->data_check=&data_check_size;
file_recovery->file_check=&file_check_mpo;
+ /*@ assert file_recovery->data_check == &data_check_size; */
return DC_CONTINUE;
}
}
@@ -2074,11 +2228,13 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
log_info("data_check_jpg %02x at %llu\n", buffer[i],
(long long unsigned)file_recovery->calculated_file_size);
#endif
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
}
}
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
/*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4; */
- /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4; */
+ /*X TODO assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4; */
return DC_CONTINUE;
}
@@ -2168,6 +2324,7 @@ int main()
/*@ assert file_recovery_new.data_check == &data_check_jpg; */
/*@ assert file_recovery_new.file_size == 0; */;
res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ /*@ assert file_recovery_new.data_check == &data_check_jpg2 ==> file_recovery_new.calculated_file_size >= 2; */
file_recovery_new.file_size+=BLOCKSIZE;
if(res_data_check == DC_CONTINUE)
{
@@ -2175,7 +2332,29 @@ int main()
#if defined(__FRAMAC__)
Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
#endif
- data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ /*@ assert file_recovery_new.data_check == &data_check_jpg || file_recovery_new.data_check == &data_check_jpg2 || file_recovery_new.data_check == &data_check_size || file_recovery_new.data_check == NULL; */
+ if(file_recovery_new.data_check == &data_check_jpg)
+ res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_jpg2)
+ res_data_check=data_check_jpg2(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_size)
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.data_check == &data_check_jpg || file_recovery_new.data_check == &data_check_jpg2 || file_recovery_new.data_check == &data_check_size || file_recovery_new.data_check == NULL; */
+ if(file_recovery_new.data_check == &data_check_jpg)
+ res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_jpg2)
+ res_data_check=data_check_jpg2(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_size)
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ }
}
}
/*@ assert file_recovery_new.offset_ok == 0; */
@@ -2190,7 +2369,8 @@ int main()
header_check_jpg(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
}
/*@ assert file_recovery_new.offset_ok == 0; */
- /*@ assert file_recovery_new.file_check == file_check_jpg; */
+ /*@ assert file_recovery_new.file_check == file_check_jpg || file_recovery_new.file_check == file_check_mpo; */
+ if(file_recovery_new.file_check == file_check_jpg)
{
file_recovery_new.handle=fopen(fn, "rb");
if(file_recovery_new.handle!=NULL)
@@ -2199,7 +2379,9 @@ int main()
fclose(file_recovery_new.handle);
}
}
+ else
{
+ /*@ assert file_recovery_new.file_check == file_check_mpo; */
file_recovery_new.handle=fopen(fn, "rb");
if(file_recovery_new.handle!=NULL)
{
diff --git a/src/file_list.c b/src/file_list.c
index f706680..6e3685a 100644
--- a/src/file_list.c
+++ b/src/file_list.c
@@ -288,6 +288,7 @@ extern const file_hint_t file_hint_rpm;
extern const file_hint_t file_hint_rw2;
extern const file_hint_t file_hint_rx2;
extern const file_hint_t file_hint_save;
+extern const file_hint_t file_hint_sdsk;
extern const file_hint_t file_hint_ses;
extern const file_hint_t file_hint_sgcta;
extern const file_hint_t file_hint_shn;
@@ -363,8 +364,9 @@ extern const file_hint_t file_hint_zcode;
extern const file_hint_t file_hint_zip;
extern const file_hint_t file_hint_zpr;
-file_enable_t list_file_enable[]=
+file_enable_t array_file_enable[]=
{
+#ifndef MAIN_fidentify
{ .enable=0, .file_hint=&file_hint_sig },
{ .enable=0, .file_hint=&file_hint_1cd },
{ .enable=0, .file_hint=&file_hint_3dm },
@@ -404,7 +406,9 @@ file_enable_t list_file_enable[]=
{ .enable=0, .file_hint=&file_hint_binvox },
{ .enable=0, .file_hint=&file_hint_bkf },
{ .enable=0, .file_hint=&file_hint_blend },
+#endif
{ .enable=0, .file_hint=&file_hint_bmp },
+#ifndef MAIN_fidentify
{ .enable=0, .file_hint=&file_hint_bpg },
{ .enable=0, .file_hint=&file_hint_bvr },
{ .enable=0, .file_hint=&file_hint_bz2 },
@@ -626,6 +630,7 @@ file_enable_t list_file_enable[]=
{ .enable=0, .file_hint=&file_hint_rw2 },
{ .enable=0, .file_hint=&file_hint_rx2 },
{ .enable=0, .file_hint=&file_hint_save },
+ { .enable=0, .file_hint=&file_hint_sdsk },
{ .enable=0, .file_hint=&file_hint_ses },
{ .enable=0, .file_hint=&file_hint_sgcta },
{ .enable=0, .file_hint=&file_hint_shn },
@@ -700,6 +705,7 @@ file_enable_t list_file_enable[]=
{ .enable=0, .file_hint=&file_hint_zcode },
{ .enable=0, .file_hint=&file_hint_zip },
{ .enable=0, .file_hint=&file_hint_zpr },
+#endif
{ .enable=0, .file_hint=NULL }
};
diff --git a/src/file_mov.c b/src/file_mov.c
index 6e71676..a403eb9 100644
--- a/src/file_mov.c
+++ b/src/file_mov.c
@@ -103,6 +103,7 @@ static void file_rename_mov(file_recovery_t *file_recovery)
/*@
@ requires buffer_size >= 16;
+ @ requires (buffer_size&1)==0;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid(file_recovery);
@ requires file_recovery->data_check==&data_check_mov;
@@ -136,8 +137,9 @@ static data_check_t data_check_mov(const unsigned char *buffer, const unsigned i
}
else if(atom_size<8)
return DC_STOP;
- if(atom_size >= 0x80000000)
+ if(atom_size >= 0x800000000000)
return DC_STOP;
+ /*@ assert 8 <= atom_size < 0x800000000000; */
#ifdef DEBUG_MOV
log_trace("file_mov.c: %s atom %c%c%c%c (0x%02x%02x%02x%02x) size %llu, calculated_file_size %llu\n",
file_recovery->filename,
@@ -199,10 +201,13 @@ static data_check_t data_check_mov(const unsigned char *buffer, const unsigned i
@ requires buffer_size >= 16;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
@ requires separation: \separated(file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_mov.extension ||
file_recovery_new->extension == extension_3g2 ||
file_recovery_new->extension == extension_3gp ||
@@ -211,12 +216,14 @@ static data_check_t data_check_mov(const unsigned char *buffer, const unsigned i
file_recovery_new->extension == extension_jp2 ||
file_recovery_new->extension == extension_m4p ||
file_recovery_new->extension == extension_mp4);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
@ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
@ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_mov || file_recovery_new->file_rename == \null);
@ ensures (\result == 1 && file_recovery_new->extension == file_hint_mov.extension) ==> (file_recovery_new->file_rename == file_rename_mov);
@ ensures (\result == 1 && file_recovery_new->extension != file_hint_mov.extension) ==> (file_recovery_new->file_rename == \null);
@ ensures (\result == 1 && (file_recovery_new->extension == extension_jp2 || file_recovery_new->blocksize < 16)) ==> (file_recovery_new->data_check == \null && file_recovery_new->file_check == \null && file_recovery_new->file_rename == \null && file_recovery_new->min_filesize > 0);
@ ensures (\result == 1 && file_recovery_new->extension != extension_jp2 && file_recovery_new->blocksize >= 16) ==> (file_recovery_new->calculated_file_size > 0 && file_recovery_new->file_check == &file_check_size && file_recovery_new->data_check == &data_check_mov);
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_mov_aux(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)
{
@@ -238,9 +245,9 @@ static int header_check_mov_aux(const unsigned char *buffer, const unsigned int
else if(atom_size<8)
return 0;
/*@ assert 8 <= atom_size; */
- if(atom_size >= 0x80000000)
+ if(atom_size >= 0x800000000000)
return 0;
- /*@ assert 8 <= atom_size < 0x80000000; */
+ /*@ assert 8 <= atom_size < 0x800000000000; */
calculated_file_size=atom_size+i;
/* check for commun atom type */
if(buffer[i+4]=='p' && buffer[i+5]=='n' && buffer[i+6]=='o' && buffer[i+7]=='t')
diff --git a/src/file_mp3.c b/src/file_mp3.c
index 25d688a..11431da 100644
--- a/src/file_mp3.c
+++ b/src/file_mp3.c
@@ -35,16 +35,12 @@
#include "__fc_builtin.h"
#endif
-#if !defined(MAIN_mp3) && !defined(MAIN_id3)
+#if !defined(MAIN_mp3)
extern const file_hint_t file_hint_mkv;
extern const file_hint_t file_hint_tiff;
#endif
static void register_header_check_mp3(file_stat_t *file_stat);
-static data_check_t data_check_id3(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
-static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
-static unsigned int pos_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size);
-static unsigned int search_MMT(const unsigned char *buffer, const unsigned int i, const unsigned int buffer_size);
const file_hint_t file_hint_mp3= {
.extension="mp3",
@@ -55,7 +51,6 @@ const file_hint_t file_hint_mp3= {
.register_header_check=&register_header_check_mp3
};
-
#define MPEG_V25 0
#define MPEG_V2 0x2
#define MPEG_V1 0x3
@@ -117,232 +112,167 @@ static const unsigned int bit_rate_table[4][4][16]=
},
};
-#ifndef MAIN_mp3
/*@
- @ requires buffer_size >= 10;
- @ requires \valid_read(buffer+(0..buffer_size-1));
- @ requires \valid_read(file_recovery);
- @ requires \valid(file_recovery_new);
- @ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
- @ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_mp3.extension);
- @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size > 0);
- @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
- @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 287);
- @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
- @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_id3);
+ @ requires needle_size > 0;
+ @ requires haystack_size > 0;
+ @ requires \valid_read(needle+(0..needle_size-1));
+ @ requires \valid_read(haystack+(0..haystack_size-1));
+ @ ensures \result == 0 || needle_size <= \result <= haystack_size;
+ @ assigns \nothing;
@*/
-static int header_check_id3(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)
+static unsigned int pos_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size)
{
- if(buffer[0]=='I' && buffer[1]=='D' && buffer[2]=='3' && (buffer[3]==2 || buffer[3]==3 || buffer[3]==4) && buffer[4]==0)
- {
- unsigned int potential_frame_offset=0;
- /*
- * TODO Handle ID3 tag
- * http://www.id3.org/id3v2-00
- * http://www.id3.org/id3v2.3.0
- */
- if(buffer[3]==4 && (buffer[5]&0x10)==0x10) /* a footer is present http://www.id3.org/id3v2.4.0-structure chap. 3.1 */
- potential_frame_offset = 10;
-
- potential_frame_offset+=((buffer[6]&0x7f)<<21) + ((buffer[7]&0x7f)<<14)
- + ((buffer[8]&0x7f)<<7) + (buffer[9]&0x7f)+ 10;
-
- /*
- log_info("ID3v2.%u found \n potential_frame_offset at 0x%x\n",buffer[3], potential_frame_offset);
- */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->calculated_file_size=potential_frame_offset;
- /*@ assert file_recovery_new->calculated_file_size > 0; */
- file_recovery_new->min_filesize=287;
- file_recovery_new->data_check=&data_check_id3;
- file_recovery_new->extension=file_hint_mp3.extension;
- file_recovery_new->file_check=&file_check_size;
- return 1;
- }
+ unsigned int i;
+ if(haystack_size < needle_size)
+ return 0;
+ /*@ assert haystack_size >= needle_size; */
+ /*@
+ @ loop assigns i;
+ @ loop invariant 0 <= i <= haystack_size - needle_size + 1;
+ @ loop variant haystack_size - needle_size - i;
+ @*/
+ for(i=0; i <= haystack_size - needle_size; i++)
+ if(memcmp(&haystack[i],needle,needle_size)==0)
+ return (i+needle_size);
return 0;
}
-#endif
-#ifndef MAIN_id3
/*@
- @ requires buffer_size >= 6;
+ @ requires 0 < buffer_size <= 10*1024*1024;
+ @ requires i <= buffer_size;
@ requires \valid_read(buffer+(0..buffer_size-1));
- @ requires \valid_read(file_recovery);
- @ requires \valid(file_recovery_new);
- @ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
- @ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_mp3.extension);
- @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size > 0);
- @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
- @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 287);
- @ ensures (\result == 1 && file_recovery_new->blocksize >= 16) ==> (file_recovery_new->file_check == &file_check_size);
- @ ensures (\result == 1 && file_recovery_new->blocksize >= 16) ==> (file_recovery_new->data_check == &data_check_mp3);
- @ ensures (\result == 1 && file_recovery_new->blocksize < 16) ==> (file_recovery_new->file_check == \null);
- @ ensures (\result == 1 && file_recovery_new->blocksize < 16) ==> (file_recovery_new->data_check == \null);
+ @ ensures \result <= buffer_size + 0x80;
+ @ assigns \nothing;
@*/
-static int header_check_mp3(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)
+static unsigned int search_MMT(const unsigned char *buffer, const unsigned int i, const unsigned int buffer_size)
{
- unsigned int potential_frame_offset=0;
- unsigned int nbr=0;
/*
- A Frame sync 11 (length in bits)
- B MPEG audio version (MPEG-1, 2, etc.) 2
- C MPEG layer (Layer I, II, III, etc.) 2
- D Protection (if on, then checksum follows header) 1
- AAAA AAAA AAAB BCCD
- 1111 1111 1111 1010 = FA = MPEG-1 layer 3
- 1111 1111 1111 0010 = F2 = MPEG-2 layer 3
- 1111 1111 1110 0010 = E2 = MPEG-2.5 layer 3
-
- http://www.dv.co.yu/mpgscript/mpeghdr.htm
- */
- if(!(buffer[0]==0xFF &&
- ((buffer[1]&0xFE)==0xFA ||
- (buffer[1]&0xFE)==0xF2 ||
- (buffer[1]&0xFE)==0xE2)))
+ Check for MusicMatch Tag
+ http://freenet-homepage.de/StefanRypalla/stuff/musicmatch.txt
+ min size = 8192bytes
+ header is optional
+ structure :
+ header 256 bytes optional
+ image extension 4 bytes
+ image binary >= 4 bytes
+ unused 4 bytes
+ version info 256 bytes
+ audio meta-data >= 7868 bytes
+ In all versions of the MusicMatch format up to and including 3.00,
+ this section (audio meta-data) is always 7868 bytes in length.
+ All subsequent versions allowed three possible lengths for this section: 7936, 8004, and 8132 bytes.
+ data offsets 20 bytes
+ Footer 48 bytes (optional?!)
+ */
+ const unsigned char mm_header[10]= {'1','8','2','7','3','6','4','5',0x00, 0x00};
+ const unsigned char mm_pad_version_info[14] = {0x00,0x00,0x00,0x00,'1','8','2','7','3','6','4','5',0x00,0x00};
+ const char mm_footer[]="Brava Software Inc.";
+ const char mm_footer_tag[]="TAG";
+ unsigned int size=0;
+ if(i+sizeof(mm_header)>buffer_size)
return 0;
- if(file_recovery->file_stat!=NULL)
+ /*@ assert i + sizeof(mm_header) <= buffer_size; */
+ if(memcmp(&buffer[i],mm_header,sizeof(mm_header))==0) // Optional Header
{
- if(file_recovery->file_stat->file_hint==&file_hint_mp3
-#if !defined(MAIN_mp3) && !defined(MAIN_id3)
- || file_recovery->file_stat->file_hint==&file_hint_mkv
-#endif
- )
- {
- header_ignored(file_recovery_new);
+ size=256;
+ /* Don't check image extension */
+ /* log_info("search_MMT: mm_header present\n"); */
+ }
+ else
+ {
+ /* Check image extension */
+ if( memcmp(&buffer[i]," ",4)!=0 &&
+ memcmp(&buffer[i],"bmp ",4)!=0 &&
+ memcmp(&buffer[i],"jpg ",4)!=0)
return 0;
- }
-#if !defined(MAIN_mp3) && !defined(MAIN_id3)
- /* RGV values from TIFF may be similar to the beginning of an mp3 */
- if(file_recovery->file_stat->file_hint==&file_hint_tiff &&
- buffer[0]==buffer[3] && buffer[1]==buffer[4] && buffer[2]==buffer[5])
- {
- if(header_ignored_adv(file_recovery, file_recovery_new)==0)
- return 0;
- }
-#endif
+ /* log_info("search_MMT: image extension present\n"); */
}
- /*@ assert nbr == 0; */
- /*@
- @ loop invariant 0 <= nbr <= potential_frame_offset <= 2048 + 8065;
- @*/
- while(potential_frame_offset+1 < buffer_size &&
- potential_frame_offset+1 < 2048)
{
- if(buffer[potential_frame_offset+0]!=0xFF)
+ const unsigned int tmp=i+size;
+ const uint32_t *image_size_ptr;
+ uint32_t image_size;
+ if(tmp+8>buffer_size)
return 0;
- {
- const unsigned int mpeg_version =(buffer[potential_frame_offset+1]>>3)&0x03;
- const unsigned int mpeg_layer =(buffer[potential_frame_offset+1]>>1)&0x03;
- const unsigned int bit_rate_key =(buffer[potential_frame_offset+2]>>4)&0x0F;
- const unsigned int sampling_rate_key=(buffer[potential_frame_offset+2]>>2)&0x03;
- const unsigned int padding =(buffer[potential_frame_offset+2]>>1)&0x01;
- const unsigned int bit_rate =bit_rate_table[mpeg_version][mpeg_layer][bit_rate_key];
- const unsigned int sample_rate =sample_rate_table[mpeg_version][sampling_rate_key];
- unsigned int frameLengthInBytes=0;
- if(sample_rate==0 || bit_rate==0 || mpeg_layer==MPEG_L1)
- return 0;
- /*@ assert 8 <= bit_rate <= 448; */
- /*@ assert 8000 <= sample_rate <= 48000; */
- if(mpeg_layer==MPEG_L3)
- {
- if(mpeg_version==MPEG_V1)
- frameLengthInBytes = 144000 * bit_rate / sample_rate + padding;
- else
- frameLengthInBytes = 72000 * bit_rate / sample_rate + padding;
- }
- else if(mpeg_layer==MPEG_L2)
- frameLengthInBytes = 144000 * bit_rate / sample_rate + padding;
- else
- frameLengthInBytes = (12000 * bit_rate / sample_rate + padding)*4;
-#ifdef DEBUG_MP3
- log_info("framesize: %u, layer: %u, bitrate: %u, padding: %u\n",
- frameLengthInBytes, 4-mpeg_layer, bit_rate, padding);
-#endif
- if(frameLengthInBytes==0)
- return 0;
- /*@ assert 0 < frameLengthInBytes <= 8065; */
- potential_frame_offset+=frameLengthInBytes;
- /*@ assert potential_frame_offset > 0; */
- nbr++;
- }
+ /*@ assert tmp + 8 <= buffer_size; */
+ image_size_ptr = (const uint32_t *)&buffer[tmp+4];
+ image_size = le32(*image_size_ptr);
+ /* Check if the image size */
+ if(image_size > buffer_size)
+ return 0;
+ /*@ assert image_size <= buffer_size; */
+ /* Image binary */
+ size+=8+image_size;
}
- if(nbr>1)
{
- /*@ assert nbr > 1; */
- /*@ assert potential_frame_offset > 0; */
-#ifdef DEBUG_MP3
- log_info("header_check_mp3 mp3 found\n");
-#endif
- reset_file_recovery(file_recovery_new);
- /*@ assert file_recovery_new->file_check == \null; */
- /*@ assert file_recovery_new->data_check == \null; */
- file_recovery_new->calculated_file_size=potential_frame_offset;
- /*@ assert file_recovery_new->calculated_file_size > 0; */
- file_recovery_new->min_filesize=287;
- file_recovery_new->extension=file_hint_mp3.extension;
- if(file_recovery_new->blocksize >= 16)
+ const unsigned int tmp=i+size;
+ /* check null padding + version_info */
+ if(tmp+sizeof(mm_pad_version_info)>buffer_size)
+ { /* FIXME: Is it better to have a partial MusicMatch Tag or none ? */
+ /* log_trace("search_MMT: partial MusicMatch Tag 1\n"); */
+ return 0;
+ }
+ /*@ assert tmp + sizeof(mm_pad_version_info) <= buffer_size; */
+ if(memcmp(&buffer[tmp], mm_pad_version_info, sizeof(mm_pad_version_info))!=0)
{
- file_recovery_new->data_check=&data_check_mp3;
- file_recovery_new->file_check=&file_check_size;
+ /* log_trace("search_MMT: mm_pad_version_info not present\n"); */
+ return 0;
}
- return 1;
}
- return 0;
-}
-#endif
-
-#ifndef MAIN_mp3
-/*@
- @ requires buffer_size >= 32;
- @ requires \valid_read(buffer+(0..buffer_size-1));
- @ requires \valid(file_recovery);
- @ requires file_recovery->data_check==&data_check_id3;
- @ ensures \result == DC_CONTINUE || \result == DC_STOP;
- @ ensures \result == DC_CONTINUE && file_recovery->data_check==&data_check_id3 ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1);
- @ ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 16);
- @*/
-static data_check_t data_check_id3(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
-{
- while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
- file_recovery->calculated_file_size + 1 < file_recovery->file_size + buffer_size/2)
+ size+=4+256; /* padding + version_info */
+ size+=20; /* data offset */
{
- const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
- /*@ assert 0 <= i < buffer_size - 1 ; */
- if(buffer[i]==0)
- { /* Padding is present */
- file_recovery->calculated_file_size++;
+ const unsigned int tmp=i+size;
+ /* check footer for various audio meta-data size: 7868, 7936, 8004, 8132 */
+ if(tmp+8132+sizeof(mm_footer) > buffer_size)
+ { /* FIXME: Is it better to have a partial MusicMatch Tag or none ? */
+ /* log_trace("search_MMT: partial MusicMatch 2\n"); */
+ return 0;
}
+ /*@ assert tmp + 8132 + sizeof(mm_footer) <= buffer_size; */
+ if( memcmp(&buffer[tmp+7868], mm_footer, sizeof(mm_footer)-1)==0 ||
+ memcmp(&buffer[tmp+7868], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
+ size+=7868;
+ else if(memcmp(&buffer[tmp+7936], mm_footer, sizeof(mm_footer)-1)==0 ||
+ memcmp(&buffer[tmp+7936], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
+ size+=7936;
+ else if(memcmp(&buffer[tmp+8004], mm_footer, sizeof(mm_footer)-1)==0 ||
+ memcmp(&buffer[tmp+8004], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
+ size+=8004;
+ else if(memcmp(&buffer[tmp+8132], mm_footer, sizeof(mm_footer)-1)==0 ||
+ memcmp(&buffer[tmp+8132], mm_footer_tag, sizeof(mm_footer_tag)-1)==0)
+ size+=8132;
else
- { /* no more padding or no padding */
- file_recovery->data_check=&data_check_mp3;
- file_recovery->file_check=&file_check_size;
- if(data_check_mp3(buffer, buffer_size, file_recovery)!=DC_CONTINUE)
- return DC_STOP;
- /*@ assert file_recovery->data_check==&data_check_mp3; */
- /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 16; */
- return DC_CONTINUE;
+ {
+ /* log_trace("search_MMT: no mm_footer present\n"); */
+ return 0;
}
}
- /*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1; */
- /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1; */
- return DC_CONTINUE;
+ {
+ const unsigned int tmp=i+size;
+ if(tmp + sizeof(mm_footer) > buffer_size)
+ return 0;
+ /*@ assert tmp + sizeof(mm_footer) <= buffer_size; */
+ if(memcmp(&buffer[tmp],mm_footer, sizeof(mm_footer)-1)==0)
+ size+=48; /* footer */
+ else
+ size+=0x80; /* TAG footer */
+ }
+ /* log_trace("search_MMT: MMT found size=%u (0x%x)\n", size, size); */
+ return size;
}
-#endif
/*@
@ requires buffer_size >= 32;
+ @ requires (buffer_size&1)==0;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid(file_recovery);
@ requires file_recovery->data_check==&data_check_mp3;
@ requires file_recovery->file_size == 0 || file_recovery->calculated_file_size >= file_recovery->file_size - 16;
@ ensures \result == DC_CONTINUE || \result == DC_STOP;
@ ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 16);
+ @ ensures file_recovery->data_check==&data_check_mp3;
+ @ assigns file_recovery->calculated_file_size;
@*/
- /* TODO: assigns file_recovery->calculated_file_size; */
static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
#ifdef DEBUG_MP3
@@ -350,6 +280,9 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
(long long unsigned)file_recovery->file_size,
(long long unsigned)file_recovery->calculated_file_size);
#endif
+ /*@
+ @ 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)
{
@@ -368,19 +301,15 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
const unsigned int bit_rate_key =(buffer[i+2]>>4)&0x0F;
const unsigned int sampling_rate_key=(buffer[i+2]>>2)&0x03;
const unsigned int padding =(buffer[i+2]>>1)&0x01;
- const unsigned int bit_rate =bit_rate_table[mpeg_version][mpeg_layer][bit_rate_key];
+ /*@ split mpeg_version; */
const unsigned int sample_rate =sample_rate_table[mpeg_version][sampling_rate_key];
+ /*@ assert sample_rate == 0 || 8000 <= sample_rate <= 48000; */
+ const unsigned int bit_rate =bit_rate_table[mpeg_version][mpeg_layer][bit_rate_key];
unsigned int frameLengthInBytes=0;
- /*
- log_info("frame_offset=%u\n",i);
- log_info("bit_rate=%u\n",bit_rate);
- log_info("sample_rate=%u\n",sample_rate);
- log_info("frameLengthInBytes=%u\n",frameLengthInBytes);
- */
if(sample_rate==0 || bit_rate==0 || mpeg_layer==MPEG_L1)
return DC_STOP;
- /*@ assert 8 <= bit_rate <= 448; */
/*@ assert 8000 <= sample_rate <= 48000; */
+ /*@ assert 0 < bit_rate <= 448; */
if(mpeg_layer==MPEG_L3)
{
if(mpeg_version==MPEG_V1)
@@ -394,7 +323,7 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
frameLengthInBytes = (12000 * bit_rate / sample_rate + padding)*4;
if(frameLengthInBytes<3)
return DC_STOP;
- /*@ assert 3 < frameLengthInBytes <= 8065; */
+ /*@ assert 3 <= frameLengthInBytes <= 8065; */
file_recovery->calculated_file_size+=frameLengthInBytes;
/*@ assert file_recovery->calculated_file_size > 0; */
}
@@ -416,13 +345,13 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
/*@ assert i + 5100 <= buffer_size; */
if((pos_lyrics=pos_in_mem(&buffer[i], 4096, (const unsigned char*)"LYRICS200", 9)) != 0)
{
- /*@ assert pos_lyrics > 0; */
+ /*@ assert 0 < pos_lyrics <= 4096; */
file_recovery->calculated_file_size+=pos_lyrics;
/*@ assert file_recovery->calculated_file_size > 0; */
}
else if((pos_lyrics=pos_in_mem(&buffer[i], 5100, (const unsigned char*)"LYRICSEND", 9)) != 0)
{
- /*@ assert pos_lyrics > 0; */
+ /*@ assert 0 < pos_lyrics <= 5100; */
file_recovery->calculated_file_size+=pos_lyrics;
/*@ assert file_recovery->calculated_file_size > 0; */
}
@@ -450,7 +379,7 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
const unsigned int MMT_size=search_MMT(buffer,i,buffer_size);
if(MMT_size==0)
return DC_STOP;
- /*@ assert MMT_size > 0; */
+ /*@ assert 0 < MMT_size <= buffer_size + 0x80; */
/*
log_info("MusicMatch Tag found at offset 0x%x with size 0x%x \n", file_recovery->calculated_file_size, MMT_size);
*/
@@ -464,152 +393,236 @@ static data_check_t data_check_mp3(const unsigned char *buffer, const unsigned i
}
/*@
- @ requires needle_size > 0;
- @ requires haystack_size > 0;
- @ requires \valid_read(needle+(0..needle_size-1));
- @ requires \valid_read(haystack+(0..haystack_size-1));
- @ ensures \result == 0 || needle_size <= \result <= haystack_size;
- @ assigns \nothing;
+ @ requires buffer_size >= 32;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_id3;
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ ensures \result == DC_CONTINUE && file_recovery->data_check==&data_check_id3 ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1);
+ @ ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 16);
+ @ ensures file_recovery->data_check==&data_check_id3 || file_recovery->data_check==&data_check_mp3;
@*/
-static unsigned int pos_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size)
+ /*TODO assigns file_recovery->data_check,file_recovery->calculated_file_size; */
+static data_check_t data_check_id3(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
- unsigned int i;
- if(haystack_size < needle_size)
- return 0;
- /*@ assert haystack_size >= needle_size; */
/*@
- @ loop assigns i;
- @ loop invariant 0 <= i <= haystack_size - needle_size + 1;
- @ loop variant haystack_size - needle_size - i;
+ @ loop assigns file_recovery->data_check,file_recovery->calculated_file_size;
@*/
- for(i=0; i <= haystack_size - needle_size; i++)
- if(memcmp(&haystack[i],needle,needle_size)==0)
- return (i+needle_size);
+ while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
+ file_recovery->calculated_file_size + 1 < 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 - 1 ; */
+ if(buffer[i]==0)
+ { /* Padding is present */
+ file_recovery->calculated_file_size++;
+ }
+ else
+ { /* no more padding or no padding */
+ file_recovery->data_check=&data_check_mp3;
+ file_recovery->file_check=&file_check_size;
+ /*@ assert file_recovery->data_check==&data_check_mp3; */
+ if(data_check_mp3(buffer, buffer_size, file_recovery)!=DC_CONTINUE)
+ return DC_STOP;
+ /*@ assert file_recovery->data_check==&data_check_mp3; */
+ /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 16; */
+ return DC_CONTINUE;
+ }
+ }
+ /*@ assert file_recovery->data_check==&data_check_id3; */
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1; */
+ /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 1; */
+ return DC_CONTINUE;
+}
+
+/*@
+ @ requires buffer_size >= 10;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_mp3, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_mp3.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size > 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 287);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_id3);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_id3(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)
+{
+ if(buffer[0]=='I' && buffer[1]=='D' && buffer[2]=='3' && (buffer[3]==2 || buffer[3]==3 || buffer[3]==4) && buffer[4]==0)
+ {
+ unsigned int potential_frame_offset=0;
+ /*
+ * TODO Handle ID3 tag
+ * http://www.id3.org/id3v2-00
+ * http://www.id3.org/id3v2.3.0
+ */
+ if(buffer[3]==4 && (buffer[5]&0x10)==0x10) /* a footer is present http://www.id3.org/id3v2.4.0-structure chap. 3.1 */
+ potential_frame_offset = 10;
+
+ potential_frame_offset+=((buffer[6]&0x7f)<<21) + ((buffer[7]&0x7f)<<14)
+ + ((buffer[8]&0x7f)<<7) + (buffer[9]&0x7f)+ 10;
+
+ /*
+ log_info("ID3v2.%u found \n potential_frame_offset at 0x%x\n",buffer[3], potential_frame_offset);
+ */
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->calculated_file_size=potential_frame_offset;
+ /*@ assert file_recovery_new->calculated_file_size > 0; */
+ file_recovery_new->min_filesize=287;
+ file_recovery_new->data_check=&data_check_id3;
+ file_recovery_new->extension=file_hint_mp3.extension;
+ file_recovery_new->file_check=&file_check_size;
+ return 1;
+ }
return 0;
}
/*@
- @ requires buffer_size > 0;
- @ requires i <= buffer_size;
+ @ requires buffer_size >= 6;
@ requires \valid_read(buffer+(0..buffer_size-1));
- @ assigns \nothing;
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_mp3, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_mp3.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size > 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 287);
+ @ ensures (\result == 1 && file_recovery_new->blocksize >= 16) ==> (file_recovery_new->data_check == &data_check_mp3);
+ @ ensures (\result == 1 && file_recovery_new->blocksize >= 16) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1 && file_recovery_new->blocksize < 16) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1 && file_recovery_new->blocksize < 16) ==> (file_recovery_new->file_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
-static unsigned int search_MMT(const unsigned char *buffer, const unsigned int i, const unsigned int buffer_size)
+static int header_check_mp3(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)
{
+ unsigned int potential_frame_offset=0;
+ unsigned int nbr=0;
/*
- Check for MusicMatch Tag
- http://freenet-homepage.de/StefanRypalla/stuff/musicmatch.txt
- min size = 8192bytes
- header is optional
- structure :
- header 256 bytes optional
- image extension 4 bytes
- image binary >= 4 bytes
- unused 4 bytes
- version info 256 bytes
- audio meta-data >= 7868 bytes
- In all versions of the MusicMatch format up to and including 3.00,
- this section (audio meta-data) is always 7868 bytes in length.
- All subsequent versions allowed three possible lengths for this section: 7936, 8004, and 8132 bytes.
- data offsets 20 bytes
- Footer 48 bytes (optional?!)
- */
- const unsigned char mm_header[10]= {'1','8','2','7','3','6','4','5',0x00, 0x00};
- const unsigned char mm_pad_version_info[14] = {0x00,0x00,0x00,0x00,'1','8','2','7','3','6','4','5',0x00,0x00};
- const char mm_footer[]="Brava Software Inc.";
- const char mm_footer_tag[]="TAG";
- unsigned int size=0;
- if(i+sizeof(mm_header)>buffer_size)
+ A Frame sync 11 (length in bits)
+ B MPEG audio version (MPEG-1, 2, etc.) 2
+ C MPEG layer (Layer I, II, III, etc.) 2
+ D Protection (if on, then checksum follows header) 1
+ AAAA AAAA AAAB BCCD
+ 1111 1111 1111 1010 = FA = MPEG-1 layer 3
+ 1111 1111 1111 0010 = F2 = MPEG-2 layer 3
+ 1111 1111 1110 0010 = E2 = MPEG-2.5 layer 3
+
+ http://www.dv.co.yu/mpgscript/mpeghdr.htm
+ */
+ if(!(buffer[0]==0xFF &&
+ ((buffer[1]&0xFE)==0xFA ||
+ (buffer[1]&0xFE)==0xF2 ||
+ (buffer[1]&0xFE)==0xE2)))
return 0;
- /*@ assert i + sizeof(mm_header) <= buffer_size; */
- if(memcmp(&buffer[i],mm_header,sizeof(mm_header))==0) // Optional Header
- {
- size=256;
- /* Don't check image extension */
- /* log_info("search_MMT: mm_header present\n"); */
- }
- else
- {
- /* Check image extension */
- if( memcmp(&buffer[i]," ",4)!=0 &&
- memcmp(&buffer[i],"bmp ",4)!=0 &&
- memcmp(&buffer[i],"jpg ",4)!=0)
- return 0;
- /* log_info("search_MMT: image extension present\n"); */
- }
- {
- const unsigned int tmp=i+size;
- const uint32_t *image_size_ptr;
- uint32_t image_size;
- if(tmp+8>buffer_size)
- return 0;
- /*@ assert tmp + 8 <= buffer_size; */
- image_size_ptr = (const uint32_t *)&buffer[tmp+4];
- image_size = le32(*image_size_ptr);
- /* Check if the image size */
- if(image_size > 10 * 1024 * 1024)
- return 0;
- /*@ assert image_size <= 10 * 1024 * 1024; */
- /* Image binary */
- size+=8+image_size;
- }
+ /*@ assert nbr == 0; */
+ /*@
+ @ loop invariant 0 <= nbr <= potential_frame_offset <= 2048 + 8065;
+ @ loop assigns potential_frame_offset,nbr;
+ @ loop variant 2048 - potential_frame_offset;
+ @*/
+ while(potential_frame_offset+1 < buffer_size &&
+ potential_frame_offset+1 < 2048)
{
- const unsigned int tmp=i+size;
- /* check null padding + version_info */
- if(tmp+sizeof(mm_pad_version_info)>buffer_size)
- { /* FIXME: Is it better to have a partial MusicMatch Tag or none ? */
- /* log_trace("search_MMT: partial MusicMatch Tag 1\n"); */
+ if(buffer[potential_frame_offset+0]!=0xFF)
return 0;
- }
- /*@ assert tmp + sizeof(mm_pad_version_info) <= buffer_size; */
- if(memcmp(&buffer[tmp], mm_pad_version_info, sizeof(mm_pad_version_info))!=0)
{
- /* log_trace("search_MMT: mm_pad_version_info not present\n"); */
- return 0;
+ const unsigned int mpeg_version =(buffer[potential_frame_offset+1]>>3)&0x03;
+ const unsigned int mpeg_layer =(buffer[potential_frame_offset+1]>>1)&0x03;
+ const unsigned int bit_rate_key =(buffer[potential_frame_offset+2]>>4)&0x0F;
+ const unsigned int sampling_rate_key=(buffer[potential_frame_offset+2]>>2)&0x03;
+ const unsigned int padding =(buffer[potential_frame_offset+2]>>1)&0x01;
+ /*@ split mpeg_version; */
+ const unsigned int bit_rate =bit_rate_table[mpeg_version][mpeg_layer][bit_rate_key];
+ const unsigned int sample_rate =sample_rate_table[mpeg_version][sampling_rate_key];
+ unsigned int frameLengthInBytes=0;
+ if(sample_rate==0 || bit_rate==0 || mpeg_layer==MPEG_L1)
+ return 0;
+ /*@ assert 8000 <= sample_rate <= 48000; */
+ /*@ assert 0 < bit_rate <= 448; */
+ if(mpeg_layer==MPEG_L3)
+ {
+ if(mpeg_version==MPEG_V1)
+ frameLengthInBytes = 144000 * bit_rate / sample_rate + padding;
+ else
+ frameLengthInBytes = 72000 * bit_rate / sample_rate + padding;
+ }
+ else if(mpeg_layer==MPEG_L2)
+ frameLengthInBytes = 144000 * bit_rate / sample_rate + padding;
+ else
+ frameLengthInBytes = (12000 * bit_rate / sample_rate + padding)*4;
+#ifdef DEBUG_MP3
+ log_info("framesize: %u, layer: %u, bitrate: %u, padding: %u\n",
+ frameLengthInBytes, 4-mpeg_layer, bit_rate, padding);
+#endif
+ if(frameLengthInBytes<3)
+ return 0;
+ /*@ assert 3 <= frameLengthInBytes <= 8065; */
+ potential_frame_offset+=frameLengthInBytes;
+ /*@ assert potential_frame_offset > 0; */
+ nbr++;
}
}
- size+=4+256; /* padding + version_info */
- size+=20; /* data offset */
+ if(nbr<=1)
+ return 0;
+ if(file_recovery->file_stat!=NULL)
{
- const unsigned int tmp=i+size;
- /* check footer for various audio meta-data size: 7868, 7936, 8004, 8132 */
- if(tmp+8132+sizeof(mm_footer) > buffer_size)
- { /* FIXME: Is it better to have a partial MusicMatch Tag or none ? */
- /* log_trace("search_MMT: partial MusicMatch 2\n"); */
+ if(file_recovery->file_stat->file_hint==&file_hint_mp3
+#if !defined(MAIN_mp3)
+ || file_recovery->file_stat->file_hint==&file_hint_mkv
+#endif
+ )
+ {
+ header_ignored(file_recovery_new);
return 0;
}
- /*@ assert tmp + 8132 + sizeof(mm_footer) <= buffer_size; */
- if( memcmp(&buffer[tmp+7868], mm_footer, sizeof(mm_footer)-1)==0 ||
- memcmp(&buffer[tmp+7868], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
- size+=7868;
- else if(memcmp(&buffer[tmp+7936], mm_footer, sizeof(mm_footer)-1)==0 ||
- memcmp(&buffer[tmp+7936], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
- size+=7936;
- else if(memcmp(&buffer[tmp+8004], mm_footer, sizeof(mm_footer)-1)==0 ||
- memcmp(&buffer[tmp+8004], mm_footer_tag, sizeof(mm_footer_tag) - 1)==0)
- size+=8004;
- else if(memcmp(&buffer[tmp+8132], mm_footer, sizeof(mm_footer)-1)==0 ||
- memcmp(&buffer[tmp+8132], mm_footer_tag, sizeof(mm_footer_tag)-1)==0)
- size+=8132;
- else
+#if !defined(MAIN_mp3)
+ /* RGV values from TIFF may be similar to the beginning of an mp3 */
+ if(file_recovery->file_stat->file_hint==&file_hint_tiff &&
+ buffer[0]==buffer[3] && buffer[1]==buffer[4] && buffer[2]==buffer[5])
{
- /* log_trace("search_MMT: no mm_footer present\n"); */
- return 0;
+ if(header_ignored_adv(file_recovery, file_recovery_new)==0)
+ return 0;
}
+#endif
}
+ /*@ assert nbr > 1; */
+ /*@ assert potential_frame_offset > 0; */
+#ifdef DEBUG_MP3
+ log_info("header_check_mp3 mp3 found\n");
+#endif
+ reset_file_recovery(file_recovery_new);
+ /*@ assert file_recovery_new->file_check == \null; */
+ /*@ assert file_recovery_new->data_check == \null; */
+ file_recovery_new->calculated_file_size=potential_frame_offset;
+ /*@ assert file_recovery_new->calculated_file_size > 0; */
+ file_recovery_new->min_filesize=287;
+ file_recovery_new->extension=file_hint_mp3.extension;
+ if(file_recovery_new->blocksize >= 16)
{
- const unsigned int tmp=i+size;
- if(tmp + sizeof(mm_footer) > buffer_size)
- return 0;
- /*@ assert tmp + sizeof(mm_footer) <= buffer_size; */
- /* dump_log(&buffer[tmp], 16); */
- if(memcmp(&buffer[tmp],mm_footer, sizeof(mm_footer)-1)==0)
- size+=48; /* footer */
- else
- size+=0x80; /* TAG footer */
+ file_recovery_new->data_check=&data_check_mp3;
+ file_recovery_new->file_check=&file_check_size;
}
- /* log_trace("search_MMT: MMT found size=%u (0x%x)\n", size, size); */
- return(size);
+ return 1;
}
/*@
@@ -623,22 +636,18 @@ static void register_header_check_mp3(file_stat_t *file_stat)
static const unsigned char mpeg2_L3_header2[2]= {0xFF, 0xF3};
static const unsigned char mpeg25_L3_header1[2]={0xFF, 0xE2};
static const unsigned char mpeg25_L3_header2[2]={0xFF, 0xE3};
-#ifndef MAIN_mp3
register_header_check(0, "ID3", 3, &header_check_id3, file_stat);
-#endif
-#ifndef MAIN_id3
register_header_check(0, mpeg1_L3_header1, sizeof(mpeg1_L3_header1), &header_check_mp3, file_stat);
register_header_check(0, mpeg1_L3_header2, sizeof(mpeg1_L3_header2), &header_check_mp3, file_stat);
register_header_check(0, mpeg2_L3_header1, sizeof(mpeg2_L3_header1), &header_check_mp3, file_stat);
register_header_check(0, mpeg2_L3_header2, sizeof(mpeg2_L3_header2), &header_check_mp3, file_stat);
register_header_check(0, mpeg25_L3_header1, sizeof(mpeg25_L3_header1), &header_check_mp3, file_stat);
register_header_check(0, mpeg25_L3_header2, sizeof(mpeg25_L3_header2), &header_check_mp3, file_stat);
-#endif
}
-#ifdef MAIN_id3
+#if defined(MAIN_mp3)
#define BLOCKSIZE 65536u
-int main()
+static int main_id3()
{
const char fn[] = "recup_dir.1/f0000000.mp3";
unsigned char buffer[BLOCKSIZE];
@@ -677,6 +686,7 @@ int main()
/*@ assert file_recovery_new.file_size == 0; */
/*@ assert file_recovery_new.min_filesize == 287; */
/*@ assert file_recovery_new.data_check == &data_check_id3; */
+ /*@ assert file_recovery_new.file_rename == \null; */
{
unsigned char big_buffer[2*BLOCKSIZE];
data_check_t res_data_check=DC_CONTINUE;
@@ -719,16 +729,10 @@ int main()
fclose(file_recovery_new.handle);
}
}
- if(file_recovery_new.file_rename!=NULL)
- {
- /*@ assert valid_read_string((char *)&file_recovery_new.filename); */
- (file_recovery_new.file_rename)(&file_recovery_new);
- }
return 0;
}
-#elif defined(MAIN_mp3)
-#define BLOCKSIZE 65536u
-int main()
+
+static int main_mp3()
{
const char fn[] = "recup_dir.1/f0000000.mp3";
unsigned char buffer[BLOCKSIZE];
@@ -755,7 +759,7 @@ int main()
file_stats.file_hint=&file_hint_mp3;
file_stats.not_recovered=0;
file_stats.recovered=0;
- file_hint_mp3.register_header_check(&file_stats);
+ register_header_check_mp3(&file_stats);
if(header_check_mp3(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
return 0;
/*@ assert valid_read_string((char *)&fn); */
@@ -764,6 +768,7 @@ int main()
/*@ assert file_recovery_new.min_filesize == 287; */
/*@ assert file_recovery_new.extension == file_hint_mp3.extension; */
/*@ assert file_recovery_new.calculated_file_size > 0; */
+ /*@ assert file_recovery_new.file_rename == \null; */
file_recovery_new.file_stat=&file_stats;
if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL &&
file_recovery_new.data_check!=NULL)
@@ -809,11 +814,13 @@ int main()
fclose(file_recovery_new.handle);
}
}
- if(file_recovery_new.file_rename!=NULL)
- {
- /*@ assert valid_read_string((char *)&file_recovery_new.filename); */
- (file_recovery_new.file_rename)(&file_recovery_new);
- }
+ return 0;
+}
+
+int main()
+{
+ main_mp3();
+ main_id3();
return 0;
}
#endif
diff --git a/src/file_pdf.c b/src/file_pdf.c
index c62b9bf..1311539 100644
--- a/src/file_pdf.c
+++ b/src/file_pdf.c
@@ -85,7 +85,7 @@ static void file_rename_pdf(file_recovery_t *file_recovery)
#else
offset=ftell(handle);
#endif
- if(offset < 0)
+ if(offset <= 0)
{
fclose(handle);
return;
@@ -250,11 +250,11 @@ static void file_date_pdf(file_recovery_t *file_recovery)
{
if(buffer[0]=='=' && (buffer[1]=='\'' || buffer[1]=='"'))
{
- file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS((const char *)&buffer[2]);
+ file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS(&buffer[2]);
}
else if(buffer[0]=='>')
{
- file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS((const char *)&buffer[1]);
+ file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS(&buffer[1]);
}
}
free(buffer);
diff --git a/src/file_pf.c b/src/file_pf.c
index 787a8a6..d01b99d 100644
--- a/src/file_pf.c
+++ b/src/file_pf.c
@@ -60,20 +60,28 @@ struct pf_header
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)&file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_pf;
+ @ ensures valid_read_string((char*)&file_recovery->filename);
@*/
static void file_rename_pf(file_recovery_t *file_recovery)
{
FILE *file;
struct pf_header hdr;
if((file=fopen(file_recovery->filename, "rb"))==NULL)
+ {
+ /*@ assert valid_read_string((char*)&file_recovery->filename); */
return;
+ }
if(fread(&hdr, sizeof(hdr), 1, file) <= 0)
{
fclose(file);
+ /*@ assert valid_read_string((char*)&file_recovery->filename); */
return ;
}
fclose(file);
+ /*@ assert valid_read_string((char*)&file_recovery->filename); */
file_rename_unicode(file_recovery, &hdr.name, sizeof(hdr.name), 0, "pf", 0);
+ /*@ assert valid_read_string((char*)&file_recovery->filename); */
}
/*@
@@ -82,13 +90,20 @@ static void file_rename_pf(file_recovery_t *file_recovery)
@ requires \valid_read(file_recovery);
@ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_pf, buffer+(..), file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_pf.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
@ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= sizeof(struct pf_header));
- @ ensures (\result == 1) ==> (file_recovery_new->file_rename==&file_rename_pf);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
@ ensures (\result == 1) ==> (file_recovery_new->data_check==&data_check_size);
@ ensures (\result == 1) ==> (file_recovery_new->file_check==&file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename==&file_rename_pf);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_pf(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)
{
diff --git a/src/file_sdsk.c b/src/file_sdsk.c
new file mode 100644
index 0000000..0d0ec6a
--- /dev/null
+++ b/src/file_sdsk.c
@@ -0,0 +1,66 @@
+/*
+
+ File: file_sdsk.c
+
+ Copyright (C) 2019 Christophe GRENIER <grenier@cgsecurity.org>
+
+ This software is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <stdio.h>
+#include "types.h"
+#include "filegen.h"
+
+static void register_header_check_sdsk(file_stat_t *file_stat);
+
+const file_hint_t file_hint_sdsk= {
+ .extension="sdsk",
+ .description="SafeHouse virtual disk",
+ .max_filesize=PHOTOREC_MAX_FILE_SIZE,
+ .recover=1,
+ .enable_by_default=1,
+ .register_header_check=&register_header_check_sdsk
+};
+
+static int header_check_sdsk(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)
+{
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_sdsk.extension;
+ file_recovery_new->min_filesize=0x1000;
+ return 1;
+}
+
+static void register_header_check_sdsk(file_stat_t *file_stat)
+{
+ static const unsigned char sdsk_header[0x48]= {
+ 'W' , 'A' , 'R' , 'N' , 'I' , 'N' , 'G' , 0x3a,
+ ' ' , 'T' , 'h' , 'i' , 's' , ' ' , 'f' , 'i' ,
+ 'l' , 'e' , ' ' , 'i' , 's' , ' ' , 'a' , ' ' ,
+ 'S' , 'a' , 'f' , 'e' , 'H' , 'o' , 'u' , 's' ,
+ 'e' , ' ' , 'v' , 'i' , 'r' , 't' , 'u' , 'a' ,
+ 'l' , ' ' , 'd' , 'i' , 's' , 'k' , ' ' , 'v' ,
+ 'o' , 'l' , 'u' , 'm' , 'e' , '.' , 0x0d, 0x0a,
+ 'h' , 'e' , 'a' , 'd' , 'e' , 'r' , ' ' , 'v' ,
+ 'e' , 'r' , 's' , 'i' , 'o' , 'n' , 0x3a, ' ' ,
+ };
+ register_header_check(0, sdsk_header, sizeof(sdsk_header), &header_check_sdsk, file_stat);
+}
diff --git a/src/file_sig.c b/src/file_sig.c
index e75a2e8..41207e4 100644
--- a/src/file_sig.c
+++ b/src/file_sig.c
@@ -36,6 +36,9 @@
#endif
#include <stdio.h>
#include <ctype.h>
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
#include "types.h"
#include "filegen.h"
#include "common.h"
@@ -424,12 +427,16 @@ static void register_header_check_sig(file_stat_t *file_stat)
handle=open_signature_file();
if(!handle)
return;
+#ifdef __FRAMAC__
+ buffer_size=1024*1024;
+#else
if(fstat(fileno(handle), &stat_rec)<0 || stat_rec.st_size>100*1024*1024)
{
fclose(handle);
return;
}
buffer_size=stat_rec.st_size;
+#endif
buffer=(char *)MALLOC(buffer_size+1);
if(fread(buffer,1,buffer_size,handle)!=buffer_size)
{
@@ -438,6 +445,9 @@ static void register_header_check_sig(file_stat_t *file_stat)
return;
}
fclose(handle);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown(buffer, buffer_size);
+#endif
buffer[buffer_size]='\0';
pos=buffer;
pos=parse_signature_file(file_stat, pos);
diff --git a/src/file_skp.c b/src/file_skp.c
index 1b16402..0ffc00b 100644
--- a/src/file_skp.c
+++ b/src/file_skp.c
@@ -35,7 +35,7 @@ static void register_header_check_skp(file_stat_t *file_stat);
const file_hint_t file_hint_skp= {
.extension="skp",
.description="SketchUp",
- .max_filesize=10*1024*1024,
+ .max_filesize=500*1024*1024,
.recover=1,
.enable_by_default=1,
.register_header_check=&register_header_check_skp
diff --git a/src/file_spe.c b/src/file_spe.c
index 9130cf1..0e79aab 100644
--- a/src/file_spe.c
+++ b/src/file_spe.c
@@ -31,9 +31,11 @@
#include "filegen.h"
#include "common.h"
#include "log.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
static void register_header_check_spe(file_stat_t *file_stat);
-static int header_check_spe(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 file_hint_t file_hint_spe= {
.extension="spe",
@@ -237,30 +239,171 @@ struct header_spe
int16_t lastvalue; /* 4098 Always the LAST value in the header */
} __attribute__ ((gcc_struct, __packed__));
-static const unsigned char spe_header[4]= {0x67, 0x45, 0x23, 0x01};
+/*@
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_spe, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_spe.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= 4100);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 4100);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @ assigns file_recovery_new->filename[0];
+ @ assigns file_recovery_new->time;
+ @ assigns file_recovery_new->file_stat;
+ @ assigns file_recovery_new->handle;
+ @ assigns file_recovery_new->file_size;
+ @ assigns file_recovery_new->location.list.prev;
+ @ assigns file_recovery_new->location.list.next;
+ @ assigns file_recovery_new->location.end;
+ @ assigns file_recovery_new->location.data;
+ @ assigns file_recovery_new->extension;
+ @ assigns file_recovery_new->min_filesize;
+ @ assigns file_recovery_new->calculated_file_size;
+ @ assigns file_recovery_new->data_check;
+ @ assigns file_recovery_new->file_check;
+ @ assigns file_recovery_new->file_rename;
+ @ assigns file_recovery_new->offset_error;
+ @ assigns file_recovery_new->offset_ok;
+ @ assigns file_recovery_new->checkpoint_status;
+ @ assigns file_recovery_new->checkpoint_offset;
+ @ assigns file_recovery_new->flags;
+ @ assigns file_recovery_new->extra;
+ @*/
+static int header_check_spe(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)
+{
+ uint64_t tmp;
+ const struct header_spe *spe;
+ if(buffer_size < 4100)
+ return 0;
+ /*@ assert buffer_size >= 4100; */
+ spe=(const struct header_spe*)buffer;
+ /*@ assert \valid_read(spe); */
+ if(le32(spe->WinView_id)!=0x01234567L || le16(spe->lastvalue)!=0x5555 || le32(spe->NumFrames)<0)
+ return 0;
+ tmp=(uint64_t)le16(spe->xdim)*le16(spe->ydim)*le32(spe->NumFrames);
+ if((tmp&0xc000000000000000)!=0)
+ return 0;
+ tmp*=(le16(spe->datatype)<=1?4:2);
+ if((tmp&0x8000000000000000)!=0)
+ return 0;
+ tmp+=4100;
+
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_spe.extension;
+ file_recovery_new->min_filesize=4100;
+ file_recovery_new->calculated_file_size=tmp;
+#ifndef __FRAMAC__
+ log_debug("spe xdim=%u ydim=%u NumFrames=%u datatype=%u size=%llu\n",
+ le16(spe->xdim), le16(spe->ydim), (unsigned int)le32(spe->NumFrames), le16(spe->datatype),
+ (long long unsigned) file_recovery_new->calculated_file_size);
+#endif
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ return 1;
+}
static void register_header_check_spe(file_stat_t *file_stat)
{
+ static const unsigned char spe_header[4]= {0x67, 0x45, 0x23, 0x01};
register_header_check(0xbb4, spe_header,sizeof(spe_header), &header_check_spe, file_stat);
}
-static int header_check_spe(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)
+#if defined(MAIN_spe)
+#define BLOCKSIZE 65536u
+int main()
{
- const struct header_spe *spe=(const struct header_spe*)buffer;
- if(le32(spe->WinView_id)==0x01234567L && le16(spe->lastvalue)==0x5555)
+ const char fn[] = "recup_dir.1/f0000000.spe";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_spe;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+ register_header_check_spe(&file_stats);
+ if(header_check_spe(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == file_hint_spe.extension; */
+ /*@ assert file_recovery_new.calculated_file_size >= 4100; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.min_filesize == 4100; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.data_check == &data_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint!=NULL; */
{
- reset_file_recovery(file_recovery_new);
- file_recovery_new->extension=file_hint_spe.extension;
- file_recovery_new->min_filesize=4100;
- file_recovery_new->calculated_file_size=(uint64_t)le16(spe->xdim)*le16(spe->ydim)*le32(spe->NumFrames);
- file_recovery_new->calculated_file_size*=(le16(spe->datatype)<=1?4:2);
- file_recovery_new->calculated_file_size+=4100;
- log_debug("spe xdim=%u ydim=%u NumFrames=%u datatype=%u size=%llu\n",
- le16(spe->xdim), le16(spe->ydim), (unsigned int)le32(spe->NumFrames), le16(spe->datatype),
- (long long unsigned) file_recovery_new->calculated_file_size);
- file_recovery_new->data_check=&data_check_size;
- file_recovery_new->file_check=&file_check_size;
- return 1;
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_size; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_spe(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
}
return 0;
}
+#endif
diff --git a/src/file_steuer2014.c b/src/file_steuer2014.c
index e293825..eba0702 100644
--- a/src/file_steuer2014.c
+++ b/src/file_steuer2014.c
@@ -33,10 +33,17 @@
#include "common.h"
static void register_header_check_steuer(file_stat_t *file_stat);
+static const char *extension_steuer2014="steuer2014";
+static const char *extension_steuer2015="steuer2015";
+static const char *extension_steuer2016="steuer2016";
+static const char *extension_steuer2017="steuer2017";
+static const char *extension_steuer2018="steuer2018";
+static const char *extension_steuer2019="steuer2019";
+static const char *extension_steuer2020="steuer2020";
const file_hint_t file_hint_steuer2014= {
.extension="steuer2014",
- .description="Steuer 2014/2015",
+ .description="Steuer 2014/...",
.max_filesize=100*1024*1024,
.recover=1,
.enable_by_default=1,
@@ -59,10 +66,30 @@ static int header_check_steuer(const unsigned char *buffer, const unsigned int b
return 0;
memset(&tm_time, 0, sizeof(struct tm));
reset_file_recovery(file_recovery_new);
- if(le32(h->version1)>=0x13)
- file_recovery_new->extension="steuer2015";
- else
- file_recovery_new->extension=file_hint_steuer2014.extension;
+ switch(le32(h->version1))
+ {
+ case 0x00 ... 0x12:
+ file_recovery_new->extension=extension_steuer2014;
+ break;
+ case 0x13:
+ file_recovery_new->extension=extension_steuer2015;
+ break;
+ case 0x14:
+ file_recovery_new->extension=extension_steuer2016;
+ break;
+ case 0x15:
+ file_recovery_new->extension=extension_steuer2017;
+ break;
+ case 0x16:
+ file_recovery_new->extension=extension_steuer2018;
+ break;
+ case 0x17:
+ file_recovery_new->extension=extension_steuer2019;
+ break;
+ default:
+ file_recovery_new->extension=extension_steuer2020;
+ break;
+ }
#ifdef HAVE_STRPTIME
strptime(h->date_string, "%b %d %Y %H:%M:%S", &tm_time);
file_recovery_new->time=mktime(&tm_time);
diff --git a/src/file_swf.c b/src/file_swf.c
index 20a1df1..17d743a 100644
--- a/src/file_swf.c
+++ b/src/file_swf.c
@@ -19,10 +19,15 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_ZLIB_H
+#undef HAVE_LIBZ
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -33,7 +38,11 @@
#endif
#include "filegen.h"
#include "common.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
+static const char *extension_swc="swc";
static void register_header_check_swf(file_stat_t *file_stat);
const file_hint_t file_hint_swf= {
@@ -66,18 +75,36 @@ struct swfz_header
// compressedLen does not include header (4+4+4 bytes) or lzma props (5 bytes)
// compressedLen does include LZMA end marker (6 bytes)
+/*@
+ @ requires \valid(data);
+ @ requires \valid_read(*data + (0..3));
+ @ requires \valid(offset_bit);
+ @ requires 0 <= *offset_bit <= 7;
+ @ requires 2 <= nbit <= 31;
+ @ requires separation: \separated(data, offset_bit, *data + (0..(nbit+*offset_bit)/8));
+ @ ensures 0 <= *offset_bit <= 7;
+ @ assigns *data, *offset_bit;
+ @*/
static int read_SB(const unsigned char **data, unsigned int *offset_bit, unsigned int nbit)
{
int res=0;
const unsigned int sign=((**data) >>(7 - (*offset_bit)))&1;
+ /*@
+ loop unroll 31;
+ loop assigns nbit, *offset_bit, *data, res;
+ loop variant nbit;
+ */
while(nbit>1)
{
+ /*@ assert 0 <= *offset_bit <= 7; */
(*offset_bit)++;
+ /*@ assert 1 <= *offset_bit <= 8; */
if(*offset_bit==8)
{
(*data)++;
*offset_bit=0;
}
+ /*@ assert 0 <= *offset_bit <= 7; */
res=(res<<1)|((**data>>(7 - *offset_bit))&1);
nbit--;
}
@@ -86,6 +113,24 @@ static int read_SB(const unsigned char **data, unsigned int *offset_bit, unsigne
return res;
}
+/*@
+ @ requires buffer_size >= 512;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_swf, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size_max);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_swc);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
static int header_check_swfc(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 struct swf_header *hdr=(const struct swf_header *)buffer;
@@ -138,8 +183,10 @@ static int header_check_swfc(const unsigned char *buffer, const unsigned int buf
if(d_stream.total_out < 16)
return 0;
nbit=(*data)>>3;
+ /* assert nbit <= 31; */
if(nbit<=1)
return 0;
+ /* assert 2 <= nbit <= 31; */
Xmin=read_SB(&data, &offset_bit, nbit);
Xmax=read_SB(&data, &offset_bit, nbit);
Ymin=read_SB(&data, &offset_bit, nbit);
@@ -149,13 +196,31 @@ static int header_check_swfc(const unsigned char *buffer, const unsigned int buf
}
#endif
reset_file_recovery(file_recovery_new);
- file_recovery_new->extension="swc";
+ file_recovery_new->extension=extension_swc;
file_recovery_new->calculated_file_size=le32(hdr->size);
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size_max;
return 1;
}
+/*@
+ @ requires buffer_size >= sizeof(struct swf_header);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_swf, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_swf.extension);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
static int header_check_swf(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)
{
/* http://www.adobe.com/go/swfspec */
@@ -189,22 +254,136 @@ static int header_check_swf(const unsigned char *buffer, const unsigned int buff
return 1;
}
+/*@
+ @ requires buffer_size >= sizeof(struct swfz_header);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_swf, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size_max);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_swf.extension);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
static int header_check_swfz(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 struct swfz_header *hdr=(const struct swfz_header *)buffer;
- if(hdr->version < 11 || le32(hdr->compressedLen) < 6)
+ const unsigned int compressedLen=le32(hdr->compressedLen);
+ /* ZWS file compression is permitted in SWF 13 or later only. */
+ if(hdr->version < 13 || hdr->version > 50 || compressedLen < 6)
return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_swf.extension;
- file_recovery_new->calculated_file_size=(uint64_t)4+4+4+5+le32(hdr->compressedLen);
+ file_recovery_new->calculated_file_size=(uint64_t)4+4+4+5+compressedLen;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size_max;
return 1;
}
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_swf(file_stat_t *file_stat)
{
register_header_check(0, "CWS", 3, &header_check_swfc, file_stat);
register_header_check(0, "FWS", 3, &header_check_swf, file_stat);
register_header_check(0, "ZWS", 3, &header_check_swfz, file_stat);
}
+
+#if defined(MAIN_swf)
+#define BLOCKSIZE 65536u
+int main(void)
+{
+ const char fn[] = "recup_dir.1/f0000000.swf";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_swf;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+ register_header_check_swf(&file_stats);
+ if(header_check_swf(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1 ||
+ header_check_swfc(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1 ||
+ header_check_swfz(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == file_hint_swf.extension || file_recovery_new.extension == extension_swc; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_size || file_recovery_new.file_check == &file_check_size_max; */
+ /*@ assert file_recovery_new.data_check == &data_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint!=NULL; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_size; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_swf(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size || file_recovery_new.file_check == &file_check_size_max; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ if(file_recovery_new.file_check == &file_check_size)
+ file_check_size(&file_recovery_new);
+ else
+ file_check_size_max(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+#endif
diff --git a/src/file_tar.c b/src/file_tar.c
index 424b314..c777a6e 100644
--- a/src/file_tar.c
+++ b/src/file_tar.c
@@ -64,6 +64,15 @@ struct posix_header
/* 500 */
};
+/*@
+ @ requires buffer_size >= 512;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_tar, buffer+(..), file_recovery, file_recovery_new);
+ @*/
int header_check_tar(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 struct posix_header *h=(const struct posix_header *)buffer;
@@ -80,6 +89,9 @@ int header_check_tar(const unsigned char *buffer, const unsigned int buffer_size
return 1;
}
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_tar(file_stat_t *file_stat)
{
static const unsigned char tar_header_gnu[6] = { 'u','s','t','a','r',0x00};
diff --git a/src/file_tiff.c b/src/file_tiff.c
index 96626ce..b30064f 100644
--- a/src/file_tiff.c
+++ b/src/file_tiff.c
@@ -47,7 +47,7 @@ static void register_header_check_tiff(file_stat_t *file_stat);
const file_hint_t file_hint_tiff= {
.extension="tif",
.description="Tag Image File Format and some raw file formats (pef/nef/dcr/sr2/cr2)",
- .max_filesize=100*1024*1024,
+ .max_filesize=1024*1024*1024,
.recover=1,
.enable_by_default=1,
.register_header_check=&register_header_check_tiff
diff --git a/src/file_tiff.h b/src/file_tiff.h
index 0fb5f6c..fa9af03 100644
--- a/src/file_tiff.h
+++ b/src/file_tiff.h
@@ -77,7 +77,7 @@ time_t get_date_from_tiff_header(const unsigned char*buffer, const unsigned int
/*@
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \separated(potential_error, buffer);
- @ ensures \valid_read(buffer+(0..buffer_size-1));
+ @ assigns *potential_error;
@*/
unsigned int find_tag_from_tiff_header(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int tag, const unsigned char **potential_error);
@@ -88,7 +88,7 @@ unsigned int find_tag_from_tiff_header(const unsigned char *buffer, const unsign
@ requires \valid_read(buffer+(0..tiff_size-1));
@ requires \valid(potential_error);
@ requires \separated(potential_error, buffer);
- @ ensures \valid_read(buffer+(0..tiff_size-1));
+ @ assigns *potential_error;
@*/
unsigned int find_tag_from_tiff_header_le(const unsigned char *buffer, const unsigned int tiff_size, const unsigned int tag, const unsigned char**potential_error);
#endif
@@ -99,6 +99,7 @@ unsigned int find_tag_from_tiff_header_le(const unsigned char *buffer, const uns
@ requires \valid(fr->handle);
@ requires \valid_read(&fr->extension);
@ requires valid_read_string(fr->extension);
+ @ requires fr->file_check==&file_check_tiff_le;
@ ensures \valid(fr->handle);
@ ensures valid_read_string(fr->extension);
@*/
@@ -108,12 +109,21 @@ void file_check_tiff_le(file_recovery_t *fr);
@ requires buffer_size >= 15;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures \result == 1 ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
@ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_tiff_le);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension != \null);
@ ensures (\result == 1) ==> valid_read_string(file_recovery_new->extension);
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
int header_check_tiff_le(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);
#endif
@@ -125,7 +135,7 @@ int header_check_tiff_le(const unsigned char *buffer, const unsigned int buffer_
@ requires \valid_read(buffer+(0..tiff_size-1));
@ requires \valid(potential_error);
@ requires \separated(potential_error, buffer);
- @ ensures \valid_read(buffer+(0..tiff_size-1));
+ @ assigns *potential_error;
@*/
unsigned int find_tag_from_tiff_header_be(const unsigned char*buffer, const unsigned int tiff_size, const unsigned int tag, const unsigned char**potential_error);
#endif
@@ -135,11 +145,20 @@ unsigned int find_tag_from_tiff_header_be(const unsigned char*buffer, const unsi
@ requires buffer_size >= 15;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures \result == 1 ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension != \null);
@ ensures (\result == 1) ==> valid_read_string(file_recovery_new->extension);
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
int header_check_tiff_be(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);
#endif
diff --git a/src/file_tiff_be.c b/src/file_tiff_be.c
index 92ac870..74bc61e 100644
--- a/src/file_tiff_be.c
+++ b/src/file_tiff_be.c
@@ -54,8 +54,31 @@ static const char *extension_pef="pef";
#ifndef MAIN_tiff_le
/*@
@ requires \valid_read(buffer+(0..tiff_size-1));
+ @ ensures \result <= 0xffff;
+ @ assigns \nothing;
+ @ */
+static unsigned int get_nbr_fields_be(const unsigned char *buffer, const unsigned int tiff_size, const unsigned int offset_hdr)
+{
+ const unsigned char *ptr_hdr;
+ const struct ifd_header *hdr;
+ if(sizeof(struct ifd_header) > tiff_size)
+ return 0;
+ /*@ assert tiff_size >= sizeof(struct ifd_header); */
+ if(offset_hdr > tiff_size - sizeof(struct ifd_header))
+ return 0;
+ /*@ assert offset_hdr + sizeof(struct ifd_header) <= tiff_size; */
+ ptr_hdr=&buffer[offset_hdr];
+ /*@ assert \valid_read(ptr_hdr + (0 .. sizeof(struct ifd_header)-1)); */
+ hdr=(const struct ifd_header *)ptr_hdr;
+ /*@ assert \valid_read(hdr); */
+ return be16(hdr->nbr_fields);
+}
+
+/*@
+ @ requires \valid_read(buffer+(0..tiff_size-1));
@ requires \valid(potential_error);
@ requires \separated(potential_error, buffer+(..));
+ @ assigns *potential_error;
@
*/
static unsigned int find_tag_from_tiff_header_be_aux(const unsigned char *buffer, const unsigned int tiff_size, const unsigned int tag, const unsigned char**potential_error, const unsigned int offset_hdr)
@@ -143,6 +166,27 @@ unsigned int find_tag_from_tiff_header_be(const unsigned char *buffer, const uns
if(tmp)
return tmp;
}
+ {
+ const unsigned int nbr_fields=get_nbr_fields_be(buffer, tiff_size, offset_ifd0);
+ unsigned int offset_tiff_next_diroff;
+ offset_tiff_next_diroff=offset_ifd0 + 2 + nbr_fields * sizeof(TIFFDirEntry);
+ /*@ assert tiff_size >= 4; */
+ if(offset_tiff_next_diroff < tiff_size - 4)
+ {
+ const unsigned char *ptr_hdr;
+ const uint32_t *tiff_next_diroff;
+ unsigned int offset_ifd1;
+ /*@ assert offset_tiff_next_diroff + 4 <= tiff_size; */
+ ptr_hdr=&buffer[offset_tiff_next_diroff];
+ /*@ assert \valid_read(ptr_hdr + (0 .. 4-1)); */
+ tiff_next_diroff=(const uint32_t *)ptr_hdr;
+ /*@ assert \valid_read(tiff_next_diroff); */
+ /* IFD1 */
+ offset_ifd1=be32(*tiff_next_diroff);
+ if(offset_ifd1 > 0)
+ return find_tag_from_tiff_header_be_aux(buffer, tiff_size, tag, potential_error, offset_ifd1);
+ }
+ }
/*@ assert \valid_read(buffer+(0..tiff_size-1)); */
return 0;
}
@@ -659,6 +703,7 @@ static uint64_t file_check_tiff_be_aux(file_recovery_t *fr, const uint32_t tiff_
@ requires \valid(fr->handle);
@ requires \valid_read(&fr->extension);
@ requires valid_read_string(fr->extension);
+ @ requires fr->file_check==&file_check_tiff_be;
@*/
static void file_check_tiff_be(file_recovery_t *fr)
{
diff --git a/src/file_tiff_le.c b/src/file_tiff_le.c
index 590e7bf..196e4c3 100644
--- a/src/file_tiff_le.c
+++ b/src/file_tiff_le.c
@@ -58,8 +58,31 @@ static const char *extension_sr2="sr2";
#ifndef MAIN_tiff_be
/*@
@ requires \valid_read(buffer+(0..tiff_size-1));
+ @ ensures \result <= 0xffff;
+ @ assigns \nothing;
+ @ */
+static unsigned int get_nbr_fields_le(const unsigned char *buffer, const unsigned int tiff_size, const unsigned int offset_hdr)
+{
+ const unsigned char *ptr_hdr;
+ const struct ifd_header *hdr;
+ if(sizeof(struct ifd_header) > tiff_size)
+ return 0;
+ /*@ assert tiff_size >= sizeof(struct ifd_header); */
+ if(offset_hdr > tiff_size - sizeof(struct ifd_header))
+ return 0;
+ /*@ assert offset_hdr + sizeof(struct ifd_header) <= tiff_size; */
+ ptr_hdr=&buffer[offset_hdr];
+ /*@ assert \valid_read(ptr_hdr + (0 .. sizeof(struct ifd_header)-1)); */
+ hdr=(const struct ifd_header *)ptr_hdr;
+ /*@ assert \valid_read(hdr); */
+ return le16(hdr->nbr_fields);
+}
+
+/*@
+ @ requires \valid_read(buffer+(0..tiff_size-1));
@ requires \valid(potential_error);
@ requires \separated(potential_error, buffer+(..));
+ @ assigns *potential_error;
@
*/
static unsigned int find_tag_from_tiff_header_le_aux(const unsigned char *buffer, const unsigned int tiff_size, const unsigned int tag, const unsigned char**potential_error, const unsigned int offset_hdr)
@@ -146,6 +169,26 @@ unsigned int find_tag_from_tiff_header_le(const unsigned char *buffer, const uns
if(tmp)
return tmp;
}
+ {
+ const unsigned int nbr_fields=get_nbr_fields_le(buffer, tiff_size, offset_ifd0);
+ unsigned int offset_tiff_next_diroff;
+ offset_tiff_next_diroff=offset_ifd0 + 2 + nbr_fields * sizeof(TIFFDirEntry);
+ if(offset_tiff_next_diroff < tiff_size - 4)
+ {
+ const unsigned char *ptr_hdr;
+ const uint32_t *tiff_next_diroff;
+ unsigned int offset_ifd1;
+ /*@ assert offset_tiff_next_diroff + 4 <= tiff_size; */
+ ptr_hdr=&buffer[offset_tiff_next_diroff];
+ /*@ assert \valid_read(ptr_hdr + (0 .. 4-1)); */
+ tiff_next_diroff=(const uint32_t *)ptr_hdr;
+ /*@ assert \valid_read(tiff_next_diroff); */
+ /* IFD1 */
+ offset_ifd1=le32(*tiff_next_diroff);
+ if(offset_ifd1 > 0)
+ return find_tag_from_tiff_header_le_aux(buffer, tiff_size, tag, potential_error, offset_ifd1);
+ }
+ }
/*@ assert \valid_read(buffer+(0..tiff_size-1)); */
return 0;
}
diff --git a/src/file_txt.c b/src/file_txt.c
index 19ea286..83efab3 100644
--- a/src/file_txt.c
+++ b/src/file_txt.c
@@ -41,41 +41,109 @@
#include "log.h"
#include "memmem.h"
#include "file_txt.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
+#if !defined(MAIN_txt)
extern const file_hint_t file_hint_doc;
extern const file_hint_t file_hint_jpg;
extern const file_hint_t file_hint_pdf;
extern const file_hint_t file_hint_sld;
extern const file_hint_t file_hint_tiff;
extern const file_hint_t file_hint_zip;
+#endif
-static inline int filtre(unsigned int car);
+typedef struct
+{
+ const char *string;
+ const unsigned int len;
+ const char *extension;
+} txt_header_t;
-static void register_header_check_txt(file_stat_t *file_stat);
-static int header_check_txt(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);
static void register_header_check_fasttxt(file_stat_t *file_stat);
static void register_header_check_snz(file_stat_t *file_stat);
-static int header_check_fasttxt(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);
+static void register_header_check_txt(file_stat_t *file_stat);
+
+static const char *extension_asp="asp";
+static const char *extension_bat="bat";
+static const char *extension_c="c";
+static const char *extension_csv="csv";
+static const char *extension_dc="dc";
+static const char *extension_emlx="emlx";
+static const char *extension_ers="ers";
+static const char *extension_f="f";
+static const char *extension_fb2="fb2";
+static const char *extension_fods="fods";
+static const char *extension_fst="fst";
+static const char *extension_gcs="gcs";
+static const char *extension_ghx="ghx";
+static const char *extension_go="go";
+static const char *extension_gpx="gpx";
+static const char *extension_groovy="groovy";
+static const char *extension_gsb="gsb";
+static const char *extension_h="h";
+#ifdef DJGPP
+static const char *extension_html="htm";
+#else
+static const char *extension_html="html";
+#endif
+static const char *extension_ics="ics";
+static const char *extension_inf="inf";
+static const char *extension_ini="ini";
+#ifdef DJGPP
+static const char *extension_java="jav";
+#else
+static const char *extension_java="java";
+#endif
+static const char *extension_json="json";
+static const char *extension_jsp="jsp";
+static const char *extension_ldif="ldif";
+static const char *extension_ly="ly";
+static const char *extension_mbox="mbox";
+static const char *extension_php="php";
+static const char *extension_pl="pl";
+#ifdef DJGPP
+static const char *extension_plist="pli";
+#else
+static const char *extension_plist="plist";
+#endif
+static const char *extension_pm="pm";
+static const char *extension_prproj="prproj";
+static const char *extension_py="py";
+static const char *extension_rb="rb";
+static const char *extension_rtf="rtf";
+static const char *extension_sla="sla";
+static const char *extension_smil="smil";
+static const char *extension_stl="stl";
+static const char *extension_svg="svg";
+static const char *extension_ttd="ttd";
+static const char *extension_tex="tex";
#ifdef UTF16
-static int header_check_le16_txt(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);
+static const char *extension_utf16="utf16";
#endif
+static const char *extension_vb="vb";
+static const char *extension_vbm="vbm";
+static const char *extension_vcf="vcf";
+static const char *extension_xml="xml";
+static const char *extension_xmp="xmp";
-const file_hint_t file_hint_snz= {
- .extension="snz",
- .description="Olfaction SeeNez odorama",
+const file_hint_t file_hint_fasttxt= {
+ .extension="tx?",
+ .description="Text files with header: rtf,xml,xhtml,mbox/imm,pm,ram,reg,sh,slk,stp,jad,url",
.max_filesize=PHOTOREC_MAX_FILE_SIZE,
.recover=1,
.enable_by_default=1,
- .register_header_check=&register_header_check_snz
+ .register_header_check=&register_header_check_fasttxt
};
-const file_hint_t file_hint_fasttxt= {
- .extension="tx?",
- .description="Text files with header: rtf,xml,xhtml,mbox/imm,pm,ram,reg,sh,slk,stp,jad,url",
+const file_hint_t file_hint_snz= {
+ .extension="snz",
+ .description="Olfaction SeeNez odorama",
.max_filesize=PHOTOREC_MAX_FILE_SIZE,
.recover=1,
.enable_by_default=1,
- .register_header_check=&register_header_check_fasttxt
+ .register_header_check=&register_header_check_snz
};
const file_hint_t file_hint_txt= {
@@ -89,28 +157,6 @@ const file_hint_t file_hint_txt= {
static unsigned char ascii_char[256];
-static void register_header_check_txt(file_stat_t *file_stat)
-{
- unsigned int i;
- for(i=0; i<256; i++)
- ascii_char[i]=i;
- for(i=0; i<256; i++)
- {
- if(filtre(i) || i==0xE2 || i==0xC2 || i==0xC3 || i==0xC5 || i==0xC6 || i==0xCB)
- register_header_check(0, &ascii_char[i], 1, &header_check_txt, file_stat);
- }
-#ifdef UTF16
- register_header_check(1, &ascii_char[0], 1, &header_check_le16_txt, file_stat);
-#endif
-}
-
-typedef struct
-{
- const char *string;
- const unsigned int len;
- const char *extension;
-} txt_header_t;
-
static const txt_header_t fasttxt_headers[] = {
/* Unix shell */
{ "#!/bin/bash", 11, "sh"},
@@ -172,6 +218,7 @@ static const txt_header_t fasttxt_headers[] = {
{ "-- phpMyAdmin SQL Dump", 22, "sql"},
{ "--\n-- PostgreSQL database cluster dump", 38, "sql"},
{ "--\r\n-- PostgreSQL database cluster dump", 39, "sql"},
+ { "# ************************************************************\n# Sequel Pro SQL dump", 84, "sql"},
{ "---- BEGIN SSH2 PUBLIC KEY ----", 31, "ppk"},
{ "PuTTY-User-Key-File-2:", 22, "ppk"},
{ "-----BEGIN PGP PRIVATE KEY BLOCK-----", 37, "priv"},
@@ -227,6 +274,9 @@ static const txt_header_t fasttxt_headers[] = {
// #define DEBUG_FILETXT
/* return 1 if char can be found in text file */
+/*@
+ @ assigns \nothing;
+ @*/
static int filtre(unsigned int car)
{
switch(car)
@@ -287,16 +337,192 @@ static int filtre(unsigned int car)
return 0;
}
+/*@
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ assigns \nothing;
+ @*/
+static int has_newline(const char *buffer, const unsigned int buffer_size)
+{
+ unsigned int i;
+ /*@
+ @ loop invariant 0 <= i <= 512;
+ @ loop assigns i;
+ @ loop variant 512-i;
+ @*/
+ for(i=0; i<512 && i < buffer_size && buffer[i]!='\0'; i++)
+ {
+ if(buffer[i]=='\n')
+ return 1;
+ }
+ /* A text file must contains several lines */
+ return 0;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ assigns \nothing;
+ @*/
+static unsigned int is_csv(const char *buffer, const unsigned int buffer_size)
+{
+ unsigned int csv_per_line_current=0;
+ unsigned int csv_per_line=0;
+ unsigned int line_nbr=0;
+ unsigned int i;
+ /*@
+ @ loop invariant 0 <= i <= buffer_size;
+ @ loop invariant csv_per_line_current <= i+1;
+ @ loop invariant line_nbr <= i+1;
+ @ loop assigns i, csv_per_line_current, csv_per_line, line_nbr;
+ @ loop variant buffer_size-i;
+ @*/
+ for(i=0; i<buffer_size; i++)
+ {
+ if(buffer[i]==';')
+ {
+ csv_per_line_current++;
+ }
+ else if(buffer[i]=='\n')
+ {
+ if(line_nbr==0)
+ {
+ if(csv_per_line_current==0)
+ return 0;
+ csv_per_line=csv_per_line_current;
+ }
+ if(csv_per_line_current!=csv_per_line)
+ return 0;
+ line_nbr++;
+ csv_per_line_current=0;
+ }
+ }
+ if(line_nbr<10)
+ return 0;
+ return 1;
+}
+
+/*@
+ @ requires valid_read_string(buffer);
+ @ assigns \nothing;
+ @*/
+static unsigned int is_fortran(const char *buffer)
+{
+ const char *str=buffer;
+ unsigned int i=0;
+ /* Detect Fortran */
+ /*@ assert valid_read_string(str); */
+ /*@
+ @ loop invariant 0 <= i <= 10;
+ @ loop assigns str,i;
+ @ loop variant 10 - i;
+ @*/
+ for(i=0; i<10; i++)
+ {
+ str=strstr(str, "\n ");
+ if(str==NULL)
+ return 0;
+ /*@ assert valid_read_string(str); */
+#ifdef __FRAMAC__
+ if(*str=='\0')
+ return 0;
+#endif
+ str++;
+ /*@ assert valid_read_string(str); */
+ }
+ if(i < 10)
+ return 0;
+ if(strstr(buffer, "integer")==NULL)
+ return 0;
+ return 1;
+}
+
+/*@
+ @ requires valid_read_string((char *)buffer);
+ @ assigns \nothing;
+ @*/
+static int is_ini(const unsigned char *buffer)
+{
+ const unsigned char *src=buffer;
+ if(*src!='[')
+ return 0;
+ src++;
+ /*@
+ @ loop assigns src;
+ @*/
+ while(*src!='\0')
+ {
+ if(*src==']')
+ {
+ if(src > buffer + 3)
+ return 1;
+ return 0;
+ }
+ if(!isalnum(*src) && *src!=' ')
+ return 0;
+ src++;
+ }
+ return 0;
+}
+
+/*@
+ @ requires buffer_size >= 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @*/
+static double is_random(const unsigned char *buffer, const unsigned int buffer_size)
+{
+ unsigned int stats[256];
+ unsigned int i;
+ double ind;
+ if(buffer_size < 2)
+ return 1;
+ memset(&stats, 0, sizeof(stats));
+ /*@ assert \forall int j; (0 <= j <= 255) ==> (stats[j] == 0); */
+#ifndef __FRAMAC__
+ /*@
+ @ loop invariant 0 <= i <= buffer_size;
+ @ loop invariant \forall integer j; (0 <= j <= 255) ==> (stats[j] <= i+1);
+ @ loop assigns i, stats[0..255];
+ @ loop variant buffer_size-i;
+ @*/
+ for(i=0; i<buffer_size; i++)
+ stats[buffer[i]]++;
+ ind=0;
+ /*@
+ @ loop invariant 0 <= i <= 256;
+ @ loop assigns ind;
+ @ loop variant 256-i;
+ @*/
+ for(i=0; i<256; i++)
+ if(stats[i]>0)
+ ind+=stats[i]*(stats[i]-1);
+#else
+ ind=Frama_C_interval(0, buffer_size*(buffer_size-1));
+#endif
+return ind/buffer_size/(buffer_size-1);
+}
+
/* destination should have an extra byte available for null terminator
- return read size */
-int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int buf_len)
+ return written size */
+/*@
+ @ requires buf_len > 0;
+ @ requires \valid(buffer_lower + (0..buf_len-1));
+ @ requires \valid_read(buffer + (0..buf_len-1));
+ @ ensures \result <= buf_len;
+ @*/
+static int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int buf_len)
{
const unsigned char *p; /* pointers to actual position in source buffer */
unsigned char *q; /* pointers to actual position in destination buffer */
- int i; /* counter of remaining bytes available in destination buffer */
- for (i = buf_len, p = buffer, q = buffer_lower; p-buffer<buf_len && i > 0 && *p!='\0';)
+ unsigned int offset_dst;
+ /* destination will be null terminated */
+ /*@
+ @ loop invariant offset_dst < buf_len;
+ @ loop invariant q == buffer_lower + offset_dst;
+ @ loop variant buf_len - 1 - offset_dst;
+ @*/
+ for (offset_dst = 0, p = buffer, q = buffer_lower;
+ p+2-buffer<buf_len && offset_dst < buf_len-1 && *p!='\0';)
{
- const unsigned char *p_org=p;
if((*p & 0xf0)==0xe0 && (*(p+1) & 0xc0)==0x80 && (*(p+2) & 0xc0)==0x80)
{ /* UTF8 l=3 */
#ifdef DEBUG_TXT
@@ -390,12 +616,17 @@ int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int
}
p+=2;
}
+ else if( 'A' <= *p && *p <='Z')
+ {
+ *q = *p-'A'+'a';
+ p++;
+ }
else
{ /* Ascii UCS */
#ifdef DEBUG_TXT
log_info("UTF8 Ascii UCS 0x%02x\n", *p);
#endif
- *q = tolower(*p);
+ *q = *p;
p++;
}
if (*q=='\0' || filtre(*q)==0)
@@ -404,25 +635,33 @@ int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int
log_warning("UTF2Lat reject 0x%x\n",*q);
#endif
*q = '\0';
- return(p_org-buffer);
+ return offset_dst;
}
q++;
- i--;
+ offset_dst++;
}
*q = '\0';
- return(p-buffer);
+ return offset_dst;
}
-static int UTFsize(const unsigned char *buffer, const unsigned int buf_len)
+int UTFsize(const unsigned char *buffer, const unsigned int buf_len)
{
const unsigned char *p=buffer; /* pointers to actual position in source buffer */
unsigned int i=0;
+ /*@
+ @ loop invariant 0 <= i < buf_len + 3;
+ @ loop invariant p == buffer + i;
+ @ loop assigns i, p;
+ @ loop variant buf_len - 1 - i;
+ @*/
while(i<buf_len && *p!='\0')
{
/* Reject some invalid UTF-8 sequences */
if(*p==0xc0 || *p==0xc1 || *p==0xf7 || *p>=0xfd)
return i;
- if((*p & 0xf0)==0xe0 && (i+2 >= buf_len || ((*(p+1) & 0xc0)==0x80 && (*(p+2) & 0xc0)==0x80)))
+ if((*p & 0xf0)==0xe0 &&
+ (i+1 >= buf_len || (*(p+1) & 0xc0)==0x80) &&
+ (i+2 >= buf_len || (*(p+2) & 0xc0)==0x80))
{ /* UTF8 l=3 */
#ifdef DEBUG_TXT
log_info("UTFsize i=%u l=3\n", i);
@@ -430,7 +669,8 @@ static int UTFsize(const unsigned char *buffer, const unsigned int buf_len)
p+=3;
i+=3;
}
- else if((*p & 0xe0)==0xc0 && (i+1 >= buf_len || (*(p+1) & 0xc0)==0x80))
+ else if((*p & 0xe0)==0xc0 &&
+ (i+1 >= buf_len || (*(p+1) & 0xc0)==0x80))
{ /* UTF8 l=2 */
#ifdef DEBUG_TXT
log_info("UTFsize i=%u l=2\n", i);
@@ -481,47 +721,68 @@ static int UTFsize(const unsigned char *buffer, const unsigned int buf_len)
return (i<buf_len?i:buf_len);
}
+/*@
+ @ requires buffer_size >= 2 && (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_html;
+ @ assigns file_recovery->calculated_file_size;
+ @ ensures \result == DC_STOP || \result == DC_CONTINUE;
+ @*/
static data_check_t data_check_html(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
const char sign_html_end[] = "</html>";
- const unsigned int i=UTFsize(&buffer[buffer_size/2], buffer_size/2);
- unsigned int j;
- for(j=(buffer_size/2>sizeof(sign_html_end)?buffer_size/2-sizeof(sign_html_end):0);
- j+sizeof(sign_html_end)-1 < buffer_size;
- j++)
+ if(buffer_size/2 > (sizeof(sign_html_end)-1))
{
- if(buffer[j]=='<' && strncasecmp((const char *)&buffer[j], sign_html_end, sizeof(sign_html_end)-1)==0)
+ unsigned int j;
+ /*@
+ @ loop assigns j, file_recovery->calculated_file_size;
+ @*/
+ for(j=buffer_size/2-(sizeof(sign_html_end)-1);
+ j+sizeof(sign_html_end)-1 < buffer_size;
+ j++)
{
- file_recovery->calculated_file_size+=j-buffer_size/2+sizeof(sign_html_end)-1;
- return DC_STOP;
+ if(buffer[j]=='<' && strncasecmp((const char *)&buffer[j], sign_html_end, sizeof(sign_html_end)-1)==0)
+ {
+ j+=sizeof(sign_html_end)-1;
+ /*@ assert j >= buffer_size/2; */
+ /*@ loop assigns j; */
+ while(j < buffer_size && (buffer[j]=='\n' || buffer[j]=='\r'))
+ j++;
+ file_recovery->calculated_file_size+=j-buffer_size/2;
+ return DC_STOP;
+ }
}
}
- if(i<buffer_size/2)
- {
- if(i>=10)
- file_recovery->calculated_file_size=file_recovery->file_size+i;
- return DC_STOP;
- }
- file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
- return DC_CONTINUE;
-}
-
-static data_check_t data_check_txt(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
-{
- const unsigned int i=UTFsize(&buffer[buffer_size/2], buffer_size/2);
- if(i<buffer_size/2)
{
- if(i>=10)
- file_recovery->calculated_file_size=file_recovery->file_size+i;
- return DC_STOP;
+ const unsigned int i=UTFsize(&buffer[buffer_size/2], buffer_size/2);
+ if(i<buffer_size/2)
+ {
+ if(i>=10)
+ file_recovery->calculated_file_size=file_recovery->file_size+i;
+ return DC_STOP;
+ }
}
file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size >= 2 && (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_ttd;
+ @ assigns file_recovery->calculated_file_size;
+ @ ensures \result == DC_STOP || \result == DC_CONTINUE;
+ @*/
static data_check_t data_check_ttd(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
unsigned int i;
+ /*@
+ @ loop invariant buffer_size/2 <= i <= buffer_size;
+ @ loop assigns i, file_recovery->calculated_file_size;
+ @ loop variant buffer_size - i;
+ @*/
for(i=buffer_size/2; i<buffer_size; i++)
{
const unsigned char car=buffer[i];
@@ -534,159 +795,139 @@ static data_check_t data_check_ttd(const unsigned char *buffer, const unsigned i
return DC_CONTINUE;
}
-static int header_check_ttd(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)
-{
- if(buffer[56]<'0' || buffer[56]>'9')
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_ttd;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="ttd";
- return 1;
-}
-
-static void file_check_ers(file_recovery_t *file_recovery)
-{
- file_search_footer(file_recovery, "DatasetHeader End", 17, 0);
- file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
-}
-
-static int header_check_ers(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)
-{
- /* ER Mapper Rasters (ERS) */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_ers;
- file_recovery_new->extension="ers";
- return 1;
-}
-
-static int header_check_ics(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)
+/*@
+ @ requires buffer_size >= 2 && (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_txt;
+ @ assigns file_recovery->calculated_file_size;
+ @ ensures \result == DC_STOP || \result == DC_CONTINUE;
+ @*/
+static data_check_t data_check_txt(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
- const char *date_asc;
- char *buffer2;
- if(buffer[15]=='\0')
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_size;
- /* vcalendar */
- file_recovery_new->extension="ics";
- /* DTSTART:19970714T133000 ;Local time
- * DTSTART:19970714T173000Z ;UTC time
- * DTSTART;TZID=US-Eastern:19970714T133000 ;Local time and time
- */
- buffer2=(char *)MALLOC(buffer_size+1);
- buffer2[buffer_size]='\0';
- memcpy(buffer2, buffer, buffer_size);
- date_asc=strstr(buffer2, "DTSTART");
- if(date_asc!=NULL)
- date_asc=strchr(date_asc, ':');
- if(date_asc!=NULL && date_asc+1+14 < buffer2+buffer_size)
+ const unsigned int i=UTFsize(&buffer[buffer_size/2], buffer_size/2);
+ if(i<buffer_size/2)
{
- file_recovery_new->time=get_time_from_YYYYMMDD_HHMMSS(date_asc+1);
+ if(i>=10)
+ file_recovery->calculated_file_size=file_recovery->file_size+i;
+ return DC_STOP;
}
- free(buffer2);
- return 1;
+ file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
+ return DC_CONTINUE;
}
-static int header_check_perlm(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)
+/*@
+ @ requires buffer_size >= 10 && (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_xml_utf8;
+ @ assigns file_recovery->calculated_file_size,file_recovery->data_check;
+ @ ensures \result == DC_STOP || \result == DC_CONTINUE;
+ @ ensures \result == DC_CONTINUE ==> (file_recovery->data_check==&data_check_txt);
+ @*/
+static data_check_t data_check_xml_utf8(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
unsigned int i;
- const unsigned int buffer_size_test=(buffer_size < 2048 ? buffer_size : 2048);
- for(i=0; i<128 && buffer[i]!=';' && buffer[i]!='\n'; i++);
- if(buffer[i]!=';')
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_size;
- if( td_memmem(buffer, buffer_size_test, "class", 5)!=NULL ||
- td_memmem(buffer, buffer_size_test, "private static", 14)!=NULL ||
- td_memmem(buffer, buffer_size_test, "public interface", 16)!=NULL)
- {
- /* source code in java */
-#ifdef DJGPP
- file_recovery_new->extension="jav";
-#else
- file_recovery_new->extension="java";
-#endif
- }
- else
+ if(buffer_size<=8)
+ return DC_CONTINUE;
+ i=UTFsize(&buffer[buffer_size/2+4], buffer_size/2-4)+4;
+ if(i<buffer_size/2)
{
- /* perl module */
- file_recovery_new->extension="pm";
- }
- return 1;
-}
-
-static int header_check_dc(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)
-{
- if(buffer[0]=='0' && buffer[1]=='0')
- { /*
- TSCe Survey Controller DC v10.0
- */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="dc";
- return 1;
+ file_recovery->calculated_file_size=file_recovery->file_size+i;
+ return DC_STOP;
}
- return 0;
+ file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
+ file_recovery->data_check=&data_check_txt;
+ return DC_CONTINUE;
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((char*)file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_fods;
+ @ ensures valid_read_string((char*)file_recovery->filename);
+ @*/
static void file_rename_fods(file_recovery_t *file_recovery)
{
+ const char *meta_title="<office:meta><dc:title>";
FILE *file;
char buffer[4096];
- char *tmp;
+ char *tmp=NULL;
size_t lu;
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
if((file=fopen(file_recovery->filename, "rb"))==NULL)
+ {
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
+ }
if((lu=fread(&buffer, 1, sizeof(buffer)-1, file)) <= 0)
{
fclose(file);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return ;
}
+ fclose(file);
buffer[lu]='\0';
- tmp=strchr(buffer,'<');
- while(tmp!=NULL)
+#ifndef __FRAMAC__
+ /*@
+ @ loop invariant tmp==\null || valid_read_string(tmp);
+ @ loop assigns tmp;
+ @*/
+ for(tmp=strchr(buffer,'<');
+ tmp!=NULL && strncasecmp(tmp, meta_title, 23)!=0;
+ tmp=strchr(tmp,'<'))
{
- if(strncasecmp(tmp, "<office:meta><dc:title>", 23)==0)
- {
- const char *title=tmp+23;
- tmp=strchr(title,'<');
- if(tmp!=NULL)
- *tmp='\0';
- file_rename(file_recovery, (const unsigned char*)title, strlen(title), 0, NULL, 1);
- fclose(file);
- return ;
- }
+ /* TODO assert tmp[0]=='<'; */
+ /*@ assert valid_read_string(tmp); */
tmp++;
- tmp=strchr(tmp,'<');
+ /*@ assert valid_read_string(tmp); */
}
- fclose(file);
+ if(tmp!=NULL)
+ {
+ const char *title=tmp+23;
+ /*@ assert valid_read_string(title); */
+ tmp=strchr(title,'<');
+ if(tmp!=NULL)
+ *tmp='\0';
+ file_rename(file_recovery, (const unsigned char*)title, strlen(title), 0, NULL, 1);
+ }
+#endif
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((char*)file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_html;
+ @ ensures valid_read_string((char*)file_recovery->filename);
+ @*/
static void file_rename_html(file_recovery_t *file_recovery)
{
FILE *file;
char buffer[4096];
char *tmp;
size_t lu;
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
if((file=fopen(file_recovery->filename, "rb"))==NULL)
+ {
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
+ }
if((lu=fread(&buffer, 1, sizeof(buffer)-1, file)) <= 0)
{
fclose(file);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return ;
}
+ fclose(file);
buffer[lu]='\0';
+#ifndef __FRAMAC__
tmp=strchr(buffer,'<');
while(tmp!=NULL)
{
if(strncasecmp(tmp, "</head", 5)==0)
{
- fclose(file);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return ;
}
if(strncasecmp(tmp, "<title>", 7)==0)
@@ -696,294 +937,381 @@ static void file_rename_html(file_recovery_t *file_recovery)
if(tmp!=NULL)
*tmp='\0';
file_rename(file_recovery, (const unsigned char*)title, strlen(title), 0, NULL, 1);
- fclose(file);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return ;
}
tmp++;
tmp=strchr(tmp,'<');
}
- fclose(file);
-}
-
-static int header_check_html(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)
-{
- if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
- strcmp(file_recovery->extension,"mbox")==0)
- return 0;
- if(buffer[14]==0)
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_html;
- file_recovery_new->file_check=&file_check_size;
- /* Hypertext Markup Language (HTML) */
-#ifdef DJGPP
- file_recovery_new->extension="htm";
-#else
- file_recovery_new->extension="html";
#endif
- file_recovery_new->file_rename=&file_rename_html;
- return 1;
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
}
-static void file_check_vbm(file_recovery_t *file_recovery)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_emlx;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_emlx(file_recovery_t *file_recovery)
{
- file_search_footer(file_recovery, "</BackupMeta>", 13, 0);
- file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
+ if(file_recovery->file_size < file_recovery->calculated_file_size)
+ file_recovery->file_size=0;
+ else
+ {
+ if(file_recovery->file_size > file_recovery->calculated_file_size+2048)
+ file_recovery->file_size=file_recovery->calculated_file_size+2048;
+ file_search_footer(file_recovery, "</plist>\n", 9, 0);
+ }
}
-static int header_check_vbm(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)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_ers;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_ers(file_recovery_t *file_recovery)
{
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->extension="vbm";
- file_recovery_new->file_check=&file_check_vbm;
- return 1;
+ file_search_footer(file_recovery, "DatasetHeader End", 17, 0);
+ file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_gpx;
+ @ ensures \valid(file_recovery->handle);
+ @*/
static void file_check_gpx(file_recovery_t *file_recovery)
{
file_search_footer(file_recovery, "</gpx>", 6, 0);
file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
-static void file_check_xml(file_recovery_t *file_recovery)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_svg;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_svg(file_recovery_t *file_recovery)
{
- file_search_footer(file_recovery, ">", 1, 0);
+ file_search_footer(file_recovery, "</svg>", 6, 0);
file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
-static void file_check_svg(file_recovery_t *file_recovery)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_smil;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_smil(file_recovery_t *file_recovery)
{
- file_search_footer(file_recovery, "</svg>", 6, 0);
+ file_search_footer(file_recovery, "</smil>", 7, 0);
file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
-static data_check_t data_check_xml_utf8(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_vbm;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_vbm(file_recovery_t *file_recovery)
{
- unsigned int i;
- if(buffer_size<=8)
- return DC_CONTINUE;
- i=UTFsize(&buffer[buffer_size/2+4], buffer_size/2-4)+4;
- if(i<buffer_size/2)
- {
- file_recovery->calculated_file_size=file_recovery->file_size+i;
- return DC_STOP;
- }
- file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
- file_recovery->data_check=&data_check_txt;
- return DC_CONTINUE;
+ file_search_footer(file_recovery, "</BackupMeta>", 13, 0);
+ file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
-static int header_check_xml_utf8(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)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_xml;
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_xml(file_recovery_t *file_recovery)
{
- const char *tmp;
- /* buffer may not be null-terminated */
- char *buf=(char *)MALLOC(buffer_size+1);
- memcpy(buf, buffer, buffer_size);
- buf[buffer_size]='\0';
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_xml_utf8;
- file_recovery_new->extension=NULL;
- tmp=strchr(buf,'<');
- while(tmp!=NULL && file_recovery_new->extension==NULL)
- {
- if(strncasecmp(tmp, "<Archive name=\"Root\">", 8)==0)
- {
- /* Grasshopper archive */
- file_recovery_new->extension="ghx";
- }
- tmp++;
- tmp=strchr(tmp,'<');
- }
- if(file_recovery_new->extension==NULL)
- {
- file_recovery_new->extension="xml";
- }
- file_recovery_new->file_check=&file_check_xml;
- free(buf);
- return 1;
+ file_search_footer(file_recovery, ">", 1, 0);
+ file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
}
-static int header_check_xml_utf16(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_dc);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> (\separated(file_recovery_new, file_recovery_new->extension));
+ @*/
+static int header_check_dc(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)
{
- /* Avoid false positive with .sldprt */
- if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_doc)
+ if(buffer_size < 2)
+ return 0;
+ if(buffer[0]!='0' || buffer[1]!='0')
return 0;
+ /*
+ TSCe Survey Controller DC v10.0
+ */
reset_file_recovery(file_recovery_new);
- file_recovery_new->extension="xml";
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=extension_dc;
return 1;
}
-static int header_check_xml(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 1;
+ @ ensures file_recovery_new->file_stat == \null;
+ @ ensures file_recovery_new->handle == \null;
+ @ ensures file_recovery_new->calculated_file_size == 0;
+ @ ensures file_recovery_new->extension == extension_ers;
+ @ ensures file_recovery_new->file_size == 0;
+ @ ensures file_recovery_new->min_filesize == 0;
+ @ ensures file_recovery_new->data_check == &data_check_txt;
+ @ ensures file_recovery_new->file_check == &file_check_ers;
+ @ ensures file_recovery_new->file_rename == \null;
+ @ ensures valid_read_string(file_recovery_new->extension);
+ @ ensures \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_ers(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 char *tmp;
- /* buffer may not be null-terminated */
- char *buf=(char *)MALLOC(buffer_size+1);
- memcpy(buf, buffer, buffer_size);
- buf[buffer_size]='\0';
+ /* ER Mapper Rasters (ERS) */
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->extension=NULL;
- tmp=strchr(buf,'<');
- while(tmp!=NULL && file_recovery_new->extension==NULL)
+ file_recovery_new->file_check=&file_check_ers;
+ file_recovery_new->extension=extension_ers;
+ return 1;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize > 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension != \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_fasttxt(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 txt_header_t *header=&fasttxt_headers[0];
+ /*@ loop unroll 200; */
+ while(header->len > 0)
{
- if(strncasecmp(tmp, "<Grisbi>", 8)==0)
- {
- /* Grisbi - Personal Finance Manager XML data */
- file_recovery_new->extension="gsb";
- }
- else if(strncasecmp(tmp, "<collection type=\"GC", 20)==0)
- {
- /* GCstart, personal collections manager, http://www.gcstar.org/ */
- file_recovery_new->extension="gcs";
- }
- else if(strncasecmp(tmp, "<html", 5)==0)
- {
- file_recovery_new->data_check=&data_check_html;
-#ifdef DJGPP
- file_recovery_new->extension="htm";
-#else
- file_recovery_new->extension="html";
-#endif
- file_recovery_new->file_rename=&file_rename_html;
- }
- else if(strncasecmp(tmp, "<Version>QBFSD", 14)==0)
- {
- /* QuickBook */
- file_recovery_new->extension="fst";
- }
- else if(strncasecmp(tmp, "<svg", 4)==0)
- {
- /* Scalable Vector Graphics */
- file_recovery_new->extension="svg";
- file_recovery_new->file_check=&file_check_svg;
- free(buf);
- return 1;
- }
- else if(strncasecmp(tmp, "<!DOCTYPE plist ", 16)==0)
- {
- /* Mac OS X property list */
-#ifdef DJGPP
- file_recovery_new->extension="pli";
-#else
- file_recovery_new->extension="plist";
-#endif
- }
- else if(strncasecmp(tmp, "<gpx ", 5)==0)
+ if(memcmp(buffer, header->string, header->len)==0)
{
- /* GPS eXchange Format */
- file_recovery_new->extension="gpx";
- file_recovery_new->file_check=&file_check_gpx;
- free(buf);
+ if(buffer[header->len]=='\0')
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ /*@ assert valid_read_string(header->extension); */
+ file_recovery_new->extension=header->extension;
+ /*@ assert file_recovery_new->extension != \null; */
+ file_recovery_new->min_filesize=header->len+1;
+ /*@ assert file_recovery_new->file_stat == \null; */
+ /*@ assert file_recovery_new->handle == \null; */
+ /*@ assert file_recovery_new->min_filesize > 0; */
+ /*@ assert file_recovery_new->calculated_file_size == 0; */
+ /*@ assert file_recovery_new->file_size == 0; */
+ /*@ assert file_recovery_new->data_check == &data_check_txt; */
+ /*@ assert file_recovery_new->file_check == &file_check_size; */
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ /*@ assert \separated(file_recovery_new, file_recovery_new->extension); */
return 1;
}
- else if(strncasecmp(tmp, "<PremiereData Version=", 22)==0)
- {
- /* Adobe Premiere project */
- file_recovery_new->data_check=NULL;
- file_recovery_new->extension="prproj";
- }
- else if(strncasecmp(tmp, "<SCRIBUS", 8)==0)
- {
- /* Scribus XML file */
- file_recovery_new->extension="sla";
- }
- else if(strncasecmp(tmp, "<FictionBook", 12)==0)
- {
- /* FictionBook, see http://www.fictionbook.org */
- file_recovery_new->extension="fb2";
- }
- else if(strncasecmp(tmp, "<office:document", 16)==0)
- {
- /* OpenDocument Flat XML Spreadsheet */
- file_recovery_new->extension="fods";
- file_recovery_new->data_check=NULL;
- file_recovery_new->file_rename=&file_rename_fods;
- }
- tmp++;
- tmp=strchr(tmp,'<');
- }
- if(file_recovery_new->extension==NULL)
- {
- /* XML Extensible Markup Language */
- file_recovery_new->extension="xml";
+ header++;
}
- file_recovery_new->file_check=&file_check_xml;
- free(buf);
- return 1;
+ return 0;
}
-static int header_check_rtf(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_html);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_html);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_html);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_html(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)
{
- unsigned int i;
- for(i=0; i<16; i++)
- if(buffer[i]=='\0')
- return 0;
- /* Avoid a false positive with .snt */
+ if(buffer_size < 15)
+ return 0;
if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_doc)
+ file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
+ file_recovery->extension==extension_mbox)
+ return 0;
+ if(buffer[14]==0)
return 0;
reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->data_check=&data_check_html;
file_recovery_new->file_check=&file_check_size;
- /* Rich Text Format */
- file_recovery_new->extension="rtf";
+ /* Hypertext Markup Language (HTML) */
+ file_recovery_new->extension=extension_html;
+ file_recovery_new->file_rename=&file_rename_html;
return 1;
}
-static int header_check_xmp(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_ics);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_ics(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)
{
- if(buffer[35]=='\0')
+ const char *date_asc;
+ char *buffer2;
+ if(buffer_size < 22)
return 0;
- if(file_recovery->file_stat!=NULL &&
- (file_recovery->file_stat->file_hint==&file_hint_jpg ||
- file_recovery->file_stat->file_hint==&file_hint_pdf ||
- file_recovery->file_stat->file_hint==&file_hint_tiff))
+ if(buffer[15]=='\0')
return 0;
- /* Adobe's Extensible Metadata Platform */
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="xmp";
- return 1;
-}
-
-static void file_check_thunderbird(file_recovery_t *file_recovery)
-{
- if(file_recovery->file_size<file_recovery->calculated_file_size)
+ /* vcalendar */
+ file_recovery_new->extension=extension_ics;
+ /* DTSTART:19970714T133000 ;Local time
+ * DTSTART:19970714T173000Z ;UTC time
+ * DTSTART;TZID=US-Eastern:19970714T133000 ;Local time and time
+ */
+ buffer2=(char *)MALLOC(buffer_size+1);
+ buffer2[buffer_size]='\0';
+ memcpy(buffer2, buffer, buffer_size);
+ date_asc=strstr(buffer2, "DTSTART");
+ if(date_asc!=NULL)
+ date_asc=strchr(date_asc, ':');
+ if(date_asc!=NULL && date_asc+1+14 < buffer2+buffer_size)
{
- file_recovery->file_size=0;
- return;
+ file_recovery_new->time=get_time_from_YYYYMMDD_HHMMSS(date_asc+1);
}
- file_recovery->file_size=file_recovery->calculated_file_size;
+ free(buffer2);
+ return 1;
}
-static int header_check_thunderbird(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)
+#ifdef UTF16
+static int header_check_le16_txt(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)
{
unsigned int i;
- if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
- strcmp(file_recovery->extension,"mbox")==0)
- return 0;
- for(i=0; i<64; i++)
- if(buffer[i]==0)
- return 0;
+ for(i=0; i+1 < buffer_size; i+=2)
+ {
+ if(!( buffer[i+1]=='\0' && (isprint(buffer[i]) || buffer[i]=='\n' || buffer[i]=='\r' || buffer[i]==0xbb)))
+ {
+ if(i<40)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->calculated_file_size=i;
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=extension_utf16;
+ return 1;
+ }
+ }
reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_thunderbird;
- file_recovery_new->extension="mbox";
+ file_recovery_new->calculated_file_size=i;
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=extension_utf16;
return 1;
}
+#endif
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_mbox);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
static int header_check_mbox(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)
{
unsigned int i;
+ if(buffer_size < 200)
+ return 0;
if(file_recovery->file_stat!=NULL &&
file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
- strcmp(file_recovery->extension,"mbox")==0)
+ file_recovery->extension==extension_mbox)
return 0;
+ /*@ loop assigns i; */
for(i=0; i<64; i++)
if(buffer[i]==0)
return 0;
@@ -991,6 +1319,7 @@ static int header_check_mbox(const unsigned char *buffer, const unsigned int buf
memcmp(buffer, "From MAILER-DAEMON ", 19)!=0)
{
/* From someone@somewhere */
+ /*@ loop assigns i; */
for(i=5; i<200 && buffer[i]!=' ' && buffer[i]!='@'; i++);
if(buffer[i]!='@')
return 0;
@@ -999,114 +1328,365 @@ static int header_check_mbox(const unsigned char *buffer, const unsigned int buf
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Incredimail has .imm extension but this extension isn't frequent */
- file_recovery_new->extension="mbox";
+ file_recovery_new->extension=extension_mbox;
return 1;
}
-static int header_check_fasttxt(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_java || file_recovery_new->extension == extension_pm);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_perlm(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 txt_header_t *header=&fasttxt_headers[0];
- while(header->len > 0)
+ unsigned int i;
+ const unsigned int buffer_size_test=(buffer_size < 2048 ? buffer_size : 2048);
+ if(buffer_size < 128)
+ return 0;
+ for(i=0; i<128 && buffer[i]!=';' && buffer[i]!='\n'; i++);
+ if(buffer[i]!=';')
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ if( td_memmem(buffer, buffer_size_test, "class", 5)!=NULL ||
+ td_memmem(buffer, buffer_size_test, "private static", 14)!=NULL ||
+ td_memmem(buffer, buffer_size_test, "public interface", 16)!=NULL)
{
- if(memcmp(buffer, header->string, header->len)==0)
- {
- if(buffer[header->len]=='\0')
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension=header->extension;
- file_recovery_new->min_filesize=header->len+1;
- return 1;
- }
- header++;
+ /* source code in java */
+ file_recovery_new->extension=extension_java;
}
- return 0;
+ else
+ {
+ /* perl module */
+ file_recovery_new->extension=extension_pm;
+ }
+ return 1;
}
-static int is_ini(const char *buffer)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_rtf);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_rtf(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 char *src=buffer;
- if(*src!='[')
+ unsigned int i;
+ if(buffer_size < 16)
return 0;
- src++;
- while(1)
- {
- if(*src==']')
- {
- if(src > buffer + 3)
- return 1;
- return 0;
- }
- if(!isalnum(*src) && *src!=' ')
+ for(i=0; i<16; i++)
+ if(buffer[i]=='\0')
return 0;
- src++;
- }
+ /* Avoid a false positive with .snt */
+ if(file_recovery->file_stat!=NULL
+#if !defined(MAIN_txt)
+ && file_recovery->file_stat->file_hint==&file_hint_doc
+#endif
+ )
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ /* Rich Text Format */
+ file_recovery_new->extension=extension_rtf;
+ return 1;
}
-#ifdef UTF16
-static int header_check_le16_txt(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_smil);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_smil);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_smil(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)
+{
+ /* Synchronized Multimedia Integration Language
+ * http://en.wikipedia.org/wiki/Synchronized_Multimedia_Integration_Language */
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_smil;
+ file_recovery_new->extension=extension_smil;
+ return 1;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_snz, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_snz.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_snz(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 unsigned int buffer_size_test=(buffer_size < 512? buffer_size : 512);
+ const unsigned char *pos=(const unsigned char *)td_memmem(buffer, buffer_size_test, ".snz", 4);
+ if(pos==NULL)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=file_hint_snz.extension;
+ file_recovery_new->min_filesize=pos-buffer;
+ return 1;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_stl);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_stl(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 unsigned int buffer_size_test=(buffer_size < 512? buffer_size : 512);
+ if(td_memmem(buffer, buffer_size_test, "facet normal", 12)==NULL)
+ return 0;
+ /* StereoLithography - STL Ascii format
+ * http://www.ennex.com/~fabbers/StL.asp */
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=extension_stl;
+ return 1;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_svg);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_svg);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_svg(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)
+{
+ /* Scalable Vector Graphics */
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=extension_svg;
+ file_recovery_new->file_check=&file_check_svg;
+ return 1;
+}
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_mbox);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_thunderbird(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)
{
unsigned int i;
- for(i=0; i+1 < buffer_size; i+=2)
- {
- if(!( buffer[i+1]=='\0' && (isprint(buffer[i]) || buffer[i]=='\n' || buffer[i]=='\r' || buffer[i]==0xbb)))
- {
- if(i<40)
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->calculated_file_size=i;
- file_recovery_new->data_check=&data_check_size;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="utf16";
- return 1;
- }
- }
+ if(buffer_size < 64)
+ return 0;
+ if(file_recovery->file_stat!=NULL &&
+ file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
+ file_recovery->extension == extension_mbox)
+ return 0;
+ /*@ loop assigns i; */
+ for(i=0; i<64; i++)
+ if(buffer[i]==0)
+ return 0;
reset_file_recovery(file_recovery_new);
- file_recovery_new->calculated_file_size=i;
- file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="utf16";
+ file_recovery_new->extension=extension_mbox;
return 1;
}
-#endif
-static void file_check_emlx(file_recovery_t *file_recovery)
+/*@
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_ttd);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_ttd);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_ttd(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)
{
- if(file_recovery->file_size < file_recovery->calculated_file_size)
- file_recovery->file_size=0;
- else
- {
- if(file_recovery->file_size > file_recovery->calculated_file_size+2048)
- file_recovery->file_size=file_recovery->calculated_file_size+2048;
- file_search_footer(file_recovery, "</plist>\n", 9, 0);
- }
+ if(buffer[56]<'0' || buffer[56]>'9')
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_ttd;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->extension=extension_ttd;
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ /*@ assert \separated(file_recovery_new, file_recovery_new->extension); */
+ return 1;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension != \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || file_recovery_new->data_check == &data_check_html || file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_emlx || file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || file_recovery_new->file_rename == &file_rename_html);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
static int header_check_txt(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)
{
static char *buffer_lower=NULL;
static unsigned int buffer_lower_size=0;
unsigned int l;
const unsigned int buffer_size_test=(buffer_size < 2048 ? buffer_size : 2048);
+ if(buffer_size < 512)
+ return 0;
{
unsigned int i;
- unsigned int tmp=0;
+ uint64_t tmp=0;
+ /*@
+ @ loop unroll 10;
+ @ loop invariant 0 <= i <= 10;
+ @ loop assigns i, tmp;
+ @ loop variant 10-i;
+ @*/
for(i=0;i<10 && isdigit(buffer[i]);i++)
- tmp=tmp*10+buffer[i]-'0';
+ {
+ /*@ assert '0' <= buffer[i] <= '9'; */
+ unsigned int v=buffer[i]-'0';
+ /*@ assert 0 <= v <= 9; */
+ tmp=tmp*10+v;
+ }
if(buffer[i]==0x0a &&
(memcmp(buffer+i+1, "Return-Path: ", 13)==0 ||
memcmp(buffer+i+1, "Received: from", 14)==0) &&
!(file_recovery->file_stat!=NULL &&
file_recovery->file_stat->file_hint==&file_hint_fasttxt &&
- strcmp(file_recovery->extension,"mbox")==0))
+ file_recovery->extension==extension_mbox))
{
reset_file_recovery(file_recovery_new);
file_recovery_new->calculated_file_size=tmp+i+1;
file_recovery_new->data_check=NULL;
file_recovery_new->file_check=&file_check_emlx;
/* Mac OSX mail */
- file_recovery_new->extension="emlx";
+ file_recovery_new->extension=extension_emlx;
return 1;
}
}
@@ -1118,7 +1698,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Dos/Windows batch */
- file_recovery_new->extension="bat";
+ file_recovery_new->extension=extension_bat;
return 1;
}
if(strncasecmp((const char *)buffer, "<%@ language=\"vbscript", 22)==0)
@@ -1129,7 +1709,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Microsoft Active Server Pages */
- file_recovery_new->extension="asp";
+ file_recovery_new->extension=extension_asp;
return 1;
}
if(strncasecmp((const char *)buffer, "version 4.00\r\nbegin", 19)==0)
@@ -1140,7 +1720,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Microsoft Visual Basic */
- file_recovery_new->extension="vb";
+ file_recovery_new->extension=extension_vb;
return 1;
}
if(strncasecmp((const char *)buffer, "begin:vcard", 11)==0)
@@ -1151,7 +1731,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* vcard, electronic business cards */
- file_recovery_new->extension="vcf";
+ file_recovery_new->extension=extension_vcf;
return 1;
}
if(buffer[0]=='#' && buffer[1]=='!')
@@ -1168,7 +1748,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Groovy script */
- file_recovery_new->extension="groovy";
+ file_recovery_new->extension=extension_groovy;
return 1;
}
if(td_memmem(haystack, ll, "perl", 4) != NULL)
@@ -1177,7 +1757,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Perl script */
- file_recovery_new->extension="pl";
+ file_recovery_new->extension=extension_pl;
return 1;
}
if(td_memmem(haystack, ll, "php", 3) != NULL)
@@ -1186,7 +1766,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* PHP script */
- file_recovery_new->extension="php";
+ file_recovery_new->extension=extension_php;
return 1;
}
if(td_memmem(haystack, ll, "python", 6) != NULL)
@@ -1195,7 +1775,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Python script */
- file_recovery_new->extension="py";
+ file_recovery_new->extension=extension_py;
return 1;
}
if(td_memmem(haystack, ll, "ruby", 4) != NULL)
@@ -1204,7 +1784,7 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Ruby script */
- file_recovery_new->extension="rb";
+ file_recovery_new->extension=extension_rb;
return 1;
}
}
@@ -1237,25 +1817,15 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
l=UTF2Lat((unsigned char*)buffer_lower, buffer, buffer_size_test);
if(l<10)
return 0;
- {
- unsigned int line_nbr=0;
- unsigned int i;
- for(i=0; i<512 && i<l; i++)
- {
- if(buffer[i]=='\n')
- line_nbr++;
- }
- /* A text file must contains several lines */
- if(line_nbr==0)
- return 0;
- }
+ if(has_newline(buffer_lower, l)==0)
+ return 0;
if(strncasecmp((const char *)buffer, "rem ", 4)==0)
{
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
/* Dos/Windows batch */
- file_recovery_new->extension="bat";
+ file_recovery_new->extension=extension_bat;
return 1;
}
if(strncasecmp((const char *)buffer, "dn: ", 4)==0)
@@ -1263,152 +1833,115 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="ldif";
+ file_recovery_new->extension=extension_ldif;
return 1;
}
{
const char *ext=NULL;
- /* ind=~0: random
- * ind=~1: constant */
- double ind;
- unsigned int nbrf=0;
- unsigned int is_csv=1;
- char *str;
- /* Detect Fortran */
- {
- str=buffer_lower;
- while((str=strstr(str, "\n "))!=NULL)
- {
- nbrf++;
- str++;
- }
- }
- /* Detect csv */
- {
- unsigned int csv_per_line_current=0;
- unsigned int csv_per_line=0;
- unsigned int line_nbr=0;
- unsigned int i;
- for(i=0;i<l && is_csv>0;i++)
- {
- if(buffer_lower[i]==';')
- {
- csv_per_line_current++;
- }
- else if(buffer_lower[i]=='\n')
- {
- if(line_nbr==0)
- csv_per_line=csv_per_line_current;
- if(csv_per_line_current!=csv_per_line)
- is_csv=0;
- line_nbr++;
- csv_per_line_current=0;
- }
- }
- if(csv_per_line<1 || line_nbr<10)
- is_csv=0;
- }
- /* if(l>1) */
- {
- unsigned int stats[256];
- unsigned int i;
- memset(&stats, 0, sizeof(stats));
- for(i=0;i<l;i++)
- stats[(unsigned char)buffer_lower[i]]++;
- ind=0;
- for(i=0;i<256;i++)
- if(stats[i]>0)
- ind+=stats[i]*(stats[i]-1);
- ind=ind/l/(l-1);
- }
+ /* ind_random=~0: random
+ * ind_random=~1: constant */
+ double ind_random;
+ const char *str;
+ ind_random=is_random((const unsigned char *)buffer_lower, l);
/* Windows Autorun */
if(strstr(buffer_lower, "[autorun]")!=NULL)
- ext="inf";
+ {
+ ext=extension_inf;
+ log_info("ext=%s\n", ext);
+ }
/* Detect .ini */
- else if(buffer[0]=='[' && l>50 && is_ini(buffer_lower))
- ext="ini";
+ else if(buffer[0]=='[' && l>50 && is_ini((const unsigned char *)buffer_lower))
+ ext=extension_ini;
/* php (Hypertext Preprocessor) script */
else if(strstr(buffer_lower, "<?php")!=NULL)
- ext="php";
+ ext=extension_php;
/* Comma separated values */
- else if(is_csv>0)
- ext="csv";
+ else if(is_csv(buffer_lower, l)!=0)
+ ext=extension_csv;
/* Detect LaTeX, C, PHP, JSP, ASP, HTML, C header */
else if(strstr(buffer_lower, "\\begin{")!=NULL)
- ext="tex";
+ ext=extension_tex;
else if(strstr(buffer_lower, "#include")!=NULL)
- ext="c";
+ ext=extension_c;
else if(l>20 && strstr(buffer_lower, "<%@")!=NULL)
- ext="jsp";
+ ext=extension_jsp;
else if(l>20 && strstr(buffer_lower, "<%=")!=NULL)
- ext="jsp";
+ ext=extension_jsp;
else if(l>20 && strstr(buffer_lower, "<% ")!=NULL)
- ext="asp";
+ ext=extension_asp;
else if(strstr(buffer_lower, "<html")!=NULL)
- ext="html";
+ ext=extension_html;
else if(strstr(buffer_lower, "private static")!=NULL ||
strstr(buffer_lower, "public interface")!=NULL)
{
-#ifdef DJGPP
- ext="jav";
-#else
- ext="java";
-#endif
+ ext=extension_java;
}
else if(strstr(buffer_lower, "\nimport (")!=NULL)
{
- ext="go";
+ ext=extension_go;
}
else if((str=strstr(buffer_lower, "\nimport "))!=NULL)
{
+ /*@ assert valid_read_string(str); */
+#ifndef __FRAMAC__
str+=8;
+#endif
+ /*@ assert valid_read_string(str); */
+ /*@
+ @ loop assigns str;
+ @*/
while(*str!='\0' && *str!='\n' && *str!=';')
str++;
if(*str==';')
- ext="java";
+ ext=extension_java;
else
- ext="py";
+ ext=extension_py;
}
else if(strstr(buffer_lower, "class ")!=NULL &&
(l>=100 || file_recovery->file_stat==NULL))
{
-#ifdef DJGPP
- ext="jav";
-#else
- ext="java";
-#endif
+ ext=extension_java;
}
/* Fortran */
- else if(nbrf>10 && ind<0.9 && strstr(buffer_lower, "integer")!=NULL)
- ext="f";
+ else if(ind_random<0.9 && is_fortran(buffer_lower)!=0)
+ ext=extension_f;
/* LilyPond http://lilypond.org*/
else if(strstr(buffer_lower, "\\score {")!=NULL)
- ext="ly";
+ ext=extension_ly;
/* C header file */
else if(strstr(buffer_lower, "/*")!=NULL && l>50)
- ext="h";
- else if(l<100 || ind<0.03 || ind>0.90)
+ ext=extension_h;
+ else if(l<100 || ind_random<0.03 || ind_random>0.90)
ext=NULL;
/* JavaScript Object Notation */
else if(memcmp(buffer_lower, "{\"", 2)==0)
- ext="json";
+ ext=extension_json;
+ else if(strstr(buffer_lower,"<br>")!=NULL || strstr(buffer_lower,"<p>")!=NULL)
+ ext=extension_html;
else
ext=file_hint_txt.extension;
if(ext==NULL)
return 0;
- if(strcmp(ext,"txt")==0 &&
- (strstr(buffer_lower,"<br>")!=NULL || strstr(buffer_lower,"<p>")!=NULL))
- {
- ext="html";
- }
if(file_recovery->file_stat!=NULL)
{
- if(file_recovery->file_stat->file_hint == &file_hint_doc)
+ if(file_recovery->file_stat->file_hint == &file_hint_fasttxt ||
+ file_recovery->file_stat->file_hint == &file_hint_txt)
+ {
+ /* file_recovery->filename is a .html */
+ buffer_lower[511]='\0';
+ if(strstr(buffer_lower, "<html")==NULL)
+ return 0;
+ /* Special case: two consecutive HTML files */
+ }
+ else
+#if !defined(MAIN_txt)
+ if(file_recovery->file_stat->file_hint == &file_hint_doc)
+#endif
{
unsigned int i;
unsigned int txt_nl=0;
/* file_recovery->filename is .doc */
- if(ind>0.20)
+ if(ind_random>0.20)
return 0;
/* Unix: \n (0xA)
* Dos: \r\n (0xD 0xA)
@@ -1424,18 +1957,9 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
if(txt_nl<=1)
return 0;
}
- else if(file_recovery->file_stat->file_hint == &file_hint_fasttxt ||
- file_recovery->file_stat->file_hint == &file_hint_txt)
- {
- /* file_recovery->filename is a .html */
- buffer_lower[511]='\0';
- if(strstr(buffer_lower, "<html")==NULL)
- return 0;
- /* Special case: two consecutive HTML files */
- }
}
reset_file_recovery(file_recovery_new);
- if(strcmp(ext, "html")==0)
+ if(ext==extension_html)
{
file_recovery_new->file_rename=&file_rename_html;
file_recovery_new->data_check=&data_check_html;
@@ -1448,66 +1972,305 @@ static int header_check_txt(const unsigned char *buffer, const unsigned int buff
}
}
-static void file_check_smil(file_recovery_t *file_recovery)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_vbm);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_vbm);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_vbm(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)
{
- file_search_footer(file_recovery, "</smil>", 7, 0);
- file_allow_nl(file_recovery, NL_BARENL|NL_CRLF|NL_BARECR);
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->data_check=&data_check_txt;
+ file_recovery_new->extension=extension_vbm;
+ file_recovery_new->file_check=&file_check_vbm;
+ return 1;
}
-static int header_check_smil(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 1;
+ @ ensures file_recovery_new->file_stat == \null;
+ @ ensures file_recovery_new->handle == \null;
+ @ ensures file_recovery_new->calculated_file_size == 0;
+ @ ensures file_recovery_new->file_size == 0;
+ @ ensures file_recovery_new->min_filesize == 0;
+ @ ensures file_recovery_new->data_check == \null ||
+ file_recovery_new->data_check == data_check_html ||
+ file_recovery_new->data_check == data_check_txt;
+ @ ensures file_recovery_new->file_check == \null ||
+ file_recovery_new->file_check == &file_check_gpx ||
+ file_recovery_new->file_check == &file_check_svg ||
+ file_recovery_new->file_check == &file_check_xml;
+ @ ensures file_recovery_new->file_rename == \null ||
+ file_recovery_new->file_rename == &file_rename_fods ||
+ file_recovery_new->file_rename == &file_rename_html;
+ @ ensures valid_read_string(file_recovery_new->extension);
+ @ ensures \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_xml(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)
{
- /* Synchronized Multimedia Integration Language
- * http://en.wikipedia.org/wiki/Synchronized_Multimedia_Integration_Language */
+ const char *tmp;
+ /* buffer may not be null-terminated */
+ char *buf=(char *)MALLOC(buffer_size+1);
+ memcpy(buf, buffer, buffer_size);
+ buf[buffer_size]='\0';
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_smil;
- file_recovery_new->extension="smil";
+ file_recovery_new->file_check=&file_check_xml;
+ file_recovery_new->extension=NULL;
+ tmp=strchr(buf,'<');
+ while(tmp!=NULL)
+ {
+ if(strncasecmp(tmp, "<Grisbi>", 8)==0)
+ {
+ /* Grisbi - Personal Finance Manager XML data */
+ file_recovery_new->extension=extension_gsb;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<collection type=\"GC", 20)==0)
+ {
+ /* GCstart, personal collections manager, http://www.gcstar.org/ */
+ file_recovery_new->extension=extension_gcs;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<html", 5)==0)
+ {
+ file_recovery_new->data_check=&data_check_html;
+ file_recovery_new->extension=extension_html;
+ file_recovery_new->file_rename=&file_rename_html;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<Version>QBFSD", 14)==0)
+ {
+ /* QuickBook */
+ file_recovery_new->extension=extension_fst;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<svg", 4)==0)
+ {
+ /* Scalable Vector Graphics */
+ file_recovery_new->extension=extension_svg;
+ file_recovery_new->file_check=&file_check_svg;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<!DOCTYPE plist ", 16)==0)
+ {
+ /* Mac OS X property list */
+ file_recovery_new->extension=extension_plist;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<gpx ", 5)==0)
+ {
+ /* GPS eXchange Format */
+ file_recovery_new->extension=extension_gpx;
+ file_recovery_new->file_check=&file_check_gpx;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<PremiereData Version=", 22)==0)
+ {
+ /* Adobe Premiere project */
+ file_recovery_new->data_check=NULL;
+ file_recovery_new->extension=extension_prproj;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<SCRIBUS", 8)==0)
+ {
+ /* Scribus XML file */
+ file_recovery_new->extension=extension_sla;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<FictionBook", 12)==0)
+ {
+ /* FictionBook, see http://www.fictionbook.org */
+ file_recovery_new->extension=extension_fb2;
+ free(buf);
+ return 1;
+ }
+ else if(strncasecmp(tmp, "<office:document", 16)==0)
+ {
+ /* OpenDocument Flat XML Spreadsheet */
+ file_recovery_new->extension=extension_fods;
+ file_recovery_new->data_check=NULL;
+ file_recovery_new->file_rename=&file_rename_fods;
+ free(buf);
+ return 1;
+ }
+ tmp++;
+ tmp=strchr(tmp,'<');
+ }
+ /* XML Extensible Markup Language */
+ file_recovery_new->extension=extension_xml;
+ free(buf);
return 1;
}
-static int header_check_stl(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 1;
+ @ ensures file_recovery_new->file_stat == \null;
+ @ ensures file_recovery_new->handle == \null;
+ @ ensures file_recovery_new->extension == extension_ghx || file_recovery_new->extension == extension_xml;
+ @ ensures file_recovery_new->calculated_file_size == 0;
+ @ ensures file_recovery_new->file_size == 0;
+ @ ensures file_recovery_new->min_filesize == 0;
+ @ ensures (buffer_size >= 10) ==> (file_recovery_new->data_check == &data_check_xml_utf8);
+ @ ensures (buffer_size < 10) ==> file_recovery_new->data_check == \null;
+ @ ensures file_recovery_new->file_check == &file_check_xml;
+ @ ensures valid_read_string(file_recovery_new->extension);
+ @ ensures \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_xml_utf8(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 unsigned int buffer_size_test=(buffer_size < 512? buffer_size : 512);
- if(td_memmem(buffer, buffer_size_test, "facet normal", 12)==NULL)
- return 0;
- /* StereoLithography - STL Ascii format
- * http://www.ennex.com/~fabbers/StL.asp */
+ const char *tmp;
+ /* buffer may not be null-terminated */
+ char *buf=(char *)MALLOC(buffer_size+1);
+ memcpy(buf, buffer, buffer_size);
+ buf[buffer_size]='\0';
reset_file_recovery(file_recovery_new);
- file_recovery_new->data_check=&data_check_txt;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="stl";
+ if(buffer_size >= 10)
+ file_recovery_new->data_check=&data_check_xml_utf8;
+ file_recovery_new->extension=NULL;
+ tmp=strchr(buf,'<');
+ /*@
+ @ loop assigns tmp,file_recovery_new->extension;
+ @*/
+ while(tmp!=NULL && file_recovery_new->extension==NULL)
+ {
+ if(strncasecmp(tmp, "<Archive name=\"Root\">", 8)==0)
+ {
+ /* Grasshopper archive */
+ file_recovery_new->extension=extension_ghx;
+ }
+ tmp++;
+ tmp=strchr(tmp,'<');
+ }
+ if(file_recovery_new->extension==NULL)
+ {
+ file_recovery_new->extension=extension_xml;
+ }
+ file_recovery_new->file_check=&file_check_xml;
+ free(buf);
return 1;
}
-static int header_check_svg(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_xml);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_xml_utf16(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)
{
- /* Scalable Vector Graphics */
+ /* Avoid false positive with .sldprt */
+ if(file_recovery->file_stat!=NULL
+#if !defined(MAIN_txt)
+ && file_recovery->file_stat->file_hint==&file_hint_doc
+#endif
+ )
+ return 0;
reset_file_recovery(file_recovery_new);
- file_recovery_new->extension="svg";
- file_recovery_new->file_check=&file_check_svg;
+ file_recovery_new->extension=extension_xml;
return 1;
}
-static int header_check_snz(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)
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_fasttxt, buffer+(..), file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == extension_xmp);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_txt);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_xmp(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 unsigned int buffer_size_test=(buffer_size < 512? buffer_size : 512);
- const unsigned char *pos=(const unsigned char *)td_memmem(buffer, buffer_size_test, ".snz", 4);
- if(pos==NULL)
+ if(buffer[35]=='\0')
return 0;
+ if(file_recovery->file_stat!=NULL
+#if !defined(MAIN_txt)
+ && (file_recovery->file_stat->file_hint==&file_hint_jpg ||
+ file_recovery->file_stat->file_hint==&file_hint_pdf ||
+ file_recovery->file_stat->file_hint==&file_hint_tiff)
+#endif
+ )
+ return 0;
+ /* Adobe's Extensible Metadata Platform */
reset_file_recovery(file_recovery_new);
file_recovery_new->data_check=&data_check_txt;
file_recovery_new->file_check=&file_check_size;
- file_recovery_new->extension="snz";
- file_recovery_new->min_filesize=pos-buffer;
+ file_recovery_new->extension=extension_xmp;
return 1;
}
-static void register_header_check_snz(file_stat_t *file_stat)
-{
- register_header_check(0, "DEFAULT\n", 8, &header_check_snz, file_stat);
- register_header_check(0, "DEFAULT\r\n", 9, &header_check_snz, file_stat);
-}
-
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_fasttxt(file_stat_t *file_stat)
{
static const unsigned char header_xml_utf8[17] = {0xef, 0xbb, 0xbf, '<', '?', 'x', 'm', 'l', ' ', 'v', 'e', 'r', 's', 'i', 'o', 'n', '='};
@@ -1549,3 +2312,1815 @@ static void register_header_check_fasttxt(file_stat_t *file_stat)
register_header_check(0, "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\"", 35, &header_check_xmp, file_stat);
register_header_check(0, "<svg xmlns=\"http://www.w3.org/2000/svg\"", 39, &header_check_svg, file_stat);
}
+
+/*@
+ @ requires \valid(file_stat);
+ @*/
+static void register_header_check_snz(file_stat_t *file_stat)
+{
+ register_header_check(0, "DEFAULT\n", 8, &header_check_snz, file_stat);
+ register_header_check(0, "DEFAULT\r\n", 9, &header_check_snz, file_stat);
+}
+
+/*@
+ @ requires \valid(file_stat);
+ @*/
+static void register_header_check_txt(file_stat_t *file_stat)
+{
+ unsigned int i;
+ for(i=0; i<256; i++)
+ ascii_char[i]=i;
+ for(i=0; i<256; i++)
+ {
+ if(filtre(i) || i==0xE2 || i==0xC2 || i==0xC3 || i==0xC5 || i==0xC6 || i==0xCB)
+ register_header_check(0, &ascii_char[i], 1, &header_check_txt, file_stat);
+ }
+#ifdef UTF16
+ register_header_check(1, &ascii_char[0], 1, &header_check_le16_txt, file_stat);
+#endif
+}
+
+#if defined(MAIN_txt)
+#define BLOCKSIZE 65536u
+static int main_dc()
+{
+ const char fn[] = "recup_dir.1/f0000000.dc";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_dc(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert file_recovery_new.extension == extension_dc; */
+ /*@ assert valid_read_string(extension_dc); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == \null; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.extension == extension_dc; */
+ /*@ assert valid_read_string(extension_dc); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_dc(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_ers()
+{
+ const char fn[] = "recup_dir.1/f0000000.ers";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_ers(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert file_recovery_new.extension == extension_ers; */
+ /*@ assert valid_read_string(extension_ers); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_ers; */
+ /*@ assert file_recovery_new.file_rename == \null; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.extension == extension_ers; */
+ /*@ assert valid_read_string(extension_ers); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_ers(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_ers; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_ers(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_fasttxt()
+{
+ const char fn[] = "recup_dir.1/f0000000.txt";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_fasttxt(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ /*@ assert file_recovery_new.extension != \null; */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert valid_read_string((char *)file_recovery_new.extension); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == \null; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_fasttxt(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_html()
+{
+ const char fn[] = "recup_dir.1/f0000000.html";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_html(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert file_recovery_new.extension == extension_html; */
+ /*@ assert valid_read_string(extension_html); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_html; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == &file_rename_html; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_html; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_html(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_html; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_html(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.extension == extension_html; */
+ /*@ assert valid_read_string(extension_html); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_html(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ file_rename_html(&file_recovery_new);
+ return 0;
+}
+
+static int main_ics()
+{
+ const char fn[] = "recup_dir.1/f0000000.ics";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_ics(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert file_recovery_new.extension == extension_ics; */
+ /*@ assert valid_read_string(extension_ics); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.extension == extension_ics; */
+ /*@ assert valid_read_string(extension_ics); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_ics(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_mbox()
+{
+ const char fn[] = "recup_dir.1/f0000000.mbox";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_mbox(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert file_recovery_new.extension == extension_mbox; */
+ /*@ assert valid_read_string(extension_mbox); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.extension == extension_mbox; */
+ /*@ assert valid_read_string(extension_mbox); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_mbox(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_perlm()
+{
+ const char fn[] = "recup_dir.1/f0000000.pm";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_perlm(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_pm || file_recovery_new.extension == extension_java; */
+ /*@ assert valid_read_string((char *)file_recovery_new.extension); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_perlm(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_rtf()
+{
+ const char fn[] = "recup_dir.1/f0000000.rtf";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_rtf(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_rtf; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_rtf(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_smail()
+{
+ const char fn[] = "recup_dir.1/f0000000.smil";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_smil(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_smil; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_smil; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_smil(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_smil; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_smil(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_snz()
+{
+ const char fn[] = "recup_dir.1/f0000000.snz";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_snz;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_snz(&file_stats);
+#endif
+ if(header_check_snz(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == file_hint_snz.extension; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_snz; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_snz(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_stl()
+{
+ const char fn[] = "recup_dir.1/f0000000.stl";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_stl(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_stl; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_stl(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_svg()
+{
+ const char fn[] = "recup_dir.1/f0000000.svg";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_svg(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_svg; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_svg; */
+ /*@ assert file_recovery_new.data_check == \null; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_svg(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_svg; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_svg(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_thunderbird()
+{
+ const char fn[] = "recup_dir.1/f0000000.mbox";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ reset_file_recovery(&file_recovery_new);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_thunderbird(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string(extension_mbox); */
+ /*@ assert file_recovery_new.extension == extension_mbox; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string(extension_mbox); */
+ /*@ assert file_recovery_new.extension == extension_mbox; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_thunderbird(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_ttd()
+{
+ const char fn[] = "recup_dir.1/f0000000.ttd";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+// register_header_check_fasttxt(&file_stats);
+ if(header_check_ttd(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_ttd; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.data_check == &data_check_ttd; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_ttd; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_ttd(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_ttd(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_ttd(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_txt()
+{
+ const char fn[] = "recup_dir.1/f0000000.txt";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.extension == \null; */
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_txt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_txt(&file_stats);
+#endif
+ /*@ assert file_recovery.extension == \null; */
+ if(header_check_txt(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ /*@ assert file_recovery_new.extension != \null; */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert valid_read_string((char *)file_recovery_new.extension); */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.data_check == \null || file_recovery_new.data_check == &data_check_html || file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_check == &file_check_emlx || file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == \null || file_recovery_new.file_rename == &file_rename_html; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_txt; */
+ if(file_recovery_new.data_check != NULL)
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_html || file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=file_recovery_new.data_check(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ file_recovery_new.data_check(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_txt(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_emlx || file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_recovery_new.file_check(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ if(file_recovery_new.file_rename != NULL)
+ {
+ /*@ assert file_recovery_new.file_rename == &file_rename_html; */
+ file_rename_html(&file_recovery_new);
+ }
+ return 0;
+}
+
+static int main_vbm()
+{
+ const char fn[] = "recup_dir.1/f0000000.vbm";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_vbm(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_vbm; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_vbm; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_vbm(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_vbm; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_vbm(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_xml()
+{
+ const char fn[] = "recup_dir.1/f0000000.xml";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_xml(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_gpx ||
+ file_recovery_new.file_check == &file_check_svg ||
+ file_recovery_new.file_check == &file_check_xml; */
+ /*@ assert file_recovery_new.data_check == \null ||
+ file_recovery_new.data_check == &data_check_html ||
+ file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_rename == \null ||
+ file_recovery_new.file_rename == &file_rename_fods ||
+ file_recovery_new.file_rename == &file_rename_html;
+ */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ if(file_recovery_new.data_check != NULL)
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=file_recovery_new.data_check(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ file_recovery_new.data_check(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_xml(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ if(file_recovery_new.file_check != NULL)
+ {
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_recovery_new.file_check(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ }
+ if(file_recovery_new.file_rename!=NULL)
+ {
+ file_recovery_new.file_rename(&file_recovery_new);
+ }
+ return 0;
+}
+
+static int main_xml_utf8()
+{
+ const char fn[] = "recup_dir.1/f0000000.xml";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_xml_utf8(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_ghx || file_recovery_new.extension == extension_xml; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_xml; */
+ /*@ assert file_recovery_new.data_check == &data_check_xml_utf8; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_xml_utf8; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_xml_utf8(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_xml_utf8(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert file_recovery_new.file_check == &file_check_xml; */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_xml(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+static int main_xml_utf16()
+{
+ const char fn[] = "recup_dir.1/f0000000.xml";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_xml_utf16(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_xml; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == \null; */
+ /*@ assert file_recovery_new.data_check == \null; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_xml_utf16(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert file_recovery_new.file_check == \null; */
+ return 0;
+}
+
+static int main_xmp()
+{
+ const char fn[] = "recup_dir.1/f0000000.xmp";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ /*@ assert file_recovery.file_stat == \null; */
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_fasttxt;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+#if 0
+ register_header_check_fasttxt(&file_stats);
+#endif
+ if(header_check_xmp(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ file_recovery_new.file_stat=&file_stats;
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert file_recovery_new.extension == extension_xmp; */
+ /*@ assert file_recovery_new.calculated_file_size == 0; */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_stat->file_hint==&file_hint_fasttxt; */
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ /*@ assert file_recovery_new.data_check == &data_check_txt; */
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_txt(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ header_check_xmp(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ file_recovery_new.handle=fopen(fn, "rb");
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ return 0;
+}
+
+int main()
+{
+ main_dc();
+ main_ers();
+ main_fasttxt();
+ main_html();
+ main_ics();
+ main_mbox();
+ main_perlm();
+ main_rtf();
+ main_smail();
+ main_snz();
+ main_stl();
+ main_svg();
+ main_thunderbird();
+ main_ttd();
+ main_txt();
+ main_vbm();
+ main_xml();
+ main_xml_utf8();
+ main_xml_utf16();
+ main_xmp();
+ return 0;
+}
+#endif
diff --git a/src/file_txt.h b/src/file_txt.h
index 127f96f..b1a6641 100644
--- a/src/file_txt.h
+++ b/src/file_txt.h
@@ -19,5 +19,10 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-int UTF2Lat(unsigned char *buffer_lower, const unsigned char *buffer, const int buf_len);
-
+/*@
+ @ requires buf_len> 0;
+ @ requires \valid_read(buffer+(0..buf_len-1));
+ @ ensures 0 <= \result <= buf_len;
+ @ assigns \nothing;
+ @*/
+int UTFsize(const unsigned char *buffer, const unsigned int buf_len);
diff --git a/src/file_win.c b/src/file_win.c
index 4db35b6..9e8b726 100644
--- a/src/file_win.c
+++ b/src/file_win.c
@@ -49,19 +49,16 @@ const file_hint_t file_hint_win= {
static data_check_t data_check_win(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
unsigned int i;
- char *buffer_lower=(char *)MALLOC(buffer_size+16);
unsigned int offset=0;
if(file_recovery->calculated_file_size==0)
offset=3;
- i=UTF2Lat((unsigned char*)buffer_lower, &buffer[buffer_size/2+offset], buffer_size/2-offset);
+ i=UTFsize(&buffer[buffer_size/2+offset], buffer_size/2-offset);
if(i<buffer_size/2-offset)
{
if(i>=10)
file_recovery->calculated_file_size=file_recovery->file_size+offset+i;
- free(buffer_lower);
return DC_STOP;
}
- free(buffer_lower);
file_recovery->calculated_file_size=file_recovery->file_size+(buffer_size/2);
return DC_CONTINUE;
}
diff --git a/src/file_wmf.c b/src/file_wmf.c
index e0a5d17..554fdca 100644
--- a/src/file_wmf.c
+++ b/src/file_wmf.c
@@ -55,37 +55,67 @@ struct wmf_header
uint16_t members;
} __attribute__ ((gcc_struct, __packed__));
-static int header_check_wmf(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)
+struct wmf_placeable_record
+{
+ uint32_t key;
+ uint16_t hwmf;
+ uint64_t boundingbox;
+ uint16_t inch;
+ uint32_t reserved;
+ uint16_t checksum;
+} __attribute__ ((gcc_struct, __packed__));
+
+static uint64_t wmf_check_meta_header(const struct wmf_header *hdr)
{
- const struct wmf_header *hdr=(const struct wmf_header *)buffer;
- if(le16(hdr->num_objects)==0)
+ const uint64_t size=2*le32(hdr->size);
+ const unsigned int num_objects=le16(hdr->num_objects);
+ const unsigned int max_record=le32(hdr->max_record);
+ if(size < sizeof(struct wmf_header))
return 0;
- if(2*le32(hdr->max_record) + le16(hdr->num_objects) - 1 >= 2*le32(hdr->size))
+ if(num_objects==0)
+ return 0;
+ if(2*max_record + num_objects - 1 >= size)
+ return 0;
+ return size;
+}
+
+static int header_check_wmf(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 size=wmf_check_meta_header((const struct wmf_header *)buffer);
+ if(size==0)
return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_wmf.extension;
- file_recovery_new->calculated_file_size=(uint64_t)2*le32(hdr->size);
+ file_recovery_new->calculated_file_size=size;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
return 1;
}
-static int header_check_other_wmf(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)
+static int header_check_wmf_placeable(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)
{
- if(buffer[0x10]!=0 || buffer[0x11]!=0)
+ const struct wmf_placeable_record *meta=(const struct wmf_placeable_record *)buffer;
+ const struct wmf_header *hdr=(const struct wmf_header *)&buffer[0x16];
+ uint64_t size;
+ /* Check META_PLACEABLE */
+ if(le32(meta->reserved) != 0)
+ return 0;
+ size=wmf_check_meta_header(hdr);
+ if(size==0)
return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_wmf.extension;
+ file_recovery_new->calculated_file_size=0x16+size;
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
return 1;
}
static void register_header_check_wmf(file_stat_t *file_stat)
{
static const unsigned char apm_header[6] = { 0xd7, 0xcd, 0xc6, 0x9a, 0x00, 0x00 };
- static const unsigned char emf_header[6] = { 0x20, 0x45, 0x4D, 0x46, 0x00, 0x00 };
/* WMF: file_type=disk, header size=9, version=3.0 */
static const unsigned char wmf_header[6] = { 0x01, 0x00, 0x09, 0x00, 0x00, 0x03 };
- register_header_check(0, apm_header,sizeof(apm_header), &header_check_other_wmf, file_stat);
- register_header_check(0, emf_header,sizeof(emf_header), &header_check_other_wmf, file_stat);
+ register_header_check(0, apm_header,sizeof(apm_header), &header_check_wmf_placeable, file_stat);
register_header_check(0, wmf_header,sizeof(wmf_header), &header_check_wmf, file_stat);
}
diff --git a/src/file_zip.c b/src/file_zip.c
index 417bd3d..b6439cd 100644
--- a/src/file_zip.c
+++ b/src/file_zip.c
@@ -46,10 +46,7 @@
extern const file_hint_t file_hint_doc;
#endif
static void register_header_check_zip(file_stat_t *file_stat);
-static int header_check_zip(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);
-static void file_check_zip(file_recovery_t *file_recovery);
static unsigned int pos_in_mem(const unsigned char *haystack, const unsigned int haystack_size, const unsigned char *needle, const unsigned int needle_size);
-static void file_rename_zip(file_recovery_t *file_recovery);
static char first_filename[256];
const file_hint_t file_hint_zip= {
@@ -61,6 +58,35 @@ const file_hint_t file_hint_zip= {
.register_header_check=&register_header_check_zip
};
+static const char *extension_apk="apk";
+static const char *extension_celtx="celtx";
+static const char *extension_docx="docx";
+static const char *extension_epub="epub";
+static const char *extension_jar="jar";
+static const char *extension_kmz="kmz";
+static const char *extension_kra="kra";
+static const char *extension_mmap="mmap";
+static const char *extension_notebook="notebook";
+static const char *extension_numbers="numbers";
+static const char *extension_odg="odg";
+static const char *extension_odp="odp";
+static const char *extension_ods="ods";
+static const char *extension_odt="odt";
+static const char *extension_ora="ora";
+static const char *extension_pages="pages";
+static const char *extension_pptx="pptx";
+static const char *extension_sh3d="sh3d";
+static const char *extension_sketch="sketch";
+static const char *extension_sxc="sxc";
+static const char *extension_sxd="sxd";
+static const char *extension_sxi="sxi";
+static const char *extension_sxw="sxw";
+static const char *extension_vsdx="vsdx";
+static const char *extension_xd="xd";
+static const char *extension_xlsx="xlsx";
+static const char *extension_xpi="xpi";
+static const char *extension_xrns="xrns";
+
static const unsigned char zip_header[4] = { 'P', 'K', 0x03, 0x04};
#define ZIP_CENTRAL_DIR 0x02014B50
#define ZIP_FILE_ENTRY 0x04034B50
@@ -86,8 +112,8 @@ struct zip_file_entry {
uint16_t unused1:2; /** Unused */
uint16_t compression; /** Compression method */
- uint16_t last_mod_time; /** Last moditication file time */
- uint16_t last_mod_date; /** Last moditication file date */
+ uint16_t last_mod_time; /** Last modification file time */
+ uint16_t last_mod_date; /** Last modification file date */
uint32_t crc32; /** CRC32 */
uint32_t compressed_size; /** Compressed size */
uint32_t uncompressed_size; /** Uncompressed size */
@@ -139,29 +165,35 @@ static int64_t file_get_pos(FILE *f, const void* needle, const unsigned int size
if(read_size >= size)
{
/*@ assert read_size >= size; */
+ const unsigned int count_max=read_size - size;
unsigned int count = 0;
+ // TODO loop invariant 0 <= count <= count_max + 1;
/*@
- @ loop invariant 0 <= count <= read_size - size + 1;
- @ loop variant read_size - size - count;
+ @ loop variant count_max - count;
@*/
- for(count=0; count <= read_size - size; count++)
+ for(count=0; count <= count_max; count++)
{
+ /*@ assert count <= count_max; */
if (buffer[count]==*(const char *)needle && memcmp(buffer+count, needle, size)==0)
{
free(buffer);
if(my_fseek(f, (off_t)count-(off_t)read_size, SEEK_CUR)<0)
{
+#if !defined(__FRAMAC__)
log_trace("zip: file_get_pos count-read failed\n");
+#endif
return -1;
}
return total+count;
}
}
- total+=count;
+ total+=count_max+1;
}
if(feof(f) || my_fseek(f, (off_t)1-size, SEEK_CUR)<0)
{
+#if !defined(__FRAMAC__)
log_trace("zip: file_get_pos 1-size failed\n");
+#endif
free(buffer);
return -1;
}
@@ -170,6 +202,7 @@ static int64_t file_get_pos(FILE *f, const void* needle, const unsigned int size
return -1;
}
+#ifndef __FRAMAC__
/*@
@ requires \valid(fr);
@ requires \valid(fr->handle);
@@ -177,6 +210,66 @@ static int64_t file_get_pos(FILE *f, const void* needle, const unsigned int size
@ requires \valid(krita);
@ requires fr->file_size < 0x8000000000000000 - 65535;
@ requires 0 < len <= 65535;
+ @ requires *ext == \null ||
+ *ext == extension_apk ||
+ *ext == extension_celtx ||
+ *ext == extension_docx ||
+ *ext == extension_epub ||
+ *ext == extension_jar ||
+ *ext == extension_kmz ||
+ *ext == extension_kra ||
+ *ext == extension_mmap ||
+ *ext == extension_notebook ||
+ *ext == extension_numbers ||
+ *ext == extension_odg ||
+ *ext == extension_odp ||
+ *ext == extension_ods ||
+ *ext == extension_odt ||
+ *ext == extension_ora ||
+ *ext == extension_pages ||
+ *ext == extension_pptx ||
+ *ext == extension_sh3d ||
+ *ext == extension_sketch ||
+ *ext == extension_sxc ||
+ *ext == extension_sxd ||
+ *ext == extension_sxi ||
+ *ext == extension_sxw ||
+ *ext == extension_vsdx ||
+ *ext == extension_xd ||
+ *ext == extension_xlsx ||
+ *ext == extension_xpi ||
+ *ext == extension_xrns ||
+ *ext == file_hint_zip.extension;
+ @ ensures *ext == \null ||
+ *ext == extension_apk ||
+ *ext == extension_celtx ||
+ *ext == extension_docx ||
+ *ext == extension_epub ||
+ *ext == extension_jar ||
+ *ext == extension_kmz ||
+ *ext == extension_kra ||
+ *ext == extension_mmap ||
+ *ext == extension_notebook ||
+ *ext == extension_numbers ||
+ *ext == extension_odg ||
+ *ext == extension_odp ||
+ *ext == extension_ods ||
+ *ext == extension_odt ||
+ *ext == extension_ora ||
+ *ext == extension_pages ||
+ *ext == extension_pptx ||
+ *ext == extension_sh3d ||
+ *ext == extension_sketch ||
+ *ext == extension_sxc ||
+ *ext == extension_sxd ||
+ *ext == extension_sxi ||
+ *ext == extension_sxw ||
+ *ext == extension_vsdx ||
+ *ext == extension_xd ||
+ *ext == extension_xlsx ||
+ *ext == extension_xpi ||
+ *ext == extension_xrns ||
+ *ext == file_hint_zip.extension;
@ ensures fr->file_size < 0x8000000000000000;
@ ensures \result == -1 || \result == 0;
@ ensures *krita==0 || *krita==19;
@@ -242,7 +335,7 @@ static int zip_parse_file_entry_fn(file_recovery_t *fr, const char **ext, const
return -1;
}
#if defined(__FRAMAC__)
- Frama_C_make_unknown(buffer, 128);
+ Frama_C_make_unknown((char *)buffer, 128);
#endif
if (my_fseek(fr->handle, -to_read, SEEK_CUR) < 0)
{
@@ -251,59 +344,59 @@ static int zip_parse_file_entry_fn(file_recovery_t *fr, const char **ext, const
return -1;
}
if(compressed_size==16 && memcmp(buffer,"image/openraster",16)==0)
- *ext="ora";
+ *ext=extension_ora;
else if(compressed_size==20 && memcmp(buffer,"application/epub+zip",20)==0)
- *ext="epub";
+ *ext=extension_epub;
else if(compressed_size==28 && memcmp(buffer,"application/vnd.sun.xml.calc",28)==0)
- *ext="sxc";
+ *ext=extension_sxc;
else if(compressed_size==28 && memcmp(buffer,"application/vnd.sun.xml.draw",28)==0)
- *ext="sxd";
+ *ext=extension_sxd;
else if(compressed_size==31 && memcmp(buffer,"application/vnd.sun.xml.impress",31)==0)
- *ext="sxi";
+ *ext=extension_sxi;
else if(compressed_size==30 && memcmp(buffer,"application/vnd.sun.xml.writer",30)==0)
- *ext="sxw";
+ *ext=extension_sxw;
else if(compressed_size==39 && memcmp(buffer,"application/vnd.oasis.opendocument.text",39)==0)
- *ext="odt";
+ *ext=extension_odt;
else if(compressed_size==43 && memcmp(buffer,"application/vnd.oasis.opendocument.graphics",43)==0)
- *ext="odg";
+ *ext=extension_odg;
else if(compressed_size==46 && memcmp(buffer,"application/vnd.oasis.opendocument.spreadsheet",46)==0)
- *ext="ods";
+ *ext=extension_ods;
else if(compressed_size==47 && memcmp(buffer,"application/vnd.oasis.opendocument.presentation",47)==0)
- *ext="odp";
+ *ext=extension_odp;
else if(memcmp(buffer,"application/x-krita",19)==0)
{
- *ext="kra";
+ *ext=extension_kra;
*krita=19;
}
else
{ /* default to writer */
- *ext="sxw";
+ *ext=extension_sxw;
}
}
/* Zipped Keyhole Markup Language (KML) used by Google Earth */
else if(len==7 && memcmp(filename, "doc.kml", 7)==0)
- *ext="kmz";
+ *ext=extension_kmz;
else if(len==4 && memcmp(filename, "Home", 4)==0)
sh3d=1;
/* Celtx, Screenwriting & Media Pre-production file */
else if(len==9 && memcmp(filename, "local.rdf", 9)==0)
- *ext="celtx";
+ *ext=extension_celtx;
else if(len==13 && memcmp(filename, "document.json", 13)==0)
- *ext="sketch";
+ *ext=extension_sketch;
}
else if(file_nbr==1 && sh3d==1)
{
if(len==1 && filename[0]=='0')
- *ext="sh3d";
+ *ext=extension_sh3d;
}
if(strncmp(filename, "word/", 5)==0)
- ext_msoffice="docx";
+ ext_msoffice=extension_docx;
else if(strncmp(filename, "xl/", 3)==0)
- ext_msoffice="xlsx";
+ ext_msoffice=extension_xlsx;
else if(strncmp(filename, "ppt/", 4)==0)
- ext_msoffice="pptx";
+ ext_msoffice=extension_pptx;
else if(strncmp(filename, "visio/", 6)==0)
- ext_msoffice="vsdx";
+ ext_msoffice=extension_vsdx;
if(msoffice && ext_msoffice!=NULL)
*ext=ext_msoffice;
}
@@ -311,31 +404,93 @@ static int zip_parse_file_entry_fn(file_recovery_t *fr, const char **ext, const
{
/* iWork */
if(len==23 && memcmp(filename, "QuickLook/Thumbnail.jpg", 23)==0)
- *ext="pages";
+ *ext=extension_pages;
else if(len==20 && strncasecmp(filename, "META-INF/MANIFEST.MF", 20)==0)
- *ext="jar";
+ *ext=extension_jar;
else if(len==15 && strncasecmp(filename, "chrome.manifest", 15)==0)
- *ext="xpi";
+ *ext=extension_xpi;
/* SMART Notebook */
else if(len==15 && memcmp(filename, "imsmanifest.xml", 15)==0)
- *ext="notebook";
+ *ext=extension_notebook;
/* Apple Numbers */
else if(len==18 && memcmp(filename, "Index/Document.iwa", 18)==0)
- *ext="numbers";
+ *ext=extension_numbers;
else if(len==19 && memcmp(filename, "AndroidManifest.xml", 19)==0)
- *ext="apk";
+ *ext=extension_apk;
else if(len==30 && memcmp(filename, "xsd/MindManagerApplication.xsd", 30)==0)
- *ext="mmap";
+ *ext=extension_mmap;
}
free(filename);
return 0;
}
+#endif
/*@
@ requires \valid(fr);
@ requires \valid(fr->handle);
@ requires \valid(ext);
@ requires fr->file_size < 0x8000000000000000 + 4;
+ @ requires \separated(fr, ext);
+ @ requires *ext == \null ||
+ *ext == extension_apk ||
+ *ext == extension_celtx ||
+ *ext == extension_docx ||
+ *ext == extension_epub ||
+ *ext == extension_jar ||
+ *ext == extension_kmz ||
+ *ext == extension_kra ||
+ *ext == extension_mmap ||
+ *ext == extension_notebook ||
+ *ext == extension_numbers ||
+ *ext == extension_odg ||
+ *ext == extension_odp ||
+ *ext == extension_ods ||
+ *ext == extension_odt ||
+ *ext == extension_ora ||
+ *ext == extension_pages ||
+ *ext == extension_pptx ||
+ *ext == extension_sh3d ||
+ *ext == extension_sketch ||
+ *ext == extension_sxc ||
+ *ext == extension_sxd ||
+ *ext == extension_sxi ||
+ *ext == extension_sxw ||
+ *ext == extension_vsdx ||
+ *ext == extension_xd ||
+ *ext == extension_xlsx ||
+ *ext == extension_xpi ||
+ *ext == extension_xrns ||
+ *ext == file_hint_zip.extension;
+ @ ensures *ext == \null ||
+ *ext == extension_apk ||
+ *ext == extension_celtx ||
+ *ext == extension_docx ||
+ *ext == extension_epub ||
+ *ext == extension_jar ||
+ *ext == extension_kmz ||
+ *ext == extension_kra ||
+ *ext == extension_mmap ||
+ *ext == extension_notebook ||
+ *ext == extension_numbers ||
+ *ext == extension_odg ||
+ *ext == extension_odp ||
+ *ext == extension_ods ||
+ *ext == extension_odt ||
+ *ext == extension_ora ||
+ *ext == extension_pages ||
+ *ext == extension_pptx ||
+ *ext == extension_sh3d ||
+ *ext == extension_sketch ||
+ *ext == extension_sxc ||
+ *ext == extension_sxd ||
+ *ext == extension_sxi ||
+ *ext == extension_sxw ||
+ *ext == extension_vsdx ||
+ *ext == extension_xd ||
+ *ext == extension_xlsx ||
+ *ext == extension_xpi ||
+ *ext == extension_xrns ||
+ *ext == file_hint_zip.extension;
@*/
static int zip_parse_file_entry(file_recovery_t *fr, const char **ext, const unsigned int file_nbr)
{
@@ -379,8 +534,10 @@ static int zip_parse_file_entry(file_recovery_t *fr, const char **ext, const uns
if (len)
{
/*@ assert 0 < len <= 65535; */
+#ifndef __FRAMAC__
if(zip_parse_file_entry_fn(fr, ext, file_nbr, file, len, &krita) < 0)
return -1;
+#endif
/*@ assert fr->file_size < 0x8000000000000000; */
}
/*@ assert fr->file_size < 0x8000000000000000; */
@@ -755,6 +912,7 @@ static int zip64_parse_end_central_dir_locator(file_recovery_t *fr)
/*@
@ requires \valid(fr);
@ requires \valid(fr->handle);
+ @ requires fr->file_check==&file_check_zip;
@*/
static void file_check_zip(file_recovery_t *fr)
{
@@ -763,6 +921,8 @@ static void file_check_zip(file_recovery_t *fr)
fr->file_size = 0;
fr->offset_error=0;
fr->offset_ok=0;
+ /* fr->time is already set to 0 but it helps frama-c */
+ fr->time=0;
first_filename[0]='\0';
if(my_fseek(fr->handle, 0, SEEK_SET) < 0)
return ;
@@ -851,23 +1011,31 @@ static void file_check_zip(file_recovery_t *fr)
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_zip;
@*/
+/* TODO ensures valid_read_string((char*)file_recovery->filename); */
static void file_rename_zip(file_recovery_t *file_recovery)
{
const char *ext=NULL;
unsigned int file_nbr=0;
file_recovery_t fr;
reset_file_recovery(&fr);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
if((fr.handle=fopen(file_recovery->filename, "rb"))==NULL)
+ {
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
+ }
fr.file_size = 0;
fr.offset_error=0;
first_filename[0]='\0';
if(my_fseek(fr.handle, 0, SEEK_SET) < 0)
{
fclose(fr.handle);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return ;
}
+ /*@ loop invariant valid_read_string((char*)file_recovery->filename); */
while (1)
{
uint32_t header;
@@ -875,6 +1043,7 @@ static void file_rename_zip(file_recovery_t *file_recovery)
if(file_nbr>=0xffffffff || fr.file_size >= 0x8000000000000000 - 4)
{
fclose(fr.handle);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
}
/*@ assert fr.file_size < 0x8000000000000000 - 4; */
@@ -885,6 +1054,7 @@ static void file_rename_zip(file_recovery_t *file_recovery)
log_trace("Failed to read block header\n");
#endif
fclose(fr.handle);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
}
#if defined(__FRAMAC__)
@@ -921,7 +1091,9 @@ static void file_rename_zip(file_recovery_t *file_recovery)
if(ext!=NULL)
{
fclose(fr.handle);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
file_rename(file_recovery, NULL, 0, 0, ext, 1);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
}
break;
@@ -943,6 +1115,7 @@ static void file_rename_zip(file_recovery_t *file_recovery)
if (status<0)
{
fclose(fr.handle);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
}
/* Only end of central dir is end of archive, 64b version of it is before */
@@ -956,7 +1129,9 @@ static void file_rename_zip(file_recovery_t *file_recovery)
first_filename[len]!='/' &&
first_filename[len]!='\\';
len++);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
file_rename(file_recovery, first_filename, len, 0, "zip", 0);
+ /*@ assert valid_read_string((char*)file_recovery->filename); */
return;
}
}
@@ -966,14 +1141,43 @@ static void file_rename_zip(file_recovery_t *file_recovery)
@ requires buffer_size >= 85;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->extension);
@ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_zip, file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 21);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 30);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
@ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_zip || file_recovery_new->file_check == \null);
@ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_zip || file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_zip.extension ||
+ file_recovery_new->extension == extension_docx ||
+ file_recovery_new->extension == extension_epub ||
+ file_recovery_new->extension == extension_kra ||
+ file_recovery_new->extension == extension_numbers ||
+ file_recovery_new->extension == extension_odg ||
+ file_recovery_new->extension == extension_odp ||
+ file_recovery_new->extension == extension_ods ||
+ file_recovery_new->extension == extension_odt ||
+ file_recovery_new->extension == extension_ora ||
+ file_recovery_new->extension == extension_pptx ||
+ file_recovery_new->extension == extension_sh3d ||
+ file_recovery_new->extension == extension_sxc ||
+ file_recovery_new->extension == extension_sxd ||
+ file_recovery_new->extension == extension_sxi ||
+ file_recovery_new->extension == extension_sxw ||
+ file_recovery_new->extension == extension_vsdx ||
+ file_recovery_new->extension == extension_xd ||
+ file_recovery_new->extension == extension_xlsx ||
+ file_recovery_new->extension == extension_xrns );
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_zip(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)
{
@@ -982,6 +1186,10 @@ static int header_check_zip(const unsigned char *buffer, const unsigned int buff
#ifdef DEBUG_ZIP
log_trace("header_check_zip\n");
#endif
+ if(len==0 || len > 4096)
+ return 0;
+ if(le16(file->version) < 10)
+ return 0;
#ifndef MAIN_zip
if(file_recovery->file_stat!=NULL &&
file_recovery->file_stat->file_hint==&file_hint_doc)
@@ -1000,63 +1208,63 @@ static int header_check_zip(const unsigned char *buffer, const unsigned int buff
return 0;
}
reset_file_recovery(file_recovery_new);
- file_recovery_new->min_filesize=21;
+ file_recovery_new->min_filesize=30; /* 4+sizeof(file) == 30 */
file_recovery_new->file_check=&file_check_zip;
if(len==8 && memcmp(&buffer[30],"mimetype",8)==0)
{
const unsigned int compressed_size=le32(file->compressed_size);
/* Mypaint .ora */
if(compressed_size==16 && memcmp(&buffer[38],"image/openraster",16)==0)
- file_recovery_new->extension="ora";
+ file_recovery_new->extension=extension_ora;
else if(compressed_size==20 && memcmp(&buffer[38],"application/epub+zip",20)==0)
- file_recovery_new->extension="epub";
+ file_recovery_new->extension=extension_epub;
else if(compressed_size==28 && memcmp(&buffer[38],"application/vnd.sun.xml.calc",28)==0)
- file_recovery_new->extension="sxc";
+ file_recovery_new->extension=extension_sxc;
else if(compressed_size==28 && memcmp(&buffer[38],"application/vnd.sun.xml.draw",28)==0)
- file_recovery_new->extension="sxd";
+ file_recovery_new->extension=extension_sxd;
else if(compressed_size==31 && memcmp(&buffer[38],"application/vnd.sun.xml.impress",31)==0)
- file_recovery_new->extension="sxi";
+ file_recovery_new->extension=extension_sxi;
else if(compressed_size==30 && memcmp(&buffer[38],"application/vnd.sun.xml.writer",30)==0)
- file_recovery_new->extension="sxw";
+ file_recovery_new->extension=extension_sxw;
else if(compressed_size==39 && memcmp(&buffer[38],"application/vnd.oasis.opendocument.text",39)==0)
- file_recovery_new->extension="odt";
+ file_recovery_new->extension=extension_odt;
else if(compressed_size==43 && memcmp(&buffer[38],"application/vnd.oasis.opendocument.graphics",43)==0)
- file_recovery_new->extension="odg";
+ file_recovery_new->extension=extension_odg;
else if(compressed_size==45 && memcmp(&buffer[38],"application/vnd.adobe.sparkler.project+dcxucf",45)==0)
- file_recovery_new->extension="xd";
+ file_recovery_new->extension=extension_xd;
else if(compressed_size==46 && memcmp(&buffer[38],"application/vnd.oasis.opendocument.spreadsheet",46)==0)
- file_recovery_new->extension="ods";
+ file_recovery_new->extension=extension_ods;
else if(compressed_size==47 && memcmp(&buffer[38],"application/vnd.oasis.opendocument.presentation",47)==0)
- file_recovery_new->extension="odp";
+ file_recovery_new->extension=extension_odp;
else if(memcmp(&buffer[38],"application/x-krita",19)==0)
- file_recovery_new->extension="kra";
+ file_recovery_new->extension=extension_kra;
else
{ /* default to writer */
- file_recovery_new->extension="sxw";
+ file_recovery_new->extension=extension_sxw;
}
}
else if(len==19 && memcmp(&buffer[30],"[Content_Types].xml",19)==0)
{
if(pos_in_mem(&buffer[0], buffer_size, (const unsigned char*)"word/", 5)!=0)
- file_recovery_new->extension="docx";
+ file_recovery_new->extension=extension_docx;
else if(pos_in_mem(&buffer[0], 2000, (const unsigned char*)"xl/", 3)!=0)
- file_recovery_new->extension="xlsx";
+ file_recovery_new->extension=extension_xlsx;
else if(pos_in_mem(&buffer[0], buffer_size, (const unsigned char*)"ppt/", 4)!=0)
- file_recovery_new->extension="pptx";
+ file_recovery_new->extension=extension_pptx;
else if(pos_in_mem(&buffer[0], buffer_size, (const unsigned char*)"visio/", 6)!=0)
- file_recovery_new->extension="vsdx";
+ file_recovery_new->extension=extension_vsdx;
else
- file_recovery_new->extension="docx";
+ file_recovery_new->extension=extension_docx;
file_recovery_new->file_rename=&file_rename_zip;
}
/* Extended Renoise song file */
else if(len==8 && memcmp(&buffer[30], "Song.xml", 8)==0)
- file_recovery_new->extension="xrns";
+ file_recovery_new->extension=extension_xrns;
else if(len==4 && memcmp(&buffer[30], "Home", 4)==0)
- file_recovery_new->extension="sh3d";
+ file_recovery_new->extension=extension_sh3d;
/* Apple Numbers */
else if(len==18 && memcmp(&buffer[30], "Index/Document.iwa", 18)==0)
- file_recovery_new->extension="numbers";
+ file_recovery_new->extension=extension_numbers;
else
{
file_recovery_new->extension=file_hint_zip.extension;
@@ -1072,7 +1280,7 @@ static int header_check_zip(const unsigned char *buffer, const unsigned int buff
@ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_zip, file_recovery, file_recovery_new);
@ ensures \result == 1;
@ ensures file_recovery_new->file_check == &file_check_zip;
@ ensures file_recovery_new->extension == file_hint_zip.extension;
@@ -1125,7 +1333,6 @@ int main()
{
const char fn[] = "recup_dir.1/f0000000.zip";
unsigned char buffer[BLOCKSIZE];
- int res;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
file_stat_t file_stats;
@@ -1140,6 +1347,7 @@ int main()
file_recovery.blocksize=BLOCKSIZE;
file_recovery_new.blocksize=BLOCKSIZE;
file_recovery_new.data_check=NULL;
+ file_recovery_new.extension=NULL;
file_recovery_new.file_stat=NULL;
file_recovery_new.file_check=NULL;
file_recovery_new.file_rename=NULL;
@@ -1153,13 +1361,15 @@ int main()
register_header_check_zip(&file_stats);
if(header_check_zip(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
return 0;
+ /*@ assert valid_read_string(file_recovery_new.extension); */
/*@ assert valid_read_string((char *)&fn); */
memcpy(file_recovery_new.filename, fn, sizeof(fn));
file_recovery_new.file_stat=&file_stats;
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
- /*@ assert file_recovery_new.min_filesize == 21; */
+ /*@ assert file_recovery_new.min_filesize == 30; */
/*@ assert file_recovery_new.file_check == &file_check_zip || file_recovery_new.file_check == \null; */
/*@ assert file_recovery_new.file_stat->file_hint!=NULL; */
+ /*@ assert file_recovery_new.time == 0; */
{
file_recovery_t file_recovery_new2;
file_recovery_new2.blocksize=BLOCKSIZE;
@@ -1167,18 +1377,43 @@ int main()
file_recovery_new2.file_check=NULL;
file_recovery_new2.location.start=BLOCKSIZE;
file_recovery_new.handle=NULL; /* In theory should be not null */
+ /*@ assert file_recovery_new.extension == file_hint_zip.extension ||
+ file_recovery_new.extension == extension_docx ||
+ file_recovery_new.extension == extension_epub ||
+ file_recovery_new.extension == extension_kra ||
+ file_recovery_new.extension == extension_numbers ||
+ file_recovery_new.extension == extension_odg ||
+ file_recovery_new.extension == extension_odp ||
+ file_recovery_new.extension == extension_ods ||
+ file_recovery_new.extension == extension_odt ||
+ file_recovery_new.extension == extension_ora ||
+ file_recovery_new.extension == extension_pptx ||
+ file_recovery_new.extension == extension_sh3d ||
+ file_recovery_new.extension == extension_sxc ||
+ file_recovery_new.extension == extension_sxd ||
+ file_recovery_new.extension == extension_sxi ||
+ file_recovery_new.extension == extension_sxw ||
+ file_recovery_new.extension == extension_vsdx ||
+ file_recovery_new.extension == extension_xd ||
+ file_recovery_new.extension == extension_xlsx ||
+ file_recovery_new.extension == extension_xrns; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
#if defined(__FRAMAC__)
Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
#endif
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
header_check_zip(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
}
+ /*@ assert file_recovery_new.time == 0; */
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
file_recovery_new.handle=fopen(fn, "rb");
if(file_recovery_new.handle!=NULL && file_recovery_new.file_check !=NULL)
{
/*@ assert file_recovery_new.file_check == &file_check_zip; */
+ /*@ assert file_recovery_new.time == 0; */
file_check_zip(&file_recovery_new);
fclose(file_recovery_new.handle);
}
diff --git a/src/filegen.c b/src/filegen.c
index c197b5e..1c3117f 100644
--- a/src/filegen.c
+++ b/src/filegen.c
@@ -23,6 +23,12 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_FTELLO
+#undef HAVE_FSEEKO
+#endif
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -39,6 +45,9 @@
#include "common.h"
#include "filegen.h"
#include "log.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
static file_check_t file_check_plist={
.list = TD_LIST_HEAD_INIT(file_check_plist.list)
@@ -48,13 +57,21 @@ file_check_list_t file_check_list={
.list = TD_LIST_HEAD_INIT(file_check_list.list)
};
-static unsigned int index_header_check(void);
+uint64_t gpls_nbr=0;
+/*@
+ @ requires \valid_read(a);
+ @ requires \valid_read(b);
+ @ assigns \nothing;
+ @*/
static int file_check_cmp(const struct td_list_head *a, const struct td_list_head *b)
{
const file_check_t *fc_a=td_list_entry_const(a, const file_check_t, list);
const file_check_t *fc_b=td_list_entry_const(b, const file_check_t, list);
int res;
+ unsigned int min_length;
+ /*@ assert \valid_read(fc_a); */
+ /*@ assert \valid_read(fc_b); */
if(fc_a->length==0 && fc_b->length!=0)
return -1;
if(fc_a->length!=0 && fc_b->length==0)
@@ -62,23 +79,44 @@ static int file_check_cmp(const struct td_list_head *a, const struct td_list_hea
res=fc_a->offset-fc_b->offset;
if(res!=0)
return res;
- res=memcmp(fc_a->value,fc_b->value, (fc_a->length<=fc_b->length?fc_a->length:fc_b->length));
+ /*@ assert \valid_read((char *)fc_a->value + (0 .. fc_a->length - 1)); */
+ /*@ assert \initialized((char *)fc_a->value + (0 .. fc_a->length - 1)); */
+#if 0
+ /*@ assert \valid_read((char *)fc_b->value + (0 .. fc_b->length - 1)); */
+ /*@ assert \initialized((char *)fc_b->value + (0 .. fc_b->length - 1)); */
+#endif
+ min_length=fc_a->length<=fc_b->length?fc_a->length:fc_b->length;
+ res=memcmp(fc_a->value,fc_b->value, min_length);
if(res!=0)
return res;
return (int)fc_b->length-(int)fc_a->length;
}
+/*@
+ @ requires \valid(file_check_new);
+ @ requires \valid(pos);
+ @*/
static void file_check_add_tail(file_check_t *file_check_new, file_check_list_t *pos)
{
unsigned int i;
+ const unsigned int tmp=(file_check_new->length==0?0:((const unsigned char *)file_check_new->value)[0]);
file_check_list_t *newe=(file_check_list_t *)MALLOC(sizeof(*newe));
newe->offset=file_check_new->offset;
+ /*@
+ @ loop unroll 256;
+ @ loop invariant 0 <= i <= 256;
+ @ loop assigns i, newe->file_checks[0 .. 255].list.prev, newe->file_checks[0 .. 255].list.next;
+ @ loop variant 255-i;
+ @*/
for(i=0;i<256;i++)
{
newe->file_checks[i].list.prev=&newe->file_checks[i].list;
newe->file_checks[i].list.next=&newe->file_checks[i].list;
+ /*@ assert newe->file_checks[i].list.prev == &newe->file_checks[i].list; */
+ /*@ assert newe->file_checks[i].list.next == &newe->file_checks[i].list; */
}
- td_list_add_tail(&file_check_new->list, &newe->file_checks[file_check_new->length==0?0:((const unsigned char *)file_check_new->value)[0]].list);
+ /*@ assert newe->file_checks[tmp].list.prev == &newe->file_checks[tmp].list; */
+ td_list_add_tail(&file_check_new->list, &newe->file_checks[tmp].list);
td_list_add_tail(&newe->list, &pos->list);
}
@@ -95,10 +133,15 @@ void register_header_check(const unsigned int offset, const void *value, const u
td_list_add_sorted(&file_check_new->list, &file_check_plist.list, file_check_cmp);
}
+/*@
+ @ requires \valid(file_check_new);
+ @*/
static void index_header_check_aux(file_check_t *file_check_new)
{
if(file_check_new->length>0)
{
+ /*@ assert file_check_new->offset < 0x80000000; */
+ /*@ assert 0 < file_check_new->length <= 4096; */
struct td_list_head *tmp;
td_list_for_each(tmp, &file_check_list.list)
{
@@ -146,6 +189,11 @@ void free_header_check(void)
{
unsigned int i;
file_check_list_t *pos=td_list_entry(tmpl, file_check_list_t, list);
+ /*@
+ @ loop unroll 256;
+ @ loop invariant 0 <= i <= 256;
+ @*/
+ /* TODO loop variant 255-i; */
for(i=0;i<256;i++)
{
struct td_list_head *tmp;
@@ -186,6 +234,9 @@ 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)
return;
taille=fread(buffer,1, 4096,file_recovery->handle);
+#ifdef __FRAMAC__
+ Frama_C_make_unknown((char *)&buffer, 4096);
+#endif
if(taille > 0 && buffer[0]=='\n' && (nl_mode&NL_BARENL)==NL_BARENL)
file_recovery->file_size++;
else if(taille > 1 && buffer[0]=='\r' && buffer[1]=='\n' && (nl_mode&NL_CRLF)==NL_CRLF)
@@ -198,20 +249,35 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
{
unsigned char*buffer;
assert(footer_length < 4096);
- buffer=(unsigned char*)MALLOC(4096+footer_length-1);
+ /*@ assert 0 < footer_length < 4096; */
+ /*
+ * 4096+footer_length-1: required size
+ * 4096+footer_length: to avoid a Frama-C warning when footer_length==1
+ * 8192: maximum size
+ * */
+ buffer=(unsigned char*)MALLOC(4096+footer_length);
memset(buffer+4096,0,footer_length-1);
do
{
int i;
int taille;
- const unsigned int read_size=(offset%4096!=0 ? offset%4096 : 4096);
- offset-=read_size;
+ if(offset <= 4096)
+ offset=0;
+ else if(offset%4096==0)
+ offset-=4096;
+ else
+ offset=offset-(offset%4096);
if(my_fseek(handle,offset,SEEK_SET)<0)
{
free(buffer);
return 0;
}
- taille=fread(buffer, 1, read_size, handle);
+ taille=fread(buffer, 1, 4096, handle);
+ if(taille <= 0)
+ {
+ free(buffer);
+ return 0;
+ }
for(i=taille-1;i>=0;i--)
{
if(buffer[i]==*(const unsigned char *)footer && memcmp(buffer+i,footer,footer_length)==0)
@@ -233,6 +299,7 @@ void file_search_footer(file_recovery_t *file_recovery, const void*footer, const
file_recovery->file_size=file_rsearch(file_recovery->handle, file_recovery->file_size-extra_length, footer, footer_length);
if(file_recovery->file_size > 0)
file_recovery->file_size+= footer_length + extra_length;
+ /*@ assert \valid(file_recovery->handle); */
}
#if 0
@@ -373,88 +440,81 @@ file_stat_t * init_file_stats(file_enable_t *files_enable)
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((const char*)&file_recovery->filename);
- @ requires new_ext==\null || valid_read_string(new_ext);
+ @ requires valid_read_string(new_ext);
+ @ ensures valid_read_string((char*)&file_recovery->filename);
@*/
-static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext, const int append_original_ext)
+static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext)
{
- /* new_filename is large enough to avoid a buffer overflow */
- char *new_filename;
- const char *src=file_recovery->filename;
- const char *ext=NULL;
+ char new_filename[sizeof(file_recovery->filename)];
char *dst;
- char *directory_sep;
- int len;
- len=strlen(src)+1;
- if(new_ext!=NULL)
- len+=strlen(new_ext);
- new_filename=(char*)MALLOC(len);
- dst=new_filename;
- directory_sep=new_filename;
- while(*src!='\0')
+ char *dst_dir_sep;
+ unsigned int len=strlen(file_recovery->filename)+1;
+ len+=strlen(new_ext);
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ if(len > sizeof(file_recovery->filename))
{
- if(*src=='/')
- {
- directory_sep=dst;
- ext=NULL;
- }
- if(*src=='.')
- ext=src;
- *dst++ = *src++;
+ return -1;
}
- *dst='\0';
- dst=directory_sep;
+ /*@ assert len <= sizeof(file_recovery->filename); */
+ /*@ assert valid_read_string((char*)&file_recovery->filename); */
+ strcpy(new_filename, (char *)&file_recovery->filename);
+ dst_dir_sep=strrchr(new_filename, '/');
+#ifndef __FRAMAC__
+ /*@ assert valid_read_string(dst_dir_sep); */
+ dst=dst_dir_sep;
while(*dst!='.' && *dst!='\0')
dst++;
/* Add extension */
- if(new_ext!=NULL)
{
+ const char *src;
src=new_ext;
*dst++ = '.';
while(*src!='\0')
*dst++ = *src++;
+ *dst='\0';
}
- else if(append_original_ext>0)
+#endif
+ /*@ assert valid_read_string(&new_filename[0]); */
+ if(strlen(new_filename) >= sizeof(file_recovery->filename))
{
- if(ext!=NULL)
- {
- while(*ext!='\0')
- *dst++ = *ext++;
- }
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ return -1;
}
- *dst='\0';
- if(rename(file_recovery->filename, new_filename)<0)
+ /*@ assert valid_read_string(&new_filename[0]); */
+ if(rename(&file_recovery->filename[0], new_filename)<0)
{
/* Rename has failed */
- free(new_filename);
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
return -1;
}
- if(strlen(new_filename)<sizeof(file_recovery->filename))
- {
- strcpy(file_recovery->filename, new_filename);
- }
- free(new_filename);
+ /*@ assert valid_read_string(&new_filename[0]); */
+ strcpy(file_recovery->filename, new_filename);
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
return 0;
}
-/* The original filename begins at offset in buffer and is null terminated */
-int file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
+/*@
+ @ requires \valid(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);
+ @*/
+static int _file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
{
- /* TODO: make the code from frama-c friendly */
-#ifndef __FRAMAC__
- /* new_filename is large enough to avoid a buffer overflow */
char *new_filename;
const char *src=file_recovery->filename;
const char *ext=NULL;
char *dst;
char *directory_sep;
int len;
- if(buffer_size<0)
- return -1;
len=strlen(src)+1;
- if(offset < buffer_size && buffer!=NULL)
- len+=buffer_size-offset+1;
+ /*@ assert offset < buffer_size; */
+ len+=buffer_size-offset+1;
if(new_ext!=NULL)
len+=strlen(new_ext);
+#ifndef __FRAMAC__
new_filename=(char*)MALLOC(len);
dst=new_filename;
directory_sep=new_filename;
@@ -474,7 +534,6 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu
while(*dst!='.' && *dst!='\0')
dst++;
/* Add original filename */
- if(offset < buffer_size && buffer!=NULL)
{
char *dst_old=dst;
int off;
@@ -538,112 +597,72 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu
}
}
*dst='\0';
- if(rename(file_recovery->filename, new_filename)<0)
- {
- /* Rename has failed */
- free(new_filename);
- if(buffer==NULL)
- return -1;
- /* Try without the original filename */
- return file_rename_aux(file_recovery, new_ext, append_original_ext);
- }
- if(strlen(new_filename)<sizeof(file_recovery->filename))
+ /*@ assert valid_read_string(new_filename); */
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ if(strlen(new_filename)<sizeof(file_recovery->filename) && rename(file_recovery->filename, new_filename)==0)
{
strcpy(file_recovery->filename, new_filename);
+ free(new_filename);
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ return 0;
+
}
free(new_filename);
#endif
- return 0;
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ return -1;
}
-/*@
- @ requires \valid(file_recovery);
- @ requires valid_read_string((const char*)&file_recovery->filename);
- @ requires new_ext==\null || valid_read_string(new_ext);
- @*/
-static int file_rename_unicode_aux(file_recovery_t *file_recovery, const char *new_ext, const int append_original_ext)
+/* The original filename begins at offset in buffer and is null terminated */
+int file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
{
- char *new_filename;
- const char *src=file_recovery->filename;
- const char *ext=src;
- char *dst;
- char *directory_sep;
- unsigned int len=strlen(file_recovery->filename)+1;
- /*@ assert len < sizeof(file_recovery->filename); */
- if(new_ext!=NULL)
- len+=strlen(new_ext);
- if(len > sizeof(file_recovery->filename))
- return -1;
- new_filename=(char*)MALLOC(len);
- strcpy(new_filename, (char *)&file_recovery->filename);
- directory_sep=strrchr(file_recovery->filename, '/');
- ext=strrchr(file_recovery->filename, '.');
- /*@ assert directory_sep != \null; */
-#if 1
- dst=directory_sep;
- while(*dst!='.' && *dst!='\0')
- dst++;
- /* Add extension */
- if(new_ext!=NULL)
- {
- src=new_ext;
- *dst++ = '.';
- while(*src!='\0')
- *dst++ = *src++;
- }
- else if(append_original_ext>0)
- {
- while(*ext!='\0')
- *dst++ = *ext++;
- }
- *dst='\0';
-#endif
- if(rename(file_recovery->filename, new_filename)<0)
- {
- /* Rename has failed */
- free(new_filename);
- return -1;
- }
- strcpy(file_recovery->filename, new_filename);
- free(new_filename);
- return 0;
+ if(buffer!=NULL && 0 <= offset && offset < buffer_size &&
+ _file_rename(file_recovery, buffer, buffer_size, offset, new_ext, append_original_ext)==0)
+ return 0;
+ if(new_ext==NULL)
+ return 0;
+ /* Try without the original filename */
+ return file_rename_aux(file_recovery, new_ext);
}
/* The original filename begins at offset in buffer and is null terminated */
-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)
+/*@
+ @ requires \valid(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);
+ @*/
+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)
{
- /* TODO: make the code from frama-c friendly */
-#ifndef __FRAMAC__
- /* new_filename is large enough to avoid a buffer overflow */
char *new_filename;
const char *src=file_recovery->filename;
- const char *ext=src;
+ const char *src_ext=src;
char *dst;
- char *directory_sep;
+ char *dst_dir_sep;
int len=strlen(src)+1;
- if(buffer_size<0)
- return -1;
- if(offset < buffer_size && buffer!=NULL)
- len+=buffer_size-offset;
+ /*@ assert offset < buffer_size; */
+ len+=buffer_size-offset;
if(new_ext!=NULL)
len+=strlen(new_ext);
+#ifndef __FRAMAC__
new_filename=(char*)MALLOC(len);
dst=new_filename;
- directory_sep=dst;
+ dst_dir_sep=dst;
while(*src!='\0')
{
if(*src=='/')
- directory_sep=dst;
+ dst_dir_sep=dst;
if(*src=='.')
- ext=src;
+ src_ext=src;
*dst++ = *src++;
}
*dst='\0';
- dst=directory_sep;
+ dst=dst_dir_sep;
while(*dst!='.' && *dst!='\0')
dst++;
/* Add original filename */
- if(offset < buffer_size && buffer!=NULL)
{
char *dst_old=dst;
int off;
@@ -698,32 +717,40 @@ int file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, cons
while(*src!='\0')
*dst++ = *src++;
}
- else if(append_original_ext>0)
+ else if(append_original_ext>0 && src_ext!=NULL)
{
- while(*ext!='\0')
- *dst++ = *ext++;
+ while(*src_ext!='\0')
+ *dst++ = *src_ext++;
}
*dst='\0';
- if(rename(file_recovery->filename, new_filename)<0)
- {
- /* Rename has failed */
- free(new_filename);
- if(buffer==NULL)
- return -1;
- /* Try without the original filename */
- return file_rename_unicode_aux(file_recovery, new_ext, append_original_ext);
- }
- if(strlen(new_filename)<sizeof(file_recovery->filename))
+ if(strlen(new_filename)<sizeof(file_recovery->filename) && rename(file_recovery->filename, new_filename)==0)
{
strcpy(file_recovery->filename, new_filename);
+ free(new_filename);
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ return 0;
}
free(new_filename);
#endif
- return 0;
+ /*@ assert valid_read_string(&file_recovery->filename[0]); */
+ return -1;
+}
+
+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)
+{
+ 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;
+ 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;
+ @*/
void header_ignored_cond_reset(uint64_t start, uint64_t end)
{
if(start <= offset_skipped_header && offset_skipped_header <= end)
@@ -753,7 +780,7 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery
}
memcpy(&fr_test, file_recovery, sizeof(fr_test));
-#if defined(HAVE_FTELLO) && !defined(__FRAMAC__)
+#if defined(HAVE_FTELLO)
if((offset=ftello(file_recovery->handle)) < 0)
offset=ftell(file_recovery->handle);
#else
@@ -786,11 +813,12 @@ void header_ignored(const file_recovery_t *file_recovery_new)
offset_skipped_header=file_recovery_new->location.start;
}
-void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const uint64_t prev_location)
+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++;
while(1)
{
file_space=td_list_prev_entry(file_space, list);
@@ -820,12 +848,13 @@ void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **cur
return;
}
*current_search_space=file_space;
- if(file_space->start < prev_location || file_space->start < offset_skipped_header)
+ if(file_space->start < offset_skipped_header)
{
#ifdef DEBUG_PREV_LOCATION
- log_info("get_prev_location_smart: file_space->start < prev_location=%llu (in 512-bytes sectors), offset=%llu\n",
+ log_info("get_prev_location_smart: file_space->start < offset_skipped_header, prev_location=%llu (in 512-bytes sectors), offset=%llu => %llu\n",
(long long unsigned)(prev_location/512),
- (long long unsigned)(*offset/512));
+ (long long unsigned)(*offset/512),
+ (long long unsigned)(offset_skipped_header/512));
#endif
*offset=offset_skipped_header;
offset_skipped_header=0;
@@ -837,7 +866,7 @@ void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **cur
int my_fseek(FILE *stream, off_t offset, int whence)
{
-#if defined(HAVE_FSEEKO) && !defined(__MINGW32__) && !defined(__ARM_EABI__) && !defined(__FRAMAC__)
+#if defined(HAVE_FSEEKO) && !defined(__MINGW32__) && !defined(__ARM_EABI__)
{
int res;
if((res=fseeko(stream, offset, whence))>=0)
diff --git a/src/filegen.h b/src/filegen.h
index 31aabfa..573997c 100644
--- a/src/filegen.h
+++ b/src/filegen.h
@@ -122,6 +122,8 @@ void free_header_check(void);
/*@
@ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ ensures file_recovery->handle == \old(file_recovery->handle);
@*/
void file_allow_nl(file_recovery_t *file_recovery, const unsigned int nl_mode);
@@ -134,32 +136,43 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
/*@
@ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
@ requires footer_length > 0;
@ requires \valid_read((char *)footer+(0..footer_length-1));
+ @ ensures \valid(file_recovery->handle);
@*/
void file_search_footer(file_recovery_t *file_recovery, const void*footer, const unsigned int footer_length, const unsigned int extra_length);
/*@
- @ requires buffer_size > 0;
+ @ requires buffer_size >= 2;
+ @ requires (buffer_size&1)==0;
@ requires \valid_read((char *)buffer+(0..buffer_size-1));
@ requires \valid(file_recovery);
- @ assigns \nothing;
+ @ 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;
@*/
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;
@*/
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;
@*/
void file_check_size_min(file_recovery_t *file_recovery);
/*@
@ requires \valid(file_recovery);
+ @ requires file_recovery->file_check == &file_check_size_max;
+ @ assigns file_recovery->file_size;
@*/
void file_check_size_max(file_recovery_t *file_recovery);
@@ -211,14 +224,16 @@ void file_check_size_max(file_recovery_t *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_function(header_check);
@ requires \valid(file_stat);
@*/
-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,
+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),
- file_stat_t *file_stat);
+ file_stat_t *file_stat);
/*@
@ requires \valid(files_enable);
@@ -230,6 +245,7 @@ file_stat_t * init_file_stats(file_enable_t *files_enable);
@ 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);
+ @ ensures valid_read_string((char*)&file_recovery->filename);
@*/
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);
@@ -238,6 +254,7 @@ 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);
+ @ ensures valid_read_string((char*)&file_recovery->filename);
@*/
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);
@@ -293,7 +310,7 @@ time_t get_time_from_YYYYMMDD_HHMMSS(const char *date_asc);
@ requires \valid(current_search_space);
@ requires \valid(offset);
@*/
-void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const uint64_t prev_location);
+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);
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/fnctdsk.c b/src/fnctdsk.c
index 0a766b2..f483ce2 100644
--- a/src/fnctdsk.c
+++ b/src/fnctdsk.c
@@ -38,8 +38,17 @@
#include "log_part.h"
#include "guid_cpy.h"
-static unsigned int get_geometry_from_list_part_aux(const disk_t *disk_car, const list_part_t *list_part, const int verbose);
-static list_part_t *element_new(partition_t *part);
+/*@
+ @ requires \valid(part);
+ @*/
+static list_part_t *element_new(partition_t *part)
+{
+ list_part_t *new_element=(list_part_t*)MALLOC(sizeof(*new_element));
+ new_element->part=part;
+ new_element->prev=new_element->next=NULL;
+ new_element->to_be_removed=0;
+ return new_element;
+}
unsigned long int C_H_S2LBA(const disk_t *disk_car,const unsigned int C, const unsigned int H, const unsigned int S)
{
@@ -318,19 +327,16 @@ partition_t *partition_new(const arch_fnct_t *arch)
return partition;
}
-static list_part_t *element_new(partition_t *part)
-{
- list_part_t *new_element=(list_part_t*)MALLOC(sizeof(*new_element));
- new_element->part=part;
- new_element->prev=new_element->next=NULL;
- new_element->to_be_removed=0;
- return new_element;
-}
-
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(list_part);
+ @ assigns \nothing;
+ @*/
static unsigned int get_geometry_from_list_part_aux(const disk_t *disk_car, const list_part_t *list_part, const int verbose)
{
const list_part_t *element;
unsigned int nbr=0;
+ /*@ loop assigns element, nbr; */
for(element=list_part;element!=NULL;element=element->next)
{
CHS_t start;
diff --git a/src/fnctdsk.h b/src/fnctdsk.h
index e979309..1c8a611 100644
--- a/src/fnctdsk.h
+++ b/src/fnctdsk.h
@@ -23,29 +23,190 @@
extern "C" {
#endif
+/*@
+ @ requires \valid_read(disk_car);
+ @ assigns \nothing;
+ @*/
unsigned long int C_H_S2LBA(const disk_t *disk_car,const unsigned int C, const unsigned int H, const unsigned int S);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ assigns \nothing;
+ @*/
uint64_t CHS2offset(const disk_t *disk_car,const CHS_t*CHS);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->geom.sectors_per_head > 0;
+ @ assigns \nothing;
+ @ ensures 0 < \result <= disk_car->geom.sectors_per_head;
+ @*/
unsigned int offset2sector(const disk_t *disk_car, const uint64_t offset);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->geom.sectors_per_head > 0;
+ @ requires disk_car->geom.heads_per_cylinder > 0;
+ @ assigns \nothing;
+ @ ensures \result <= disk_car->geom.heads_per_cylinder;
+ @*/
unsigned int offset2head(const disk_t *disk_car, const uint64_t offset);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->geom.sectors_per_head > 0;
+ @ requires disk_car->geom.heads_per_cylinder > 0;
+ @ assigns \nothing;
+ @*/
unsigned int offset2cylinder(const disk_t *disk_car, const uint64_t offset);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid(CHS);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->geom.sectors_per_head > 0;
+ @ requires disk_car->geom.heads_per_cylinder > 0;
+ @ assigns CHS->cylinder,CHS->head,CHS->sector;
+ @*/
void offset2CHS(const disk_t *disk_car,const uint64_t offset, CHS_t*CHS);
+/*@
+ @ requires list_disk==\null || \valid(list_disk);
+ @ requires disk==\null || (\valid(disk) && valid_read_string(disk->device));
+ @ requires the_disk==\null || \valid(the_disk);
+ @ ensures \result==\null || \valid(\result);
+ @ ensures disk==\null ==> \result == list_disk;
+ @*/
list_disk_t *insert_new_disk_aux(list_disk_t *list_disk, disk_t *disk, disk_t **the_disk);
+
+/*@
+ @ requires list_disk==\null || \valid(list_disk);
+ @ requires disk_car==\null || (\valid(disk_car) && valid_read_string(disk_car->device));
+ @ ensures \result==\null || \valid(\result);
+ @*/
list_disk_t *insert_new_disk(list_disk_t *list_disk, disk_t *disk_car);
+
+/*@
+ @ requires list_part == \null || \valid(list_part);
+ @ requires \valid(part);
+ @ requires \valid(insert_error);
+ @*/
list_part_t *insert_new_partition(list_part_t *list_part, partition_t *part, const int force_insert, int *insert_error);
+
+/*@
+ @ requires \valid(list_part);
+ @*/
list_part_t *sort_partition_list(list_part_t *list_part);
+
+/*@
+ @ requires \valid_read(list_part);
+ @*/
list_part_t *gen_sorted_partition_list(const list_part_t *list_part);
+
+/*@
+ @ requires \valid(list_part);
+ @*/
void part_free_list(list_part_t *list_part);
+
+/*@
+ @ requires \valid(list_part);
+ @*/
void part_free_list_only(list_part_t *list_part);
+
+/*@
+ @ requires \valid(partition);
+ @ requires \valid_read(arch);
+ @ assigns partition->part_size;
+ @ assigns partition->sborg_offset;
+ @ assigns partition->sb_offset;
+ @ assigns partition->sb_size;
+ @ assigns partition->blocksize;
+ @ assigns partition->part_type_i386;
+ @ assigns partition->part_type_sun;
+ @ assigns partition->part_type_mac;
+ @ assigns partition->part_type_xbox;
+ @ assigns partition->part_type_gpt;
+ @ assigns partition->part_uuid;
+ @ assigns partition->upart_type;
+ @ assigns partition->status;
+ @ assigns partition->order;
+ @ assigns partition->errcode;
+ @ assigns partition->fsname[0];
+ @ assigns partition->partname[0];
+ @ assigns partition->info[0];
+ @ ensures partition->part_size == 0;
+ @ ensures partition->sborg_offset == 0;
+ @ ensures partition->sb_offset == 0;
+ @ ensures partition->sb_size == 0;
+ @ ensures partition->blocksize == 0;
+ @ ensures partition->part_type_i386 == P_NO_OS;
+ @ ensures partition->part_type_sun == PSUN_UNK;
+ @ ensures partition->part_type_mac == PMAC_UNK;
+ @ ensures partition->part_type_xbox == PXBOX_UNK;
+ @ ensures partition->upart_type == UP_UNK;
+ @ ensures partition->status == STATUS_DELETED;
+ @ ensures partition->order == NO_ORDER;
+ @ ensures partition->errcode == BAD_NOERR;
+ @ ensures partition->fsname[0] == '\0';
+ @ ensures partition->partname[0] == '\0';
+ @ ensures partition->info[0] == '\0';
+ @ ensures partition->arch == arch;
+ @*/
void partition_reset(partition_t *partition, const arch_fnct_t *arch);
+
+/*@
+ @ requires \valid_read(arch);
+ @ ensures \result->arch == arch;
+ @*/
partition_t *partition_new(const arch_fnct_t *arch);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(list_part);
+ @ assigns \nothing;
+ @*/
unsigned int get_geometry_from_list_part(const disk_t *disk_car, const list_part_t *list_part, const int verbose);
+
+/*@
+ @ requires list_disk==\null || \valid(list_disk);
+ @ requires list_disk==\null || \freeable(list_disk);
+ @ requires list_disk==\null || \freeable(list_disk->disk);
+ @ requires list_disk==\null || (list_disk->disk->device == \null || \freeable(list_disk->disk->device));
+ @ requires list_disk==\null || (list_disk->disk->model == \null || \freeable(list_disk->disk->model));
+ @ requires list_disk==\null || (list_disk->disk->serial_no == \null || \freeable(list_disk->disk->serial_no));
+ @ requires list_disk==\null || (list_disk->disk->fw_rev == \null || \freeable(list_disk->disk->fw_rev));
+ @ requires list_disk==\null || (list_disk->disk->data == \null || \freeable(list_disk->disk->data));
+ @ requires list_disk==\null || (list_disk->disk->rbuffer == \null || \freeable(list_disk->disk->rbuffer));
+ @ requires list_disk==\null || (list_disk->disk->wbuffer == \null || \freeable(list_disk->disk->wbuffer));
+ @*/
int delete_list_disk(list_disk_t *list_disk);
+
+/*@
+ @ requires \valid(buffer + (0..99));
+ @ ensures valid_string(buffer);
+ @*/
+/* TODO assigns */
void size_to_unit(const uint64_t disk_size, char *buffer);
+
+/*@
+ @ requires \valid_read(list_part);
+ @ assigns \nothing;
+ @*/
int is_part_overlapping(const list_part_t *list_part);
+
+/*@
+ @ requires \valid(dest);
+ @ requires \valid_read(src);
+ @*/
void dup_partition_t(partition_t *dest, const partition_t *src);
-void log_disk_list(list_disk_t *list_disk);
+/*@
+ @ requires list_disk==\null || \valid(list_disk);
+ @*/
+void log_disk_list(list_disk_t *list_disk);
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/fuzzerfidentify.cpp b/src/fuzzerfidentify.cpp
index f5be374..90f0ef8 100644
--- a/src/fuzzerfidentify.cpp
+++ b/src/fuzzerfidentify.cpp
@@ -49,7 +49,7 @@
#include "filegen.h"
#include <sys/types.h>
#include <unistd.h>
-extern file_enable_t list_file_enable[];
+extern file_enable_t array_file_enable[];
extern file_check_list_t file_check_list;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
@@ -71,9 +71,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
/* Enable all file formats */
file_enable_t *file_enable;
- for(file_enable=list_file_enable;file_enable->file_hint!=NULL;file_enable++)
+ for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++)
file_enable->enable=1;
- file_stats=init_file_stats(list_file_enable);
+ file_stats=init_file_stats(array_file_enable);
}
if(buffer_start==NULL)
{
diff --git a/src/geometry.c b/src/geometry.c
index 470ab60..98f4d75 100644
--- a/src/geometry.c
+++ b/src/geometry.c
@@ -80,6 +80,7 @@ int change_geometry_cli(disk_t *disk_car, char ** current_cmd)
if(*current_cmd==NULL)
return 0;
log_info("Current geometry\n%s sector_size=%u\n", disk_car->description(disk_car), disk_car->sector_size);
+ /*@ loop invariant valid_read_string(*current_cmd); */
while (done==0)
{
skip_comma_in_command(current_cmd);
diff --git a/src/geometry.h b/src/geometry.h
index 98993c2..5534241 100644
--- a/src/geometry.h
+++ b/src/geometry.h
@@ -23,8 +23,29 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk);
+ @ requires 0 < disk->geom.sectors_per_head;
+ @ requires 0 < disk->geom.heads_per_cylinder;
+ @ assigns disk->geom.cylinders;
+ @*/
void set_cylinders_from_size_up(disk_t *disk);
+
+/*@
+ @ requires \valid(disk);
+ @ assigns disk->sector_size, disk->geom.cylinders;
+ @*/
int change_sector_size(disk_t *disk, const int cyl_modified, const unsigned int sector_size);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_function(disk->description);
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ requires separation: \separated(disk, current_cmd);
+ @ requires \valid_function(disk->description);
+ @ ensures valid_read_string(*current_cmd);
+ @*/
int change_geometry_cli(disk_t *disk, char **current_cmd);
#ifdef __cplusplus
diff --git a/src/gfs2.c b/src/gfs2.c
index e710dd2..d0eadc8 100644
--- a/src/gfs2.c
+++ b/src/gfs2.c
@@ -40,7 +40,7 @@ static void set_gfs2_info(partition_t *partition)
partition->info[0]='\0';
}
-static int test_gfs2(disk_t *disk, const struct gfs2_sb *sb, const partition_t *partition, const int dump_ind)
+static int test_gfs2(const disk_t *disk, const struct gfs2_sb *sb, const partition_t *partition, const int dump_ind)
{
if(sb->sb_header.mh_magic != be32(GFS2_MAGIC))
return 1;
@@ -78,7 +78,7 @@ int check_gfs2(disk_t *disk, partition_t *partition)
return 0;
}
-int recover_gfs2(disk_t *disk, const struct gfs2_sb *sb, partition_t *partition, const int dump_ind)
+int recover_gfs2(const disk_t *disk, const struct gfs2_sb *sb, partition_t *partition, const int dump_ind)
{
if(test_gfs2(disk,sb,partition,dump_ind)!=0)
return 1;
diff --git a/src/gfs2.h b/src/gfs2.h
index 6c9859a..20d7302 100644
--- a/src/gfs2.h
+++ b/src/gfs2.h
@@ -79,7 +79,7 @@ struct gfs2_sb {
//
int check_gfs2(disk_t *disk_car, partition_t *partition);
-int recover_gfs2(disk_t *disk_car, const struct gfs2_sb *sb, partition_t *partition, const int dump_ind);
+int recover_gfs2(const disk_t *disk_car, const struct gfs2_sb *sb, partition_t *partition, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/godmode.c b/src/godmode.c
index 0b41b0e..fc15c77 100644
--- a/src/godmode.c
+++ b/src/godmode.c
@@ -60,22 +60,13 @@ extern const arch_fnct_t arch_mac;
extern const arch_fnct_t arch_none;
extern const arch_fnct_t arch_sun;
extern const arch_fnct_t arch_xbox;
-static int use_backup(disk_t *disk_car, const list_part_t *list_part, const int verbose,const int dump_ind, const unsigned int expert, char**current_cmd);
-static int interface_part_bad_log(disk_t *disk_car,list_part_t *list_part_bad);
#ifdef HAVE_NCURSES
-static int interface_part_bad_ncurses(disk_t *disk_car, list_part_t *list_part_bad);
-static void ask_mbr_order_i386(disk_t *disk_car,list_part_t *list_part);
#define ANALYSE_X 0
#define ANALYSE_Y 5
#define INTER_BAD_PART 10
#endif
-static list_part_t *add_ext_part_i386(disk_t *disk_car, list_part_t *list_part, const int max_ext, const int verbose);
-static void hint_insert(uint64_t *tab, const uint64_t offset, unsigned int *tab_nbr);
-/* Optimization */
-static inline uint64_t CHS2offset_inline(const disk_t *disk_car,const CHS_t*CHS);
-static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_org, const int verbose, const int dump_ind, const int fast_mode, char **current_cmd);
-static inline void offset2CHS_inline(const disk_t *disk_car,const uint64_t offset, CHS_t*CHS);
+/* Optimization */
static inline void offset2CHS_inline(const disk_t *disk_car,const uint64_t offset, CHS_t*CHS)
{
uint64_t pos=offset/disk_car->sector_size;
@@ -160,7 +151,7 @@ static void align_structure(list_part_t *list_part, const disk_t *disk, const un
}
}
-void only_one_bootable( list_part_t *list_part, list_part_t *part_boot)
+void only_one_bootable( list_part_t *list_part, const list_part_t *part_boot)
{
list_part_t *element;
if(part_boot->part->status==STATUS_PRIM_BOOT)
@@ -1124,7 +1115,7 @@ static list_part_t *reduce_structure(const list_part_t *list_part_org)
return list_part;
}
-static list_part_t *add_ext_part_i386(disk_t *disk, list_part_t *list_part, const int max_ext, const int verbose)
+static list_part_t *add_ext_part_i386(const disk_t *disk, list_part_t *list_part, const int max_ext, const int verbose)
{
/* list_part need to be sorted! */
/* All extended partitions of an P_EXTENDX are P_EXTENDED */
diff --git a/src/godmode.h b/src/godmode.h
index 1af7448..d93081b 100644
--- a/src/godmode.h
+++ b/src/godmode.h
@@ -25,7 +25,7 @@ extern "C" {
typedef enum part_offset part_offset_t;
int interface_recovery(disk_t *disk_car, const list_part_t * list_part_org, const int verbose, const int dump_ind, const int align, const int ask_part_order, const unsigned int expert, char **current_cmd);
-void only_one_bootable( list_part_t *list_part, list_part_t *part_boot);
+void only_one_bootable( list_part_t *list_part, const list_part_t *part_boot);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/guid_cmp.h b/src/guid_cmp.h
index 14ccde8..4c0aece 100644
--- a/src/guid_cmp.h
+++ b/src/guid_cmp.h
@@ -19,6 +19,10 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
+/*@
+ @ assigns \nothing;
+ @*/
static inline int guid_cmp (const efi_guid_t left, const efi_guid_t right)
{
return memcmp(&left, &right, sizeof(efi_guid_t));
diff --git a/src/guid_cpy.h b/src/guid_cpy.h
index 5244a70..c68a087 100644
--- a/src/guid_cpy.h
+++ b/src/guid_cpy.h
@@ -19,6 +19,15 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
+/*@ requires \valid(dst);
+ @ requires \valid_read(src);
+ @ requires separation:
+ @ \separated(((char *)dst)+(0..sizeof(efi_guid_t)-1),((char *)src)+(0..sizeof(efi_guid_t)-1));
+ @ assigns ((char*)dst)[0..sizeof(efi_guid_t) - 1];
+ @*/
+// assigns ((char*)dst)[0..sizeof(efi_guid_t) - 1] \from ((char*)src)[0..sizeof(efi_guid_t)-1];
+// ensures copied_contents: memcmp{Post,Pre}((char*)dst,(char*)src,sizeof(efi_guid_t)) == 0;
static inline void guid_cpy (efi_guid_t *dst, const efi_guid_t *src)
{
memcpy(dst, src, sizeof(efi_guid_t));
diff --git a/src/hdaccess.c b/src/hdaccess.c
index 261a014..b501cb2 100644
--- a/src/hdaccess.c
+++ b/src/hdaccess.c
@@ -22,6 +22,19 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_FSYNC
+#undef HAVE_GLOB_H
+#undef HAVE_LIBEWF
+#undef HAVE_LINUX_HDREG_H
+#undef HAVE_LINUX_TYPES_H
+#undef HAVE_PREAD
+#undef HAVE_PWRITE
+#undef HAVE_SYS_MOUNT_H
+#undef HAVE_SYS_PARAM_H
+#undef TARGET_LINUX
+#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@@ -38,7 +51,7 @@
#include <stdio.h>
#include <errno.h>
#include "types.h"
-#ifdef HAVE_LINUX_TYPES_H
+#if defined(HAVE_LINUX_TYPES_H)
#include <linux/types.h>
#endif
#include "common.h"
@@ -48,13 +61,13 @@
#ifdef HAVE_SYS_DISKLABEL_H
#include <sys/disklabel.h>
#endif
-#ifdef HAVE_SYS_PARAM_H
+#if defined(HAVE_SYS_PARAM_H)
#include <sys/param.h>
#endif
-#ifdef HAVE_SYS_MOUNT_H
+#if defined(HAVE_SYS_MOUNT_H)
#include <sys/mount.h> /* BLKFLSBUF */
#endif
-#ifdef HAVE_LINUX_HDREG_H
+#if defined(HAVE_LINUX_HDREG_H)
#include <linux/hdreg.h>
#endif
#ifdef HAVE_SYS_DISK_H
@@ -104,6 +117,9 @@
#if defined(__HAIKU__)
#include <Drivers.h>
#endif
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
#include "fnctdsk.h"
#include "ewf.h"
#include "log.h"
@@ -849,7 +865,9 @@ void update_disk_car_fields(disk_t *disk_car)
{
if(disk_car->geom.cylinders>0)
{
+#ifndef __FRAMAC__
log_warning("Fix disk size using CHS\n");
+#endif
disk_car->disk_real_size=(uint64_t)disk_car->geom.cylinders * disk_car->geom.heads_per_cylinder *
disk_car->geom.sectors_per_head * disk_car->sector_size;
}
@@ -862,8 +880,10 @@ void update_disk_car_fields(disk_t *disk_car)
(uint64_t)disk_car->sector_size;
if(cylinder_num>0 && disk_car->geom.cylinders != cylinder_num)
{
+#ifndef __FRAMAC__
log_debug("Fix cylinder count for %s: number of cylinders %lu != %lu (calculated)\n",
disk_car->device, disk_car->geom.cylinders, cylinder_num);
+#endif
disk_car->geom.cylinders = cylinder_num;
}
}
@@ -901,7 +921,7 @@ static char * read_device_sysfs_file (const disk_t *disk_car, const char *file)
* information. It uses the deprecated SCSI_IOCTL_SEND_COMMAND to
* issue this query.
*/
-#ifdef TARGET_LINUX
+#if defined(TARGET_LINUX)
#ifdef HAVE_SCSI_SCSI_H
#include <scsi/scsi.h>
#endif
@@ -1179,10 +1199,10 @@ static void file_clean(disk_t *disk)
generic_clean(disk);
}
-static int file_pread_aux(disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
+static int file_pread_aux(const disk_t *disk, void *buf, const unsigned int count, const uint64_t offset)
{
long int ret;
- int fd=((struct info_file_struct *)disk->data)->handle;
+ const int fd=((const struct info_file_struct *)disk->data)->handle;
#if defined(__CYGWIN__)
if(lseek(fd,offset,SEEK_SET) < 0)
{
@@ -1284,7 +1304,7 @@ static int file_pread_aux(disk_t *disk, void *buf, const unsigned int count, con
#ifdef HDCLONE
if(ret>0)
{
- int handle_clone=((struct info_file_struct *)disk->data)->handle_clone;
+ const int handle_clone=((const struct info_file_struct *)disk->data)->handle_clone;
if(handle_clone>0)
{
pwrite(handle_clone, buf, ret, offset);
diff --git a/src/hdaccess.h b/src/hdaccess.h
index 01ffbcc..0aa7f0d 100644
--- a/src/hdaccess.h
+++ b/src/hdaccess.h
@@ -22,14 +22,88 @@
#ifdef __cplusplus
extern "C" {
#endif
-
-
+/*@
+ @ requires \valid(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->geom.heads_per_cylinder > 0;
+ @ requires \valid_function(disk_car->pread);
+ @*/
void hd_update_geometry(disk_t *disk_car, const int verbose);
+
+/*@
+ @ requires list_disk==\null || \valid_read(list_disk);
+ @*/
void hd_update_all_geometry(const list_disk_t * list_disk, const int verbose);
+
+/*@
+ @ requires list_disk==\null || \valid_read(list_disk);
+ @ ensures \result==\null || \valid_read(\result);
+ @*/
list_disk_t *hd_parse(list_disk_t *list_disk, const int verbose, const int testdisk_mode);
+
+/*@
+ @ requires valid_read_string(device);
+ @ ensures \result==\null || \valid(\result);
+ @ ensures \result!=\null ==> (0 < \result->geom.cylinders < 0x2000000000000);
+ @ ensures \result!=\null ==> (0 < \result->geom.heads_per_cylinder <= 255);
+ @ ensures \result!=\null ==> (0 < \result->geom.sectors_per_head <= 63);
+ @ ensures \result!=\null ==> valid_read_string(\result->device);
+ @ ensures \result!=\null ==> \freeable(\result);
+ @ ensures \result!=\null ==> (\result->device == \null || \freeable(\result->device));
+ @ ensures \result!=\null ==> (\result->model == \null || \freeable(\result->model));
+ @ ensures \result!=\null ==> (\result->serial_no == \null || \freeable(\result->serial_no));
+ @ ensures \result!=\null ==> (\result->fw_rev == \null || \freeable(\result->fw_rev));
+ @ ensures \result!=\null ==> (\result->data == \null || \freeable(\result->data));
+ @ ensures \result!=\null ==> (\result->rbuffer == \null || \freeable(\result->rbuffer));
+ @ ensures \result!=\null ==> (\result->wbuffer == \null || \freeable(\result->wbuffer));
+ @*/
disk_t *file_test_availability(const char *device, const int verbose, const int testdisk_mode);
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires 0 < disk_car->geom.heads_per_cylinder;
+ @ requires 0 < disk_car->geom.sectors_per_head;
+ @ requires 0 < disk_car->sector_size;
+ @ ensures 0 < disk_car->geom.cylinders < 0x2000000000000;
+ @*/
void update_disk_car_fields(disk_t *disk_car);
+
+/*@
+ @ requires \valid(disk);
+ @ ensures disk->autodetect == 0;
+ @ ensures disk->disk_size == 0;
+ @ ensures disk->user_max == 0;
+ @ ensures disk->native_max == 0;
+ @ ensures disk->dco == 0;
+ @ ensures disk->offset == 0;
+ @ ensures disk->rbuffer == NULL;
+ @ ensures disk->wbuffer == NULL;
+ @ ensures disk->rbuffer_size == 0;
+ @ ensures disk->wbuffer_size == 0;
+ @ ensures disk->model == NULL;
+ @ ensures disk->serial_no == NULL;
+ @ ensures disk->fw_rev == NULL;
+ @ ensures disk->write_used == 0;
+ @ ensures disk->description_txt[0] == '\0';
+ @ ensures disk->unit == UNIT_CHS;
+ @ assigns disk->autodetect, disk->disk_size, disk->user_max, disk->native_max, disk->dco, disk->offset;
+ @ assigns disk->rbuffer, disk->wbuffer, disk->rbuffer_size, disk->wbuffer_size;
+ @ assigns disk->model, disk->serial_no, disk->fw_rev, disk->write_used;
+ @ assigns disk->description_txt[0], disk->unit;
+ @*/
void init_disk(disk_t *disk);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \freeable(disk);
+ @ requires disk->device == \null || \freeable(disk->device);
+ @ requires disk->model == \null || \freeable(disk->model);
+ @ requires disk->serial_no == \null || \freeable(disk->serial_no);
+ @ requires disk->fw_rev == \null || \freeable(disk->fw_rev);
+ @ requires disk->data == \null || \freeable(disk->data);
+ @ requires disk->rbuffer == \null || \freeable(disk->rbuffer);
+ @ requires disk->wbuffer == \null || \freeable(disk->wbuffer);
+ @*/
void generic_clean(disk_t *disk);
#ifdef __cplusplus
diff --git a/src/hdcache.c b/src/hdcache.c
index c7ae0ab..e2bc862 100644
--- a/src/hdcache.c
+++ b/src/hdcache.c
@@ -62,20 +62,16 @@ struct cache_struct
unsigned int last_io_error_nbr;
};
-static int cache_pread_aux(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset, const unsigned int read_ahead);
static int cache_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset);
static int cache_pwrite(disk_t *disk_car, const void *buffer, const unsigned int count, const uint64_t offset);
static int cache_sync(disk_t *disk);
static void cache_clean(disk_t *disk);
-static const char *cache_description(disk_t *disk_car);
-static const char *cache_description_short(disk_t *disk_car);
-
-static int cache_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset)
-{
- const struct cache_struct *data=(const struct cache_struct *)disk_car->data;
- return cache_pread_aux(disk_car, buffer, count, offset, (data->last_io_error_nbr==0));
-}
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid((char *)buffer + (0 .. count-1));
+ @ requires separation: \separated(disk_car, (char *)buffer + (0 .. count-1));
+ @*/
static int cache_pread_aux(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset, const unsigned int read_ahead)
{
struct cache_struct *data=(struct cache_struct *)disk_car->data;
@@ -184,6 +180,22 @@ static int cache_pread_aux(disk_t *disk_car, void *buffer, const unsigned int co
}
}
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid((char *)buffer + (0 .. count-1));
+ @ requires separation: \separated(disk_car, (char *)buffer + (0 .. count-1));
+ @*/
+static int cache_pread(disk_t *disk_car, void *buffer, const unsigned int count, const uint64_t offset)
+{
+ const struct cache_struct *data=(const struct cache_struct *)disk_car->data;
+ return cache_pread_aux(disk_car, buffer, count, offset, (data->last_io_error_nbr==0));
+}
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid_read((char *)buffer + (0 .. count-1));
+ @ requires separation: \separated(disk_car, (const char *)buffer + (0 .. count-1));
+ @*/
static int cache_pwrite(disk_t *disk_car, const void *buffer, const unsigned int count, const uint64_t offset)
{
struct cache_struct *data=(struct cache_struct *)disk_car->data;
@@ -201,6 +213,9 @@ static int cache_pwrite(disk_t *disk_car, const void *buffer, const unsigned int
return data->disk_car->pwrite(data->disk_car, buffer, count, offset);
}
+/*@
+ @ requires \valid(disk_car);
+ @*/
static void cache_clean(disk_t *disk_car)
{
if(disk_car->data)
@@ -225,12 +240,24 @@ static void cache_clean(disk_t *disk_car)
free(disk_car);
}
+/*@
+ @ requires \valid(disk_car);
+ @*/
static int cache_sync(disk_t *disk_car)
{
struct cache_struct *data=(struct cache_struct *)disk_car->data;
return data->disk_car->sync(data->disk_car);
}
+/*@
+ @ requires \valid_read(CHS_source);
+ @ requires \valid(CHS_dst);
+ @ requires separation: \separated(CHS_dst, CHS_source);
+ @ assigns CHS_dst->cylinders, CHS_dst->heads_per_cylinder, CHS_dst->sectors_per_head;
+ @ ensures CHS_dst->cylinders==CHS_source->cylinders;
+ @ ensures CHS_dst->heads_per_cylinder==CHS_source->heads_per_cylinder;
+ @ ensures CHS_dst->sectors_per_head==CHS_source->sectors_per_head;
+ @*/
static void dup_geometry(CHSgeometry_t * CHS_dst, const CHSgeometry_t * CHS_source)
{
CHS_dst->cylinders=CHS_source->cylinders;
@@ -238,6 +265,36 @@ static void dup_geometry(CHSgeometry_t * CHS_dst, const CHSgeometry_t * CHS_sour
CHS_dst->sectors_per_head=CHS_source->sectors_per_head;
}
+/*@
+ @ requires \valid(disk_car);
+ @ ensures valid_read_string(\result);
+ @*/
+static const char *cache_description(disk_t *disk_car)
+{
+ const char *tmp;
+ struct cache_struct *data=(struct cache_struct *)disk_car->data;
+ dup_geometry(&data->disk_car->geom,&disk_car->geom);
+ data->disk_car->disk_size=disk_car->disk_size;
+ tmp=data->disk_car->description(data->disk_car);
+ /*@ assert valid_read_string(tmp); */
+ return tmp;
+}
+
+/*@
+ @ requires \valid(disk_car);
+ @ ensures valid_read_string(\result);
+ @*/
+static const char *cache_description_short(disk_t *disk_car)
+{
+ const char *tmp;
+ struct cache_struct *data=(struct cache_struct *)disk_car->data;
+ dup_geometry(&data->disk_car->geom,&disk_car->geom);
+ data->disk_car->disk_size=disk_car->disk_size;
+ tmp=data->disk_car->description_short(data->disk_car);
+ /*@ assert valid_read_string(tmp); */
+ return tmp;
+}
+
disk_t *new_diskcache(disk_t *disk_car, const unsigned int testdisk_mode)
{
unsigned int i;
@@ -281,19 +338,3 @@ disk_t *new_diskcache(disk_t *disk_car, const unsigned int testdisk_mode)
}
return new_disk_car;
}
-
-static const char *cache_description(disk_t *disk_car)
-{
- struct cache_struct *data=(struct cache_struct *)disk_car->data;
- dup_geometry(&data->disk_car->geom,&disk_car->geom);
- data->disk_car->disk_size=disk_car->disk_size;
- return data->disk_car->description(data->disk_car);
-}
-
-static const char *cache_description_short(disk_t *disk_car)
-{
- struct cache_struct *data=(struct cache_struct *)disk_car->data;
- dup_geometry(&data->disk_car->geom,&disk_car->geom);
- data->disk_car->disk_size=disk_car->disk_size;
- return data->disk_car->description_short(data->disk_car);
-}
diff --git a/src/hdcache.h b/src/hdcache.h
index 4bc76dc..c32ad3a 100644
--- a/src/hdcache.h
+++ b/src/hdcache.h
@@ -23,6 +23,10 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk_car);
+ @ ensures \valid(\result);
+ @*/
disk_t *new_diskcache(disk_t *disk_car, const unsigned int cache_size_min);
#ifdef __cplusplus
diff --git a/src/hfs.c b/src/hfs.c
index 203ed86..5fc4247 100644
--- a/src/hfs.c
+++ b/src/hfs.c
@@ -55,7 +55,7 @@ int check_HFS(disk_t *disk_car,partition_t *partition,const int verbose)
return 0;
}
-int recover_HFS(disk_t *disk_car, const hfs_mdb_t *hfs_mdb,partition_t *partition,const int verbose, const int dump_ind, const int backup)
+int recover_HFS(const disk_t *disk_car, const hfs_mdb_t *hfs_mdb,partition_t *partition,const int verbose, const int dump_ind, const int backup)
{
uint64_t part_size;
if(test_HFS(disk_car,hfs_mdb,partition,verbose,dump_ind)!=0)
@@ -83,7 +83,7 @@ int recover_HFS(disk_t *disk_car, const hfs_mdb_t *hfs_mdb,partition_t *partitio
return 0;
}
-int test_HFS(disk_t *disk_car, const hfs_mdb_t *hfs_mdb, const partition_t *partition, const int verbose, const int dump_ind)
+int test_HFS(const disk_t *disk_car, const hfs_mdb_t *hfs_mdb, const partition_t *partition, const int verbose, const int dump_ind)
{
/* Check for HFS signature */
if (hfs_mdb->drSigWord!=be16(HFS_SUPER_MAGIC))
diff --git a/src/hfs.h b/src/hfs.h
index 9886916..3020f97 100644
--- a/src/hfs.h
+++ b/src/hfs.h
@@ -75,9 +75,29 @@ struct hfs_mdb {
uint32_t drCTFlSize; /* 0x92 bytes in the catalog B-tree */
hfs_extent_rec drCTExtRec; /* 0x96 catalog B-tree's first 3 extents */
} __attribute__ ((gcc_struct, __packed__));
-int check_HFS(disk_t *disk_car,partition_t *partition,const int verbose);
-int test_HFS(disk_t *disk_car, const hfs_mdb_t *hfs_mdb, const partition_t *partition, const int verbose, const int dump_ind);
-int recover_HFS(disk_t *disk_car, const hfs_mdb_t *hfs_mdb,partition_t *partition,const int verbose, const int dump_ind, const int backup);
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
+int check_HFS(disk_t *disk_car, partition_t *partition, const int verbose);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(hfs_mdb);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, hfs_mdb, partition);
+ @*/
+int test_HFS(const disk_t *disk_car, const hfs_mdb_t *hfs_mdb, const partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(hfs_mdb);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, hfs_mdb, partition);
+ @*/
+int recover_HFS(const disk_t *disk_car, const hfs_mdb_t *hfs_mdb, partition_t *partition, const int verbose, const int dump_ind, const int backup);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/hfsp.c b/src/hfsp.c
index 040a859..d8add90 100644
--- a/src/hfsp.c
+++ b/src/hfsp.c
@@ -52,7 +52,6 @@ static void set_HFSP_info(partition_t *partition, const struct hfsp_vh *vh)
}
}
-
int check_HFSP(disk_t *disk_car,partition_t *partition,const int verbose)
{
unsigned char *buffer=(unsigned char*)MALLOC(HFSP_BOOT_SECTOR_SIZE);
@@ -77,7 +76,7 @@ int check_HFSP(disk_t *disk_car,partition_t *partition,const int verbose)
return 0;
}
-int recover_HFSP(disk_t *disk_car, const struct hfsp_vh *vh,partition_t *partition,const int verbose, const int dump_ind, const int backup)
+int recover_HFSP(disk_t *disk_car, const struct hfsp_vh *vh, partition_t *partition, const int verbose, const int dump_ind, const int backup)
{
uint64_t part_size;
if(test_HFSP(disk_car,vh,partition,verbose,dump_ind)!=0)
@@ -116,7 +115,7 @@ int recover_HFSP(disk_t *disk_car, const struct hfsp_vh *vh,partition_t *partiti
return 0;
}
-int test_HFSP(disk_t *disk_car, const struct hfsp_vh *vh, const partition_t *partition, const int verbose, const int dump_ind)
+int test_HFSP(const disk_t *disk_car, const struct hfsp_vh *vh, const partition_t *partition, const int verbose, const int dump_ind)
{
if (be32(vh->free_blocks) > be32(vh->total_blocks))
return 1;
diff --git a/src/hfsp.h b/src/hfsp.h
index 4cbb928..f6e4b07 100644
--- a/src/hfsp.h
+++ b/src/hfsp.h
@@ -149,8 +149,8 @@ typedef struct hfsp_vh {
int check_HFSP(disk_t *disk_car,partition_t *partition,const int verbose);
-int test_HFSP(disk_t *disk_car, const struct hfsp_vh *vh, const partition_t *partition, const int verbose, const int dump_ind);
-int recover_HFSP(disk_t *disk_car, const struct hfsp_vh *vh,partition_t *partition,const int verbose, const int dump_ind, const int backup);
+int test_HFSP(const disk_t *disk_car, const struct hfsp_vh *vh, const partition_t *partition, const int verbose, const int dump_ind);
+int recover_HFSP(disk_t *disk_car, const struct hfsp_vh *vh, partition_t *partition, const int verbose, const int dump_ind, const int backup);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/hpa_dco.c b/src/hpa_dco.c
index 61d4804..a11c5b1 100644
--- a/src/hpa_dco.c
+++ b/src/hpa_dco.c
@@ -22,7 +22,13 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-
+
+#if defined(__FRAMAC__)
+#undef HAVE_LINUX_TYPES_H
+#undef HAVE_LINUX_HDREG_H
+#undef HAVE_SCSI_SG_H
+#endif
+
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@@ -37,20 +43,20 @@
#endif
#include <stdio.h>
#include "types.h"
-#ifdef HAVE_LINUX_TYPES_H
+#if defined(HAVE_LINUX_TYPES_H)
#include <linux/types.h>
#endif
#include "common.h"
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
-#ifdef HAVE_LINUX_HDREG_H
+#if defined(HAVE_LINUX_HDREG_H)
#include <linux/hdreg.h>
#endif
#ifdef HAVE_FNCTL_H
#include <fnctl.h>
#endif
-#ifdef HAVE_SCSI_SG_H
+#if defined(HAVE_SCSI_SG_H)
#include <scsi/sg.h>
#endif
#include "log.h"
diff --git a/src/hpfs.c b/src/hpfs.c
index 8524491..645e810 100644
--- a/src/hpfs.c
+++ b/src/hpfs.c
@@ -46,7 +46,7 @@ static void set_HPFS_info(partition_t *partition)
partition->upart_type=UP_HPFS;
}
-static int test_HPFS(disk_t *disk_car, const struct fat_boot_sector *hpfs_header, const partition_t *partition, const int verbose, const int dump_ind)
+static int test_HPFS(const disk_t *disk_car, const struct fat_boot_sector *hpfs_header, const partition_t *partition, const int verbose, const int dump_ind)
{
const char*buffer=(const char*)hpfs_header;
if(le16(hpfs_header->marker)==0xAA55)
@@ -70,7 +70,7 @@ static int test_HPFS(disk_t *disk_car, const struct fat_boot_sector *hpfs_header
return 1;
}
-int recover_HPFS(disk_t *disk_car, const struct fat_boot_sector *hpfs_header, partition_t *partition, const int verbose)
+int recover_HPFS(const disk_t *disk_car, const struct fat_boot_sector *hpfs_header, partition_t *partition, const int verbose)
{
if(test_HPFS(disk_car, hpfs_header, partition, verbose,0)!=0)
return 1;
diff --git a/src/hpfs.h b/src/hpfs.h
index b5947d4..faee3ae 100644
--- a/src/hpfs.h
+++ b/src/hpfs.h
@@ -26,7 +26,7 @@
extern "C" {
#endif
-int recover_HPFS(disk_t *disk_car, const struct fat_boot_sector *hpfs_header, partition_t *partition, const int verbose);
+int recover_HPFS(const disk_t *disk_car, const struct fat_boot_sector *hpfs_header, partition_t *partition, const int verbose);
int check_HPFS(disk_t *disk_car,partition_t *partition, const int verbose);
#ifdef __cplusplus
diff --git a/src/intrf.c b/src/intrf.c
index 3905015..ef2fa1b 100644
--- a/src/intrf.c
+++ b/src/intrf.c
@@ -201,6 +201,7 @@ const char *aff_part_aux(const unsigned int newline, const disk_t *disk_car, con
uint64_t atouint64(const char *nptr)
{
uint64_t tmp=0;
+ /*@ loop assigns tmp, nptr; */
while(*nptr >='0' && *nptr <= '9')
{
tmp = tmp * 10 + *nptr - '0';
@@ -215,7 +216,9 @@ uint64_t ask_number_cli(char **current_cmd, const uint64_t val_cur, const uint64
{
uint64_t tmp_val;
skip_comma_in_command(current_cmd);
+ /*@ assert valid_read_string(*current_cmd); */
tmp_val = get_int_from_command(current_cmd);
+ /*@ assert valid_read_string(*current_cmd); */
if (val_min==val_max || (tmp_val >= val_min && tmp_val <= val_max))
return tmp_val;
else
@@ -231,6 +234,7 @@ uint64_t ask_number_cli(char **current_cmd, const uint64_t val_cur, const uint64
va_end(ap);
}
}
+ /*@ assert valid_read_string(*current_cmd); */
return val_cur;
}
diff --git a/src/intrf.h b/src/intrf.h
index a50acfb..e675679 100644
--- a/src/intrf.h
+++ b/src/intrf.h
@@ -58,9 +58,18 @@ struct MenuItem
void log_CHS_from_LBA(const disk_t *disk_car, const unsigned long int pos_LBA);
const char *aff_part_aux(const unsigned int newline, const disk_t *disk_car, const partition_t *partition);
-void aff_part_buffer(const unsigned int newline,const disk_t *disk_car,const partition_t *partition);
+void aff_part_buffer(const unsigned int newline, const disk_t *disk_car, const partition_t *partition);
+/*@
+ @ requires valid_read_string(nptr);
+ @ assigns \nothing;
+ @*/
uint64_t atouint64(const char *nptr);
+
+/*@
+ @ requires valid_read_string(*current_cmd);
+ @ ensures valid_read_string(*current_cmd);
+ @*/
uint64_t ask_number_cli(char **current_cmd, const uint64_t val_cur, const uint64_t val_min, const uint64_t val_max, const char * _format, ...) __attribute__ ((format (printf, 5, 6)));
void screen_buffer_reset(void);
int screen_buffer_add(const char *_format, ...) __attribute__ ((format (printf, 1, 2)));
diff --git a/src/intrfn.c b/src/intrfn.c
index 7c446af..1714e2a 100644
--- a/src/intrfn.c
+++ b/src/intrfn.c
@@ -22,9 +22,13 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-
+
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_NCURSES
+#endif
+
#include <stdio.h>
-#ifdef HAVE_NCURSES
+#if defined(HAVE_NCURSES)
#include <stdarg.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -1173,13 +1177,10 @@ int end_ncurses(void)
wrefresh(stdscr);
nl();
endwin();
-#if defined(DJGPP) || defined(__MINGW32__)
-#else
-#ifdef HAVE_DELSCREEN
+#if defined(HAVE_DELSCREEN) && !defined(DJGPP) && !defined(__MINGW32__)
if(screenp!=NULL)
delscreen(screenp);
#endif
-#endif
return 0;
}
diff --git a/src/intrfn.h b/src/intrfn.h
index b49257e..6c35e90 100644
--- a/src/intrfn.h
+++ b/src/intrfn.h
@@ -24,7 +24,7 @@
extern "C" {
#endif
-#ifdef HAVE_NCURSES
+#if defined(HAVE_NCURSES) && !defined(MAIN_photorec)
#ifdef HAVE_NCURSES_H
#include <ncurses.h>
#elif defined(HAVE_NCURSESW_NCURSES_H)
diff --git a/src/iso.h b/src/iso.h
index 3567a92..674352b 100644
--- a/src/iso.h
+++ b/src/iso.h
@@ -22,7 +22,18 @@
#ifdef __cplusplus
extern "C" {
#endif
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
int check_ISO(disk_t *disk_car, partition_t *partition);
+
+/*@
+ @ requires \valid_read(iso);
+ @ requires \valid(partition);
+ @ requires separation: \separated(iso, partition);
+ @*/
int recover_ISO(const struct iso_primary_descriptor *iso, partition_t *partition);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/jfs.c b/src/jfs.c
index 4dfc4f4..fc702da 100644
--- a/src/jfs.c
+++ b/src/jfs.c
@@ -37,8 +37,42 @@
#include "log.h"
#include "guid_cpy.h"
-static int test_JFS(disk_t *disk_car, const struct jfs_superblock *sb, const partition_t *partition, const int dump_ind);
-static void set_JFS_info(const struct jfs_superblock *sb, partition_t *partition);
+static void set_JFS_info(const struct jfs_superblock *sb, partition_t *partition)
+{
+ partition->upart_type=UP_JFS;
+ partition->blocksize=le32(sb->s_bsize);
+ snprintf(partition->info, sizeof(partition->info), "JFS %u, blocksize=%u",
+ (unsigned int)le32(sb->s_version), partition->blocksize);
+ partition->fsname[0]='\0';
+ if(le32(sb->s_version)==1)
+ {
+ set_part_name(partition,sb->s_fpack,11);
+ }
+}
+
+static int test_JFS(const disk_t *disk_car, const struct jfs_superblock *sb, const partition_t *partition, const int dump_ind)
+{
+ if(memcmp(sb->s_magic,"JFS1",4)!=0)
+ return 1;
+ /* Blocksize must be a multiple of 512 */
+ if(le32(sb->s_bsize)<512 ||
+ ((le32(sb->s_bsize)-1) & le32(sb->s_bsize))!=0)
+ return 1;
+ if(dump_ind!=0)
+ {
+ log_info("\nJFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
+ /* There is a little offset ... */
+ dump_log(sb,DEFAULT_SECTOR_SIZE);
+ }
+ /*
+ if( le32(sb->s_agsize) >= (1 << L2BPERDMAP) ) {
+ return 2;
+ }
+ if(partition->part_size!=0 && (partition->part_size<le64(sb->s_size)))
+ return 8;
+ */
+ return 0;
+}
int check_JFS(disk_t *disk_car, partition_t *partition)
{
@@ -58,23 +92,10 @@ int check_JFS(disk_t *disk_car, partition_t *partition)
return 0;
}
-static void set_JFS_info(const struct jfs_superblock *sb, partition_t *partition)
-{
- partition->upart_type=UP_JFS;
- partition->blocksize=le32(sb->s_bsize);
- snprintf(partition->info, sizeof(partition->info), "JFS %u, blocksize=%u",
- (unsigned int)le32(sb->s_version), partition->blocksize);
- partition->fsname[0]='\0';
- if(le32(sb->s_version)==1)
- {
- set_part_name(partition,sb->s_fpack,11);
- }
-}
-
/*
Primary superblock is at 0x8000
*/
-int recover_JFS(disk_t *disk_car, const struct jfs_superblock *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_JFS(const disk_t *disk_car, const struct jfs_superblock *sb,partition_t *partition,const int verbose, const int dump_ind)
{
if(test_JFS(disk_car, sb, partition, dump_ind)!=0)
return 1;
@@ -100,27 +121,3 @@ int recover_JFS(disk_t *disk_car, const struct jfs_superblock *sb,partition_t *p
}
return 0;
}
-
-static int test_JFS(disk_t *disk_car, const struct jfs_superblock *sb, const partition_t *partition, const int dump_ind)
-{
- if(memcmp(sb->s_magic,"JFS1",4)!=0)
- return 1;
- /* Blocksize must be a multiple of 512 */
- if(le32(sb->s_bsize)<512 ||
- ((le32(sb->s_bsize)-1) & le32(sb->s_bsize))!=0)
- return 1;
- if(dump_ind!=0)
- {
- log_info("\nJFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
- /* There is a little offset ... */
- dump_log(sb,DEFAULT_SECTOR_SIZE);
- }
- /*
- if( le32(sb->s_agsize) >= (1 << L2BPERDMAP) ) {
- return 2;
- }
- if(partition->part_size!=0 && (partition->part_size<le64(sb->s_size)))
- return 8;
- */
- return 0;
-}
diff --git a/src/jfs.h b/src/jfs.h
index 74d38d7..1ab5589 100644
--- a/src/jfs.h
+++ b/src/jfs.h
@@ -26,8 +26,20 @@ extern "C" {
#define JFS_SUPERBLOCK_SIZE 512
#define L2BPERDMAP 13 /* l2 num of blks per dmap */
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
int check_JFS(disk_t *disk_car, partition_t *partition);
-int recover_JFS(disk_t *disk_car, const struct jfs_superblock *sb,partition_t *partition,const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(sb);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, sb, partition);
+ @*/
+int recover_JFS(const disk_t *disk_car, const struct jfs_superblock *sb, partition_t *partition, const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/list.h b/src/list.h
index 29e8dad..2abb40a 100644
--- a/src/list.h
+++ b/src/list.h
@@ -59,6 +59,17 @@ struct td_list_head {
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
+/*@
+ @ requires \valid(newe);
+ @ requires \valid(prev);
+ @ requires \valid(next);
+ @ requires separation: \separated(newe, \union(prev,next));
+ @ ensures next->prev == newe;
+ @ ensures newe->next == next;
+ @ ensures newe->prev == prev;
+ @ ensures prev->next == newe;
+ @ assigns next->prev,newe->next,newe->prev,prev->next;
+ @*/
static inline void __td_list_add(struct td_list_head *newe,
struct td_list_head *prev,
struct td_list_head *next)
@@ -67,6 +78,10 @@ static inline void __td_list_add(struct td_list_head *newe,
newe->next = next;
newe->prev = prev;
prev->next = newe;
+ /*@ assert next->prev == newe; */
+ /*@ assert newe->next == next; */
+ /*@ assert newe->prev == prev; */
+ /*@ assert prev->next == newe; */
}
/**
@@ -90,6 +105,17 @@ static inline void td_list_add(struct td_list_head *newe, struct td_list_head *h
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
+/*@
+ @ requires \valid(newe);
+ @ requires \valid(head);
+ @ requires \valid(head->prev);
+ @ requires separation: \separated(newe, head);
+ @ ensures head->prev == newe;
+ @ ensures newe->next == head;
+ @ ensures newe->prev == \old(head->prev);
+ @ ensures \old(head->prev)->next == newe;
+ @ assigns head->prev,newe->next,newe->prev,\old(head->prev)->next;
+ @*/
static inline void td_list_add_tail(struct td_list_head *newe, struct td_list_head *head)
{
__td_list_add(newe, head->prev, head);
@@ -102,10 +128,19 @@ static inline void td_list_add_tail(struct td_list_head *newe, struct td_list_he
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
+/*@
+ @ requires \valid(prev);
+ @ requires \valid(next);
+ @ ensures next->prev == prev;
+ @ ensures prev->next == next;
+ @ assigns next->prev,prev->next;
+ @*/
static inline void __td_list_del(struct td_list_head * prev, struct td_list_head * next)
{
next->prev = prev;
prev->next = next;
+ /*@ assert next->prev == prev; */
+ /*@ assert prev->next == next; */
}
/**
@@ -114,11 +149,23 @@ static inline void __td_list_del(struct td_list_head * prev, struct td_list_head
* Note: td_list_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
+/*@
+ @ requires \valid(entry);
+ @ requires \valid(entry->prev);
+ @ requires \valid(entry->next);
+ @ ensures \old(entry->prev)->next == \old(entry->next);
+ @ ensures \old(entry->next)->prev == \old(entry->prev);
+ @ assigns \old(entry->prev)->next, \old(entry->next)->prev, entry->next, entry->prev;
+ @*/
static inline void td_list_del(struct td_list_head *entry)
{
__td_list_del(entry->prev, entry->next);
+ /*@ assert entry->prev->next == entry->next; */
+ /*@ assert entry->next->prev == entry->prev; */
entry->next = (struct td_list_head*)LIST_POISON1;
entry->prev = (struct td_list_head*)LIST_POISON2;
+ /*@ assert \at(entry->prev,Pre)->next == \at(entry->next,Pre); */
+ /*@ assert \at(entry->next,Pre)->prev == \at(entry->prev,Pre); */
}
/**
@@ -372,6 +419,12 @@ static inline void td_list_splice_init(struct td_list_head *list,
td_list_entry((pos)->member.prev, typeof(*(pos)), member)
+/*@
+ @ requires \valid(newe);
+ @ requires \valid(head);
+ @ requires \valid_function(compar);
+ @ requires separation: \separated(newe, head);
+ @*/
static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
@@ -387,6 +440,12 @@ static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_
td_list_add_tail(newe, head);
}
+/*@
+ @ requires \valid(newe);
+ @ requires \valid(head);
+ @ requires \valid_function(compar);
+ @ requires separation: \separated(newe, head);
+ @*/
static inline int td_list_add_sorted_uniq(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
diff --git a/src/log.c b/src/log.c
index 84092cb..10b4599 100644
--- a/src/log.c
+++ b/src/log.c
@@ -49,13 +49,18 @@
static FILE *log_handle=NULL;
static int f_status=0;
+
+/*@
+ @ requires valid_read_string(_format);
+ @*/
static int log_handler(const char *_format, va_list ap) __attribute__((format(printf, 1, 0)));
+
/* static unsigned int log_levels=LOG_LEVEL_DEBUG|LOG_LEVEL_TRACE|LOG_LEVEL_QUIET|LOG_LEVEL_INFO|LOG_LEVEL_VERBOSE|LOG_LEVEL_PROGRESS|LOG_LEVEL_WARNING|LOG_LEVEL_ERROR|LOG_LEVEL_PERROR|LOG_LEVEL_CRITICAL; */
static unsigned int log_levels=LOG_LEVEL_TRACE|LOG_LEVEL_QUIET|LOG_LEVEL_INFO|LOG_LEVEL_VERBOSE|LOG_LEVEL_PROGRESS|LOG_LEVEL_WARNING|LOG_LEVEL_ERROR|LOG_LEVEL_PERROR|LOG_LEVEL_CRITICAL;
-int log_set_levels(const unsigned int levels)
+unsigned int log_set_levels(const unsigned int levels)
{
- const int old_levels=log_levels;
+ const unsigned int old_levels=log_levels;
log_levels=levels;
return old_levels;
}
@@ -160,7 +165,7 @@ int log_close(void)
return f_status;
}
-int log_redirect(unsigned int level, const char *format, ...)
+int log_redirect(const unsigned int level, const char *format, ...)
{
if((log_levels & level)==0)
return 0;
diff --git a/src/log.h b/src/log.h
index 8f8664b..cb91fed 100644
--- a/src/log.h
+++ b/src/log.h
@@ -25,12 +25,29 @@
extern "C" {
#endif
-int log_set_levels(const unsigned int levels);
+unsigned int log_set_levels(const unsigned int levels);
+
+/*@
+ @ requires valid_read_string(default_filename);
+ @ requires \valid(errsv);
+ @ requires separation: \separated(default_filename, errsv);
+ @*/
FILE *log_open(const char*default_filename, const int mode, int *errsv);
+
+/*@
+ @ requires \valid_read(default_filename);
+ @ requires \valid(errsv);
+ @ requires separation: \separated(default_filename, errsv);
+ @*/
FILE *log_open_default(const char*default_filename, const int mode, int *errsv);
+
int log_flush(void);
int log_close(void);
-int log_redirect(unsigned int level, const char *format, ...) __attribute__((format(printf, 2, 3)));
+
+/*@
+ @ requires valid_read_string(format);
+ @*/
+int log_redirect(const unsigned int level, const char *format, ...) __attribute__((format(printf, 2, 3)));
void dump_log(const void *nom_dump,unsigned int lng);
void dump2_log(const void *dump_1, const void *dump_2,const unsigned int lng);
diff --git a/src/luks.c b/src/luks.c
index 9704839..53b0660 100644
--- a/src/luks.c
+++ b/src/luks.c
@@ -36,8 +36,31 @@
#include "log.h"
#include "guid_cpy.h"
-static int test_LUKS(disk_t *disk_car, const struct luks_phdr *sb, const partition_t *partition, const int dump_ind);
-static void set_LUKS_info(const struct luks_phdr *sb, partition_t *partition);
+static void set_LUKS_info(const struct luks_phdr *sb, partition_t *partition)
+{
+ partition->upart_type=UP_LUKS;
+ if(partition->part_size > 0)
+ sprintf(partition->info,"LUKS %u", be16(sb->version));
+ else
+ sprintf(partition->info,"LUKS %u (Data size unknown)", be16(sb->version));
+}
+
+static int test_LUKS(const disk_t *disk_car, const struct luks_phdr *sb, const partition_t *partition, const int dump_ind)
+{
+ static const uint8_t LUKS_MAGIC[LUKS_MAGIC_L] = {'L','U','K','S', 0xba, 0xbe};
+ if(memcmp(sb->magic, LUKS_MAGIC, LUKS_MAGIC_L)!=0)
+ return 1;
+ if(dump_ind!=0)
+ {
+ if(partition!=NULL && disk_car!=NULL)
+ log_info("\nLUKS magic value at %u/%u/%u\n",
+ offset2cylinder(disk_car,partition->part_offset),
+ offset2head(disk_car,partition->part_offset),
+ offset2sector(disk_car,partition->part_offset));
+ dump_log(sb,DEFAULT_SECTOR_SIZE);
+ }
+ return 0;
+}
int check_LUKS(disk_t *disk_car,partition_t *partition)
{
@@ -57,16 +80,7 @@ int check_LUKS(disk_t *disk_car,partition_t *partition)
return 0;
}
-static void set_LUKS_info(const struct luks_phdr *sb, partition_t *partition)
-{
- partition->upart_type=UP_LUKS;
- if(partition->part_size > 0)
- sprintf(partition->info,"LUKS %u", be16(sb->version));
- else
- sprintf(partition->info,"LUKS %u (Data size unknown)", be16(sb->version));
-}
-
-int recover_LUKS(disk_t *disk_car, const struct luks_phdr *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_LUKS(const disk_t *disk_car, const struct luks_phdr *sb,partition_t *partition,const int verbose, const int dump_ind)
{
if(test_LUKS(disk_car, sb, partition, dump_ind)!=0)
return 1;
@@ -89,20 +103,3 @@ int recover_LUKS(disk_t *disk_car, const struct luks_phdr *sb,partition_t *parti
}
return 0;
}
-
-static int test_LUKS(disk_t *disk_car, const struct luks_phdr *sb, const partition_t *partition, const int dump_ind)
-{
- static const uint8_t LUKS_MAGIC[LUKS_MAGIC_L] = {'L','U','K','S', 0xba, 0xbe};
- if(memcmp(sb->magic, LUKS_MAGIC, LUKS_MAGIC_L)!=0)
- return 1;
- if(dump_ind!=0)
- {
- if(partition!=NULL && disk_car!=NULL)
- log_info("\nLUKS magic value at %u/%u/%u\n",
- offset2cylinder(disk_car,partition->part_offset),
- offset2head(disk_car,partition->part_offset),
- offset2sector(disk_car,partition->part_offset));
- dump_log(sb,DEFAULT_SECTOR_SIZE);
- }
- return 0;
-}
diff --git a/src/luks.h b/src/luks.h
index de67e4b..514c7d7 100644
--- a/src/luks.h
+++ b/src/luks.h
@@ -57,7 +57,7 @@ struct luks_phdr {
};
int check_LUKS(disk_t *disk_car, partition_t *partition);
-int recover_LUKS(disk_t *disk_car, const struct luks_phdr *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_LUKS(const disk_t *disk_car, const struct luks_phdr *sb,partition_t *partition,const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/lvm.c b/src/lvm.c
index f8375d6..7e62261 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -37,11 +37,52 @@
#include "log.h"
#include "guid_cpy.h"
-static void set_LVM_info(partition_t *partition);
-static int test_LVM(disk_t *disk_car, const pv_disk_t *pv, const partition_t *partition,const int verbose, const int dump_ind);
+static void set_LVM_info(partition_t *partition)
+{
+ partition->upart_type=UP_LVM;
+ partition->fsname[0]='\0';
+ partition->info[0]='\0';
+ snprintf(partition->info,sizeof(partition->info),"LVM");
+}
+
+static int test_LVM(const disk_t *disk_car, const pv_disk_t *pv, const partition_t *partition, const int verbose, const int dump_ind)
+{
+ if ((memcmp((const char *)pv->id,LVM_ID,sizeof(pv->id)) == 0) && (le16(pv->version) == 1 || le16(pv->version) == 2))
+ {
+ uint32_t size;
+ if(verbose>0 || dump_ind!=0)
+ {
+ log_info("\nLVM magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
+ }
+ if(dump_ind!=0)
+ {
+ /* There is a little offset ... */
+ dump_log(pv,DEFAULT_SECTOR_SIZE);
+ }
+ if (le32(pv->pv_size) > LVM_MAX_SIZE)
+ return (1);
+ if (le32(pv->pv_status) != 0 && le32(pv->pv_status) != PV_ACTIVE)
+ return (1);
+ if (le32(pv->pv_allocatable) != 0 && le32(pv->pv_allocatable) != PV_ALLOCATABLE)
+ return (1);
+ if (le32(pv->lv_cur) > MAX_LV)
+ return (1);
+ if (strlen((const char *)pv->vg_name) > NAME_LEN / 2)
+ return (1);
+ size = le32(pv->pe_size) / LVM_MIN_PE_SIZE * LVM_MIN_PE_SIZE;
+ if ((le32(pv->pe_size) != size) ||
+ (le32(pv->pe_size) < LVM_MIN_PE_SIZE) ||
+ (le32(pv->pe_size) > LVM_MAX_PE_SIZE))
+ return (1);
-static void set_LVM2_info(partition_t*partition);
-static int test_LVM2(disk_t *disk_car, const struct lvm2_label_header *lh, const partition_t *partition, const int verbose, const int dump_ind);
+ if (le32(pv->pe_total) > ( pv->pe_on_disk.size / sizeof ( disk_pe_t)))
+ return (1);
+ if (le32(pv->pe_allocated) > le32(pv->pe_total))
+ return (1);
+ return 0;
+ }
+ return 1;
+}
int check_LVM(disk_t *disk_car,partition_t *partition,const int verbose)
{
@@ -61,7 +102,7 @@ int check_LVM(disk_t *disk_car,partition_t *partition,const int verbose)
return 0;
}
-int recover_LVM(disk_t *disk_car, const pv_disk_t *pv,partition_t *partition,const int verbose, const int dump_ind)
+int recover_LVM(const disk_t *disk_car, const pv_disk_t *pv,partition_t *partition,const int verbose, const int dump_ind)
{
if(test_LVM(disk_car,pv,partition,verbose,dump_ind)!=0)
return 1;
@@ -79,53 +120,34 @@ int recover_LVM(disk_t *disk_car, const pv_disk_t *pv,partition_t *partition,con
return 0;
}
-static int test_LVM(disk_t *disk_car, const pv_disk_t *pv, const partition_t *partition, const int verbose, const int dump_ind)
+static void set_LVM2_info(partition_t*partition)
{
- if ((memcmp((const char *)pv->id,LVM_ID,sizeof(pv->id)) == 0) && (le16(pv->version) == 1 || le16(pv->version) == 2))
+ partition->upart_type=UP_LVM2;
+ partition->fsname[0]='\0';
+ partition->info[0]='\0';
+ snprintf(partition->info,sizeof(partition->info),"LVM2");
+}
+
+static int test_LVM2(const disk_t *disk_car, const struct lvm2_label_header *lh, const partition_t *partition, const int verbose, const int dump_ind)
+{
+ if (memcmp((const char *)lh->type,LVM2_LABEL,sizeof(lh->type)) == 0)
{
- uint32_t size;
if(verbose>0 || dump_ind!=0)
{
- log_info("\nLVM magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
+ log_info("\nLVM2 magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
}
+ if(le32(lh->offset_xl)>400)
+ return 1;
if(dump_ind!=0)
{
/* There is a little offset ... */
- dump_log(pv,DEFAULT_SECTOR_SIZE);
+ dump_log(lh,DEFAULT_SECTOR_SIZE);
}
- if (le32(pv->pv_size) > LVM_MAX_SIZE)
- return (1);
- if (le32(pv->pv_status) != 0 && le32(pv->pv_status) != PV_ACTIVE)
- return (1);
- if (le32(pv->pv_allocatable) != 0 && le32(pv->pv_allocatable) != PV_ALLOCATABLE)
- return (1);
- if (le32(pv->lv_cur) > MAX_LV)
- return (1);
- if (strlen((const char *)pv->vg_name) > NAME_LEN / 2)
- return (1);
- size = le32(pv->pe_size) / LVM_MIN_PE_SIZE * LVM_MIN_PE_SIZE;
- if ((le32(pv->pe_size) != size) ||
- (le32(pv->pe_size) < LVM_MIN_PE_SIZE) ||
- (le32(pv->pe_size) > LVM_MAX_PE_SIZE))
- return (1);
-
- if (le32(pv->pe_total) > ( pv->pe_on_disk.size / sizeof ( disk_pe_t)))
- return (1);
- if (le32(pv->pe_allocated) > le32(pv->pe_total))
- return (1);
return 0;
}
return 1;
}
-static void set_LVM_info(partition_t *partition)
-{
- partition->upart_type=UP_LVM;
- partition->fsname[0]='\0';
- partition->info[0]='\0';
- snprintf(partition->info,sizeof(partition->info),"LVM");
-}
-
int check_LVM2(disk_t *disk_car,partition_t