PhotoRec: TIFF parser, use 0xffffffffffffffff via a constant instead of -1 as error value

This commit is contained in:
Christophe Grenier 2019-09-03 08:39:19 +02:00
parent 90932d8b4b
commit 8d1de543f4
4 changed files with 89 additions and 78 deletions

View file

@ -184,7 +184,7 @@ void file_check_tiff(file_recovery_t *fr)
log_info("TIFF Current %llu\n", (unsigned long long)fr->file_size);
log_info("TIFF Estimated %llu %llx\n", (unsigned long long)calculated_file_size, (unsigned long long)calculated_file_size);
#endif
if(fr->file_size < calculated_file_size || calculated_file_size==0)
if(fr->file_size < calculated_file_size || calculated_file_size==0 || calculated_file_size==TIFF_ERROR)
fr->file_size=0;
/* PhotoRec isn't yet capable to find the correct filesize for
* Sony arw and dng,

View file

@ -22,6 +22,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#define TIFF_ERROR 0xffffffffffffffff
#define TIFF_BIGENDIAN 0x4d4d
#define TIFF_LITTLEENDIAN 0x4949

View file

@ -76,7 +76,7 @@ const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const unsigned
return NULL;
ifd0=(const struct ifd_header *)((const char*)tiff + be32(tiff->tiff_diroff));
/* Bound checking */
if((const char*)ifd0 < (const char*)tiff ||
if((const char*)ifd0 <= (const char*)tiff ||
(const char*)(ifd0+1) > (const char*)tiff + tiff_size)
return NULL;
{
@ -85,7 +85,8 @@ const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const unsigned
return tmp;
}
exififd=(const struct ifd_header *)find_tag_from_tiff_header_be_aux(tiff, tiff_size, TIFFTAG_EXIFIFD, potential_error, ifd0);
if(exififd!=NULL)
if((const char *)exififd > (const char *)tiff &&
(const char *)(exififd + 1) <= (const char *)tiff + tiff_size)
{
/* Exif */
const char *tmp=find_tag_from_tiff_header_be_aux(tiff, tiff_size, tag, potential_error, exififd);
@ -93,13 +94,17 @@ const char *find_tag_from_tiff_header_be(const TIFFHeader *tiff, const unsigned
return tmp;
}
tiff_next_diroff=(const uint32_t *)(&ifd0->ifd + be16(ifd0->nbr_fields));
if( (const char *)tiff_next_diroff >= (const char *)tiff &&
(const char *)(tiff_next_diroff + 1) < (const char*)tiff + tiff_size &&
if( (const char *)tiff_next_diroff > (const char *)tiff &&
(const char *)(tiff_next_diroff + 1) <= (const char*)tiff + tiff_size &&
be32(*tiff_next_diroff)>0)
{
/* IFD1 */
const struct ifd_header *ifd1=(const struct ifd_header*)((const char *)tiff+be32(*tiff_next_diroff));
return find_tag_from_tiff_header_be_aux(tiff, tiff_size, tag, potential_error, ifd1);
if((const char *)ifd1 > (const char *)tiff &&
(const char *)(ifd1 + 1) <= (const char *)tiff + tiff_size)
{
return find_tag_from_tiff_header_be_aux(tiff, tiff_size, tag, potential_error, ifd1);
}
}
return NULL;
}
@ -114,17 +119,17 @@ static uint64_t parse_strip_be(FILE *handle, const TIFFDirEntry *entry_strip_off
uint32_t *sizep;
uint64_t max_offset=0;
if(be32(entry_strip_offsets->tdir_count) != be32(entry_strip_bytecounts->tdir_count))
return -1;
return TIFF_ERROR;
if(be32(entry_strip_offsets->tdir_count)==0 ||
be16(entry_strip_offsets->tdir_type)!=4 ||
be16(entry_strip_bytecounts->tdir_type)!=4)
return -1;
return TIFF_ERROR;
offsetp=(uint32_t *)MALLOC(nbr*sizeof(*offsetp));
if(fseek(handle, be32(entry_strip_offsets->tdir_offset), SEEK_SET) < 0 ||
fread(offsetp, sizeof(*offsetp), nbr, handle) != nbr)
{
free(offsetp);
return -1;
return TIFF_ERROR;
}
sizep=(uint32_t *)MALLOC(nbr*sizeof(*sizep));
if(fseek(handle, be32(entry_strip_bytecounts->tdir_offset), SEEK_SET) < 0 ||
@ -132,7 +137,7 @@ static uint64_t parse_strip_be(FILE *handle, const TIFFDirEntry *entry_strip_off
{
free(offsetp);
free(sizep);
return -1;
return TIFF_ERROR;
}
for(i=0; i<nbr; i++)
{
@ -182,12 +187,12 @@ static uint64_t tiff_be_makernote(FILE *in, const uint32_t tiff_diroff)
uint64_t tile_bytecounts=0;
const TIFFDirEntry *entry;
if(tiff_diroff < sizeof(TIFFHeader))
return -1;
return TIFF_ERROR;
if(fseek(in, tiff_diroff, SEEK_SET) < 0)
return -1;
return TIFF_ERROR;
data_read=fread(buffer, 1, sizeof(buffer), in);
if(data_read<2)
return -1;
return TIFF_ERROR;
if( memcmp(buffer, sign_nikon1, sizeof(sign_nikon1))==0 ||
memcmp(buffer, sign_nikon2, sizeof(sign_nikon2))==0 ||
memcmp(buffer, sign_pentax, sizeof(sign_pentax))==0 )
@ -201,7 +206,7 @@ static uint64_t tiff_be_makernote(FILE *in, const uint32_t tiff_diroff)
if(n > (unsigned)(data_read-2)/12)
n=(data_read-2)/12;
if(n==0)
return -1;
return TIFF_ERROR;
for(i=0;i<n;i++)
{
const uint64_t val=(uint64_t)be32(entry->tdir_count) * tiff_type2size(be16(entry->tdir_type));
@ -220,7 +225,7 @@ static uint64_t tiff_be_makernote(FILE *in, const uint32_t tiff_diroff)
{
const uint64_t new_offset=be32(entry->tdir_offset)+val;
if(new_offset==0)
return -1;
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -287,16 +292,16 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
log_info("header_check_tiff_be(fr, %lu, %u, %u)\n", (long unsigned)tiff_diroff, depth, count);
#endif
if(depth>4)
return -1;
return TIFF_ERROR;
if(count>16)
return -1;
return TIFF_ERROR;
if(tiff_diroff < sizeof(TIFFHeader))
return -1;
return TIFF_ERROR;
if(fseek(fr->handle, tiff_diroff, SEEK_SET) < 0)
return -1;
return TIFF_ERROR;
data_read=fread(buffer, 1, sizeof(buffer), fr->handle);
if(data_read<2)
return -1;
return TIFF_ERROR;
n=(buffer[0]<<8)+buffer[1];
#ifdef DEBUG_TIFF
log_info("header_check_tiff_be(fr, %lu, %u, %u) => %u entries\n", (long unsigned)tiff_diroff, depth, count, n);
@ -305,7 +310,7 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(n > (unsigned)(data_read-2)/12)
n=(data_read-2)/12;
if(n==0)
return -1;
return TIFF_ERROR;
for(i=0;i<n;i++)
{
const unsigned int tdir_tag=be16(entry->tdir_tag);
@ -326,13 +331,13 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
{ /* Entries must be sorted by tag */
sorted_tag_error++;
if(sorted_tag_error > 1)
return -1;
return TIFF_ERROR;
}
if(val>4)
{
const uint64_t new_offset=be32(entry->tdir_offset)+val;
if(new_offset==0)
return -1;
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -355,8 +360,8 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
case TIFFTAG_KODAKIFD:
{
const uint64_t new_offset=header_check_tiff_be(fr, tmp, depth+1, 0);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -364,8 +369,8 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
case TIFFTAG_SUBIFD:
{
const uint64_t new_offset=header_check_tiff_be(fr, tmp, depth+1, 0);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -374,8 +379,8 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
case EXIFTAG_MAKERNOTE:
{
const uint64_t new_offset=tiff_be_makernote(fr->handle, tmp);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -397,21 +402,21 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
uint32_t *subifd_offsetp;
if(fseek(fr->handle, be32(entry->tdir_offset), SEEK_SET) < 0)
{
return -1;
return TIFF_ERROR;
}
subifd_offsetp=(uint32_t *)MALLOC(nbr*sizeof(*subifd_offsetp));
if(fread(subifd_offsetp, sizeof(*subifd_offsetp), nbr, fr->handle) != nbr)
{
free(subifd_offsetp);
return -1;
return TIFF_ERROR;
}
for(j=0; j<nbr; j++)
{
const uint64_t new_offset=header_check_tiff_be(fr, be32(subifd_offsetp[j]), depth+1, 0);
if(new_offset==-1)
if(new_offset==TIFF_ERROR)
{
free(subifd_offsetp);
return -1;
return TIFF_ERROR;
}
if(max_offset < new_offset)
max_offset = new_offset;
@ -451,16 +456,16 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(entry_strip_offsets != NULL && entry_strip_bytecounts != NULL)
{
const uint64_t tmp=parse_strip_be(fr->handle, entry_strip_offsets, entry_strip_bytecounts);
if(tmp==-1)
return -1;
if(tmp==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < tmp)
max_offset=tmp;
}
if(entry_tile_offsets != NULL && entry_tile_bytecounts != NULL)
{
const uint64_t tmp=parse_strip_be(fr->handle, entry_tile_offsets, entry_tile_bytecounts);
if(tmp==-1)
return -1;
if(tmp==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < tmp)
max_offset=tmp;
}
@ -468,7 +473,7 @@ uint64_t header_check_tiff_be(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(be32(*tiff_next_diroff) > 0)
{
const uint64_t new_offset=header_check_tiff_be(fr, be32(*tiff_next_diroff), depth+1, count+1);
if(new_offset != -1 && max_offset < new_offset)
if(new_offset != TIFF_ERROR && max_offset < new_offset)
max_offset=new_offset;
}
return max_offset;

View file

@ -77,7 +77,7 @@ const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned
return NULL;
ifd0=(const struct ifd_header *)((const char*)tiff + le32(tiff->tiff_diroff));
/* Bound checking */
if((const char*)ifd0 < (const char*)tiff ||
if((const char*)ifd0 <= (const char*)tiff ||
(const char*)(ifd0+1) > (const char*)tiff + tiff_size)
return NULL;
{
@ -86,7 +86,8 @@ const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned
return tmp;
}
exififd=(const struct ifd_header *)find_tag_from_tiff_header_le_aux(tiff, tiff_size, TIFFTAG_EXIFIFD, potential_error, ifd0);
if(exififd!=NULL)
if((const char *)exififd > (const char *)tiff &&
(const char *)(exififd + 1) <= (const char *)tiff + tiff_size)
{
/* Exif */
const char *tmp=find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, exififd);
@ -94,13 +95,17 @@ const char *find_tag_from_tiff_header_le(const TIFFHeader *tiff, const unsigned
return tmp;
}
tiff_next_diroff=(const uint32_t *)(&ifd0->ifd + le16(ifd0->nbr_fields));
if( (const char *)tiff_next_diroff >= (const char *)tiff &&
(const char *)(tiff_next_diroff + 1) < (const char*)tiff + tiff_size &&
if( (const char *)tiff_next_diroff > (const char *)tiff &&
(const char *)(tiff_next_diroff + 1) <= (const char*)tiff + tiff_size &&
le32(*tiff_next_diroff)>0)
{
/* IFD1 */
const struct ifd_header *ifd1=(const struct ifd_header*)((const char *)tiff+le32(*tiff_next_diroff));
return find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, ifd1);
if((const char *)ifd1 > (const char *)tiff &&
(const char *)(ifd1 + 1) <= (const char *)tiff + tiff_size)
{
return find_tag_from_tiff_header_le_aux(tiff, tiff_size, tag, potential_error, ifd1);
}
}
return NULL;
}
@ -115,17 +120,17 @@ static uint64_t parse_strip_le(FILE *handle, const TIFFDirEntry *entry_strip_off
uint32_t *sizep;
uint64_t max_offset=0;
if(le32(entry_strip_offsets->tdir_count) != le32(entry_strip_bytecounts->tdir_count))
return -1;
return TIFF_ERROR;
if(le32(entry_strip_offsets->tdir_count)==0 ||
le16(entry_strip_offsets->tdir_type)!=4 ||
le16(entry_strip_bytecounts->tdir_type)!=4)
return -1;
return TIFF_ERROR;
offsetp=(uint32_t *)MALLOC(nbr*sizeof(*offsetp));
if(fseek(handle, le32(entry_strip_offsets->tdir_offset), SEEK_SET) < 0 ||
fread(offsetp, sizeof(*offsetp), nbr, handle) != nbr)
{
free(offsetp);
return -1;
return TIFF_ERROR;
}
sizep=(uint32_t *)MALLOC(nbr*sizeof(*sizep));
if(fseek(handle, le32(entry_strip_bytecounts->tdir_offset), SEEK_SET) < 0 ||
@ -133,7 +138,7 @@ static uint64_t parse_strip_le(FILE *handle, const TIFFDirEntry *entry_strip_off
{
free(offsetp);
free(sizep);
return -1;
return TIFF_ERROR;
}
for(i=0; i<nbr; i++)
{
@ -183,12 +188,12 @@ static uint64_t tiff_le_makernote(FILE *in, const uint32_t tiff_diroff)
uint64_t tile_bytecounts=0;
const TIFFDirEntry *entry;
if(tiff_diroff < sizeof(TIFFHeader))
return -1;
return TIFF_ERROR;
if(fseek(in, tiff_diroff, SEEK_SET) < 0)
return -1;
return TIFF_ERROR;
data_read=fread(buffer, 1, sizeof(buffer), in);
if(data_read<2)
return -1;
return TIFF_ERROR;
if( memcmp(buffer, sign_nikon1, sizeof(sign_nikon1))==0 ||
memcmp(buffer, sign_nikon2, sizeof(sign_nikon2))==0 ||
memcmp(buffer, sign_pentax, sizeof(sign_pentax))==0 )
@ -199,10 +204,10 @@ static uint64_t tiff_le_makernote(FILE *in, const uint32_t tiff_diroff)
log_info("tiff_le_makernote(%lu) => %u entries\n", (long unsigned)tiff_diroff, n);
#endif
//sizeof(TIFFDirEntry)=12;
if(n > (unsigned)(data_read-2)/12)
if(n > (unsigned int)(data_read-2)/12)
n=(data_read-2)/12;
if(n==0)
return -1;
return TIFF_ERROR;
for(i=0;i<n;i++)
{
const uint64_t val=(uint64_t)le32(entry->tdir_count) * tiff_type2size(le16(entry->tdir_type));
@ -221,7 +226,7 @@ static uint64_t tiff_le_makernote(FILE *in, const uint32_t tiff_diroff)
{
const uint64_t new_offset=le32(entry->tdir_offset)+val;
if(new_offset==0)
return -1;
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -288,16 +293,16 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
log_info("header_check_tiff_le(fr, %lu, %u, %u)\n", (long unsigned)tiff_diroff, depth, count);
#endif
if(depth>4)
return -1;
return TIFF_ERROR;
if(count>16)
return -1;
return TIFF_ERROR;
if(tiff_diroff < sizeof(TIFFHeader))
return -1;
return TIFF_ERROR;
if(fseek(fr->handle, tiff_diroff, SEEK_SET) < 0)
return -1;
return TIFF_ERROR;
data_read=fread(buffer, 1, sizeof(buffer), fr->handle);
if(data_read<2)
return -1;
return TIFF_ERROR;
n=buffer[0]+(buffer[1]<<8);
#ifdef DEBUG_TIFF
log_info("header_check_tiff_le(fr, %lu, %u, %u) => %u entries\n", (long unsigned)tiff_diroff, depth, count, n);
@ -306,7 +311,7 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(n > (unsigned)(data_read-2)/12)
n=(data_read-2)/12;
if(n==0)
return -1;
return TIFF_ERROR;
for(i=0;i<n;i++)
{
const unsigned int tdir_tag=le16(entry->tdir_tag);
@ -327,13 +332,13 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
{ /* Entries must be sorted by tag, some SR2 file doesn't respected this rule */
sorted_tag_error++;
if(sorted_tag_error > 1 && strcmp(fr->extension,"sr2")!=0)
return -1;
return TIFF_ERROR;
}
if(val>4)
{
const uint64_t new_offset=le32(entry->tdir_offset)+val;
if(new_offset==0)
return -1;
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -356,8 +361,8 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
case TIFFTAG_KODAKIFD:
{
const uint64_t new_offset=header_check_tiff_le(fr, tmp, depth+1, 0);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -372,8 +377,8 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
else
{
const uint64_t new_offset=header_check_tiff_le(fr, tmp, depth+1, 0);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -382,8 +387,8 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
case EXIFTAG_MAKERNOTE:
{
const uint64_t new_offset=tiff_le_makernote(fr->handle, tmp);
if(new_offset==-1)
return -1;
if(new_offset==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < new_offset)
max_offset=new_offset;
}
@ -405,21 +410,21 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
uint32_t *subifd_offsetp;
if(fseek(fr->handle, le32(entry->tdir_offset), SEEK_SET) < 0)
{
return -1;
return TIFF_ERROR;
}
subifd_offsetp=(uint32_t *)MALLOC(nbr*sizeof(*subifd_offsetp));
if(fread(subifd_offsetp, sizeof(*subifd_offsetp), nbr, fr->handle) != nbr)
{
free(subifd_offsetp);
return -1;
return TIFF_ERROR;
}
for(j=0; j<nbr; j++)
{
const uint64_t new_offset=header_check_tiff_le(fr, le32(subifd_offsetp[j]), depth+1, 0);
if(new_offset==-1)
if(new_offset==TIFF_ERROR)
{
free(subifd_offsetp);
return -1;
return TIFF_ERROR;
}
if(max_offset < new_offset)
max_offset = new_offset;
@ -459,16 +464,16 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(entry_strip_offsets != NULL && entry_strip_bytecounts != NULL)
{
const uint64_t tmp=parse_strip_le(fr->handle, entry_strip_offsets, entry_strip_bytecounts);
if(tmp==-1)
return -1;
if(tmp==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < tmp)
max_offset=tmp;
}
if(entry_tile_offsets != NULL && entry_tile_bytecounts != NULL)
{
const uint64_t tmp=parse_strip_le(fr->handle, entry_tile_offsets, entry_tile_bytecounts);
if(tmp==-1)
return -1;
if(tmp==TIFF_ERROR)
return TIFF_ERROR;
if(max_offset < tmp)
max_offset=tmp;
}
@ -476,7 +481,7 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
if(le32(*tiff_next_diroff) > 0)
{
const uint64_t new_offset=header_check_tiff_le(fr, le32(*tiff_next_diroff), depth+1, count+1);
if(new_offset != -1 && max_offset < new_offset)
if(new_offset != TIFF_ERROR && max_offset < new_offset)
max_offset=new_offset;
}
return max_offset;
@ -484,7 +489,7 @@ uint64_t header_check_tiff_le(file_recovery_t *fr, const uint32_t tiff_diroff, c
int header_check_tiff_le_new(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 raf_fp[15]={0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0, 0x0d, 0x00, 0x01};
const unsigned char raf_fp[15]={0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xf0, 0x0d, 0x00, 0x01};
const char *potential_error=NULL;
const TIFFHeader *header=(const TIFFHeader *)buffer;
if((uint32_t)le32(header->tiff_diroff) < sizeof(TIFFHeader))
@ -526,7 +531,7 @@ int header_check_tiff_le_new(const unsigned char *buffer, const unsigned int buf
file_recovery_new->extension="sr2";
else if(strncmp(tag_make, "SONY ",5)==0)
file_recovery_new->extension="arw";
else if(memcmp(tag_make, "NIKON CORPORATION", 18)==0)
else if(tag_make < (const char *)buffer + buffer_size - 18 && memcmp(tag_make, "NIKON CORPORATION", 18)==0)
file_recovery_new->extension="nef";
}
}