PhotoRec: fix an out of bound memory read in src/file_jpg.c

Thanks to Adel KHALDI from Blue Frost Security GmbH for reporting the problem.
This commit is contained in:
Christophe Grenier 2017-06-18 15:19:50 +02:00
parent 607c909d79
commit 6ac98cc960

View file

@ -1055,8 +1055,15 @@ static unsigned int jpg_find_border(const unsigned int output_scanline, const un
#define JPG_MAX_OFFSETS 10240
/* FIXME: it doesn handle correctly when there is a few extra sectors */
static uint64_t jpg_find_error(FILE *handle, const unsigned int output_scanline, const unsigned int output_width, const unsigned int output_components, const unsigned char *frame, const unsigned int *offsets, const uint64_t offset, const unsigned int blocksize, const uint64_t checkpoint_offset)
static uint64_t jpg_find_error(struct jpeg_session_struct *jpeg_session, const unsigned int *offsets, const uint64_t checkpoint_offset)
{
FILE *handle = jpeg_session->handle;
const unsigned int output_scanline = jpeg_session->cinfo.output_scanline;
const unsigned int output_width = jpeg_session->output_width;
const unsigned int output_components = jpeg_session->output_components;
//const unsigned int blocksize = jpeg_session->blocksize;
const unsigned char *frame = jpeg_session->frame;
const uint64_t offset = jpeg_session->offset;
const unsigned int row_stride = output_width * output_components;
unsigned int result=0;
unsigned int result_max=0;
@ -1068,6 +1075,8 @@ static uint64_t jpg_find_error(FILE *handle, const unsigned int output_scanline,
unsigned int output_scanline_max;
if(output_scanline/8 >= JPG_MAX_OFFSETS)
return 0;
if(jpeg_session->output_height < 10)
return 0;
output_scanline_max=jpg_find_border(output_scanline, output_width, output_components, frame);
for(i = 0, pos_new= 8 * row_stride;
i < row_stride;
@ -1166,7 +1175,7 @@ static uint64_t jpg_check_thumb(FILE *infile, const uint64_t offset, const unsig
offset_error=jpeg_session.offset + src->file_size - src->pub.bytes_in_buffer;
if(jpeg_session.frame!=NULL && jpeg_session.flags!=0)
{
const uint64_t tmp=jpg_find_error(jpeg_session.handle, jpeg_session.cinfo.output_scanline, jpeg_session.output_width, jpeg_session.output_components, jpeg_session.frame, &offsets[0], jpeg_session.offset, blocksize, checkpoint_offset);
const uint64_t tmp=jpg_find_error(&jpeg_session, &offsets[0], checkpoint_offset);
// log_info("jpg_check_thumb jpeg corrupted near %llu\n", offset_error);
if(tmp !=0 && offset_error > tmp)
offset_error=tmp;
@ -1177,9 +1186,9 @@ static uint64_t jpg_check_thumb(FILE *infile, const uint64_t offset, const unsig
}
memset(offsets, 0, sizeof(offsets));
jpeg_session_start(&jpeg_session);
jpeg_session.frame = (unsigned char*)MALLOC(jpeg_session.output_height * jpeg_session.row_stride);
jpeg_session.frame = (unsigned char*)MALLOC((jpeg_session.output_height+1) * jpeg_session.row_stride);
/* 0x100/2=0x80, medium value */
memset(jpeg_session.frame, 0x80, jpeg_session.row_stride * jpeg_session.cinfo.output_height);
memset(jpeg_session.frame, 0x80, jpeg_session.row_stride * (jpeg_session.cinfo.output_height+1));
while (jpeg_session.cinfo.output_scanline < jpeg_session.cinfo.output_height)
{
JSAMPROW row_pointer[1];
@ -1244,7 +1253,7 @@ static void jpg_check_picture(file_recovery_t *file_recovery)
#if 1
if(jpeg_session.frame!=NULL && jpeg_session.flags!=0)
{
const uint64_t offset_error=jpg_find_error(jpeg_session.handle, jpeg_session.cinfo.output_scanline, jpeg_session.output_width, jpeg_session.output_components, jpeg_session.frame, &offsets[0], jpeg_session.offset, jpeg_session.blocksize, file_recovery->checkpoint_offset);
const uint64_t offset_error=jpg_find_error(&jpeg_session, &offsets[0], file_recovery->checkpoint_offset);
if(offset_error !=0 && file_recovery->offset_error > offset_error)
file_recovery->offset_error=offset_error;
#ifdef DEBUG_JPEG