* The EXIF parser now keeps a set of visited offsets to avoid entering endless

loops with corrupted data.
* This fixes bug #2206.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25447 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-05-11 12:28:01 +00:00
parent fdeee1a708
commit 2f00291de2
2 changed files with 34 additions and 15 deletions

View File

@ -1,18 +1,19 @@
/*
* Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2007-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "exif_parser.h"
#include <ReadHelper.h>
#include <ctype.h>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <Message.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <ReadHelper.h>
enum {
@ -37,8 +38,8 @@ static const size_t kNumDefaultTags = sizeof(kDefaultTags)
/ sizeof(kDefaultTags[0]);
static status_t parse_tiff_directory(TReadHelper& read, BMessage& target,
const convert_tag* tags, size_t tagCount);
static status_t parse_tiff_directory(TReadHelper& read, set<off_t>& visited,
BMessage& target, const convert_tag* tags, size_t tagCount);
static status_t
@ -226,10 +227,16 @@ parse_tiff_tag(TReadHelper& read, tiff_tag& tag, off_t& offset)
static status_t
parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
const convert_tag* convertTags, size_t convertTagCount)
parse_tiff_directory(TReadHelper& read, set<off_t>& visited, off_t offset,
BMessage& target, const convert_tag* convertTags, size_t convertTagCount)
{
if (visited.find(offset) != visited.end()) {
// The EXIF data is obviously corrupt
return B_BAD_DATA;
}
read.Seek(offset, SEEK_SET);
visited.insert(offset);
uint16 tags;
read(tags);
@ -247,7 +254,7 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
case TAG_EXIF_OFFSET:
case TAG_SUB_DIR_OFFSET:
{
status_t status = parse_tiff_directory(read, target,
status_t status = parse_tiff_directory(read, visited, target,
convertTags, convertTagCount);
if (status < B_OK)
return status;
@ -263,7 +270,12 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
}
break;
}
if (visited.find(nextOffset) != visited.end())
return B_BAD_DATA;
read.Seek(nextOffset, SEEK_SET);
visited.insert(nextOffset);
}
return B_OK;
@ -271,7 +283,7 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
static status_t
parse_tiff_directory(TReadHelper& read, BMessage& target,
parse_tiff_directory(TReadHelper& read, set<off_t>& visited, BMessage& target,
const convert_tag* tags, size_t tagCount)
{
while (true) {
@ -280,7 +292,7 @@ parse_tiff_directory(TReadHelper& read, BMessage& target,
if (offset == 0)
break;
status_t status = parse_tiff_directory(read, offset, target,
status_t status = parse_tiff_directory(read, visited, offset, target,
tags, tagCount);
if (status < B_OK)
return status;
@ -293,6 +305,11 @@ parse_tiff_directory(TReadHelper& read, BMessage& target,
// #pragma mark -
/*! Converts the EXIF data that starts in \a source to a BMessage in \a target.
If the EXIF data is corrupt, this function will return an appropriate error
code. Nevertheless, there might be some data ending up in \a target that
was parsed until this point.
*/
status_t
convert_exif_to_message(BPositionIO& source, BMessage& target,
const convert_tag* tags, size_t tagCount)
@ -315,7 +332,8 @@ convert_exif_to_message(BPositionIO& source, BMessage& target,
if (magic != 42)
return B_BAD_TYPE;
return parse_tiff_directory(read, target, tags, tagCount);
set<off_t> visitedOffsets;
return parse_tiff_directory(read, visitedOffsets, target, tags, tagCount);
}

View File

@ -27,8 +27,9 @@ process_exif(uint8* data, uint32 length)
BMemoryIO source(data + 8, length - 8);
BMessage exif;
status_t status = convert_exif_to_message(source, exif);
if (status == B_OK)
exif.PrintToStream();
exif.PrintToStream();
// even if it failed, some data might end up in the message
return status;
}