From 2f00291de2d4005e1986cc8037d1769635a0d07a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 11 May 2008 12:28:01 +0000 Subject: [PATCH] * 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 --- src/add-ons/translators/jpeg/exif_parser.cpp | 44 +++++++++++++------ .../add-ons/translators/exif/dump_exif.cpp | 5 ++- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/add-ons/translators/jpeg/exif_parser.cpp b/src/add-ons/translators/jpeg/exif_parser.cpp index 24a89177a8..750d0825c0 100644 --- a/src/add-ons/translators/jpeg/exif_parser.cpp +++ b/src/add-ons/translators/jpeg/exif_parser.cpp @@ -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 +#include +#include +#include +#include #include -#include -#include -#include +#include 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& 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& 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& 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 visitedOffsets; + return parse_tiff_directory(read, visitedOffsets, target, tags, tagCount); } diff --git a/src/tests/add-ons/translators/exif/dump_exif.cpp b/src/tests/add-ons/translators/exif/dump_exif.cpp index f5f47c4620..53040169dd 100644 --- a/src/tests/add-ons/translators/exif/dump_exif.cpp +++ b/src/tests/add-ons/translators/exif/dump_exif.cpp @@ -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; }