summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/file_tar.c89
-rw-r--r--src/file_tar.h27
-rw-r--r--src/phbs.c2
-rw-r--r--src/photorec_check_header.h2
-rw-r--r--src/qphbs.cpp2
5 files changed, 93 insertions, 29 deletions
diff --git a/src/file_tar.c b/src/file_tar.c
index 1056584..bfea497 100644
--- a/src/file_tar.c
+++ b/src/file_tar.c
@@ -34,6 +34,8 @@
#include "file_tar.h"
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};
+static const unsigned char tar_header_posix[8] = { 'u','s','t','a','r',' ',' ',0x00};
const file_hint_t file_hint_tar= {
.extension="tar",
@@ -44,26 +46,63 @@ const file_hint_t file_hint_tar= {
.register_header_check=&register_header_check_tar
};
-struct posix_header
-{ /* byte offset */
- char name[100]; /* 0 */
- char mode[8]; /* 100 */
- char uid[8]; /* 108 */
- char gid[8]; /* 116 */
- char size[12]; /* 124 */
- char mtime[12]; /* 136 */
- char chksum[8]; /* 148 */
- char typeflag; /* 156 */
- char linkname[100]; /* 157 */
- char magic[6]; /* 257 */
- char version[2]; /* 263 */
- char uname[32]; /* 265 */
- char gname[32]; /* 297 */
- char devmajor[8]; /* 329 */
- char devminor[8]; /* 337 */
- char prefix[155]; /* 345 */
- /* 500 */
-};
+/*@
+ @ requires \valid_read(h);
+ @ assigns \nothing;
+ @*/
+static int is_valid_checksum_format(const struct tar_posix_header *h)
+{
+ unsigned int i;
+ int space_allowed=1;
+ int all_null=1;
+ /* No checksum ? */
+ /*@
+ @ loop assigns i,all_null;
+ @*/
+ for(i=0; i<8; i++)
+ if(h->chksum[i]!=0)
+ all_null=0;
+ if(all_null!=0)
+ return 1;
+ /*
+ * Checksum should be stored as a six digit octal number with leading zeroes followed by a NUL and then a space.
+ * Various implementations do not adhere to this format, try to handle them
+ */
+ /*@
+ @ loop assigns i,space_allowed;
+ @*/
+ for(i=0; i<6; i++)
+ {
+ if(h->chksum[i] >= '0' || h->chksum[i] <= '7')
+ {
+ space_allowed=0;
+ continue;
+ }
+ if(h->chksum[i] == ' ')
+ {
+ if(space_allowed == 0)
+ return 0;
+ }
+ else
+ return 0;
+ }
+ if(h->chksum[6] == 0 || h->chksum[7] == ' ')
+ return 1;
+ if((h->chksum[6] >= '0' || h->chksum[6] <= '7') && h->chksum[7] == ' ')
+ return 1;
+ return 0;
+}
+
+int is_valid_tar_header(const struct tar_posix_header *h)
+{
+ /* Do not remove this check. */
+ if(memcmp(&h->magic,tar_header_gnu,sizeof(tar_header_gnu))!=0 &&
+ memcmp(&h->magic,tar_header_posix,sizeof(tar_header_posix))!=0)
+ return 0;
+ if(is_valid_checksum_format(h)==0)
+ return 0;
+ return 1;
+}
/*@
@ requires buffer_size >= 512;
@@ -74,10 +113,10 @@ struct posix_header
@ 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)
+static 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;
- if(!isspace(h->chksum[0]) && !((unsigned) (h->chksum[0]) - '0' <= 7))
+ const struct tar_posix_header *h=(const struct tar_posix_header *)buffer;
+ if(is_valid_tar_header(h)==0)
return 0;
if(file_recovery->file_stat!=NULL && file_recovery->file_stat->file_hint==&file_hint_tar)
{
@@ -95,9 +134,9 @@ int header_check_tar(const unsigned char *buffer, const unsigned int buffer_size
@*/
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};
- static const unsigned char tar_header_posix[8] = { 'u','s','t','a','r',' ',' ',0x00};
register_header_check(0x101, tar_header_gnu,sizeof(tar_header_gnu), &header_check_tar, file_stat);
+#ifndef __FRAMAC__
register_header_check(0x101, tar_header_posix,sizeof(tar_header_posix), &header_check_tar, file_stat);
+#endif
}
#endif
diff --git a/src/file_tar.h b/src/file_tar.h
index 18528a6..85e02c4 100644
--- a/src/file_tar.h
+++ b/src/file_tar.h
@@ -25,7 +25,32 @@
extern "C" {
#endif
-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);
+struct tar_posix_header
+{ /* byte offset */
+ char name[100]; /* 0 */
+ char mode[8]; /* 100 */
+ char uid[8]; /* 108 */
+ char gid[8]; /* 116 */
+ char size[12]; /* 124 */
+ char mtime[12]; /* 136 */
+ char chksum[8]; /* 148 */
+ char typeflag; /* 156 */
+ char linkname[100]; /* 157 */
+ char magic[6]; /* 257 */
+ char version[2]; /* 263 */
+ char uname[32]; /* 265 */
+ char gname[32]; /* 297 */
+ char devmajor[8]; /* 329 */
+ char devminor[8]; /* 337 */
+ char prefix[155]; /* 345 */
+ /* 500 */
+};
+
+/*@
+ @ requires \valid_read(h);
+ @ assigns \nothing;
+ @*/
+int is_valid_tar_header(const struct tar_posix_header *h);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/phbs.c b/src/phbs.c
index 1962d09..ad08d20 100644
--- a/src/phbs.c
+++ b/src/phbs.c
@@ -103,7 +103,7 @@ pstatus_t photorec_find_blocksize(struct ph_param *params, const struct ph_optio
file_recovery_new.blocksize=blocksize;
file_recovery_new.location.start=offset;
if(file_recovery.file_stat!=NULL && file_recovery.file_stat->file_hint==&file_hint_tar &&
- header_check_tar(buffer-0x200,0x200,0,&file_recovery,&file_recovery_new))
+ is_valid_tar_header((const struct tar_posix_header *)(buffer-0x200)))
{ /* Currently saving a tar, do not check the data for know header */
}
else
diff --git a/src/photorec_check_header.h b/src/photorec_check_header.h
index 1aecd86..203641e 100644
--- a/src/photorec_check_header.h
+++ b/src/photorec_check_header.h
@@ -146,7 +146,7 @@ inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, st
file_recovery_new.blocksize=blocksize;
file_recovery_new.location.start=offset;
if(file_recovery->file_stat!=NULL && file_recovery->file_stat->file_hint==&file_hint_tar &&
- header_check_tar(buffer-0x200,0x200, 0, file_recovery, &file_recovery_new))
+ is_valid_tar_header((const struct tar_posix_header *)(buffer-0x200)))
{ /* Currently saving a tar, do not check the data for know header */
if(options->verbose > 1)
{
diff --git a/src/qphbs.cpp b/src/qphbs.cpp
index e0e6438..4c496e4 100644
--- a/src/qphbs.cpp
+++ b/src/qphbs.cpp
@@ -98,7 +98,7 @@ pstatus_t QPhotorec::photorec_find_blocksize(alloc_data_t *list_search_space)
{
file_recovery_t file_recovery_new;
if(file_recovery.file_stat!=NULL && file_recovery.file_stat->file_hint==&file_hint_tar &&
- header_check_tar(buffer-0x200,0x200,0,&file_recovery,&file_recovery_new))
+ is_valid_tar_header((const struct tar_posix_header *)(buffer-0x200)))
{ /* Currently saving a tar, do not check the data for know header */
}
else