* 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:
@@ -1,18 +1,19 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2007-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "exif_parser.h"
|
#include "exif_parser.h"
|
||||||
|
|
||||||
#include <ReadHelper.h>
|
#include <ctype.h>
|
||||||
|
#include <set>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ReadHelper.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -37,8 +38,8 @@ static const size_t kNumDefaultTags = sizeof(kDefaultTags)
|
|||||||
/ sizeof(kDefaultTags[0]);
|
/ sizeof(kDefaultTags[0]);
|
||||||
|
|
||||||
|
|
||||||
static status_t parse_tiff_directory(TReadHelper& read, BMessage& target,
|
static status_t parse_tiff_directory(TReadHelper& read, set<off_t>& visited,
|
||||||
const convert_tag* tags, size_t tagCount);
|
BMessage& target, const convert_tag* tags, size_t tagCount);
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
@@ -226,10 +227,16 @@ parse_tiff_tag(TReadHelper& read, tiff_tag& tag, off_t& offset)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
|
parse_tiff_directory(TReadHelper& read, set<off_t>& visited, off_t offset,
|
||||||
const convert_tag* convertTags, size_t convertTagCount)
|
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);
|
read.Seek(offset, SEEK_SET);
|
||||||
|
visited.insert(offset);
|
||||||
|
|
||||||
uint16 tags;
|
uint16 tags;
|
||||||
read(tags);
|
read(tags);
|
||||||
@@ -247,7 +254,7 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
|
|||||||
case TAG_EXIF_OFFSET:
|
case TAG_EXIF_OFFSET:
|
||||||
case TAG_SUB_DIR_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);
|
convertTags, convertTagCount);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
@@ -263,7 +270,12 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (visited.find(nextOffset) != visited.end())
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
read.Seek(nextOffset, SEEK_SET);
|
read.Seek(nextOffset, SEEK_SET);
|
||||||
|
visited.insert(nextOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -271,7 +283,7 @@ parse_tiff_directory(TReadHelper& read, off_t offset, BMessage& target,
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
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)
|
const convert_tag* tags, size_t tagCount)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -280,7 +292,7 @@ parse_tiff_directory(TReadHelper& read, BMessage& target,
|
|||||||
if (offset == 0)
|
if (offset == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
status_t status = parse_tiff_directory(read, offset, target,
|
status_t status = parse_tiff_directory(read, visited, offset, target,
|
||||||
tags, tagCount);
|
tags, tagCount);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
@@ -293,6 +305,11 @@ parse_tiff_directory(TReadHelper& read, BMessage& target,
|
|||||||
// #pragma mark -
|
// #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
|
status_t
|
||||||
convert_exif_to_message(BPositionIO& source, BMessage& target,
|
convert_exif_to_message(BPositionIO& source, BMessage& target,
|
||||||
const convert_tag* tags, size_t tagCount)
|
const convert_tag* tags, size_t tagCount)
|
||||||
@@ -315,7 +332,8 @@ convert_exif_to_message(BPositionIO& source, BMessage& target,
|
|||||||
if (magic != 42)
|
if (magic != 42)
|
||||||
return B_BAD_TYPE;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ process_exif(uint8* data, uint32 length)
|
|||||||
BMemoryIO source(data + 8, length - 8);
|
BMemoryIO source(data + 8, length - 8);
|
||||||
BMessage exif;
|
BMessage exif;
|
||||||
status_t status = convert_exif_to_message(source, 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;
|
return status;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user