From 020135661d9d4248c9df740cc11664eb814da75b Mon Sep 17 00:00:00 2001 From: Joe Drago Date: Thu, 21 Nov 2019 16:12:02 -0800 Subject: [PATCH 1/3] Fix CHANGELOG link --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e425b61c..4356843267 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -254,7 +254,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `avifVersion()` function [Unreleased]: https://github.com/AOMediaCodec/libavif/compare/v0.5.0...HEAD -[0.5.0]: https://github.com/AOMediaCodec/libavif/compare/v0.4.7...v0.5.0 +[0.5.0]: https://github.com/AOMediaCodec/libavif/compare/v0.4.8...v0.5.0 [0.4.8]: https://github.com/AOMediaCodec/libavif/compare/v0.4.7...v0.4.8 [0.4.7]: https://github.com/AOMediaCodec/libavif/compare/v0.4.6...v0.4.7 [0.4.6]: https://github.com/AOMediaCodec/libavif/compare/v0.4.5...v0.4.6 From 71b8805d7c9cf55a82044d4f0336c0ee6e4a6e6d Mon Sep 17 00:00:00 2001 From: Joe Drago Date: Thu, 21 Nov 2019 16:54:20 -0800 Subject: [PATCH 2/3] Fix expectations for Exif payload to better match normal usage --- CHANGELOG.md | 2 ++ include/avif/avif.h | 4 +++- src/avif.c | 1 + src/read.c | 1 - src/write.c | 36 +++++++++++++++++++++++++++++------- 5 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4356843267..aa583cd79b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Fix expectations for Exif payload to better match normal usage ## [0.5.0] - 2019-11-21 ### Added diff --git a/include/avif/avif.h b/include/avif/avif.h index 42b907497a..0b9c6b30db 100644 --- a/include/avif/avif.h +++ b/include/avif/avif.h @@ -89,7 +89,8 @@ typedef enum avifResult AVIF_RESULT_COLOR_ALPHA_SIZE_MISMATCH, AVIF_RESULT_ISPE_SIZE_MISMATCH, AVIF_RESULT_NO_CODEC_AVAILABLE, - AVIF_RESULT_NO_IMAGES_REMAINING + AVIF_RESULT_NO_IMAGES_REMAINING, + AVIF_RESULT_INVALID_EXIF_PAYLOAD } avifResult; const char * avifResultToString(avifResult result); @@ -315,6 +316,7 @@ void avifImageSetProfileNone(avifImage * image); void avifImageSetProfileICC(avifImage * image, const uint8_t * icc, size_t iccSize); void avifImageSetProfileNCLX(avifImage * image, avifNclxColorProfile * nclx); +// Warning: If the Exif payload is set and invalid, avifEncoderWrite() may return AVIF_RESULT_INVALID_EXIF_PAYLOAD void avifImageSetMetadataExif(avifImage * image, const uint8_t * exif, size_t exifSize); void avifImageSetMetadataXMP(avifImage * image, const uint8_t * xmp, size_t xmpSize); diff --git a/src/avif.c b/src/avif.c index c16263c313..053bcef516 100644 --- a/src/avif.c +++ b/src/avif.c @@ -87,6 +87,7 @@ const char * avifResultToString(avifResult result) case AVIF_RESULT_ISPE_SIZE_MISMATCH: return "Plane sizes don't match ispe values"; case AVIF_RESULT_NO_CODEC_AVAILABLE: return "No codec available"; case AVIF_RESULT_NO_IMAGES_REMAINING: return "No images remaining"; + case AVIF_RESULT_INVALID_EXIF_PAYLOAD: return "Invalid Exif payload"; case AVIF_RESULT_UNKNOWN_ERROR: default: break; diff --git a/src/read.c b/src/read.c index 15aedcc835..865ebe71b9 100644 --- a/src/read.c +++ b/src/read.c @@ -1728,7 +1728,6 @@ avifResult avifDecoderReset(avifDecoder * decoder) BEGIN_STREAM(exifBoxStream, boxPtr, item->size); uint32_t exifTiffHeaderOffset; CHECK(avifROStreamReadU32(&exifBoxStream, &exifTiffHeaderOffset)); // unsigned int(32) exif_tiff_header_offset; - CHECK(avifROStreamSkip(&exifBoxStream, exifTiffHeaderOffset)); exifData.data = avifROStreamCurrent(&exifBoxStream); exifData.size = avifROStreamRemainingBytes(&exifBoxStream); diff --git a/src/write.c b/src/write.c index ea5dbb8708..6329a0a773 100644 --- a/src/write.c +++ b/src/write.c @@ -20,10 +20,6 @@ static void ipmaPush(struct ipmaArray * ipma, uint8_t assoc) static const char alphaURN[] = URN_ALPHA0; static const size_t alphaURNSize = sizeof(alphaURN); -// Exit block header (see ISO/IEC 23008-12:2017, Annex A.2.1 -static const char exifHeader[] = "Exif"; -static const size_t exifHeaderSize = sizeof(exifHeader); - static const char xmpContentType[] = CONTENT_TYPE_XMP; static const size_t xmpContentTypeSize = sizeof(xmpContentType); @@ -76,6 +72,33 @@ avifResult avifEncoderWrite(avifEncoder * encoder, avifImage * image, avifRWData } } + // ----------------------------------------------------------------------- + // Validate Exif payload (if any) and find TIFF header offset + + uint32_t exifTiffHeaderOffset = 0; + if (image->exif.size > 0) { + if (image->exif.size < 4) { + // Can't even fit the TIFF header, something is wrong + return AVIF_RESULT_INVALID_EXIF_PAYLOAD; + } + + const uint8_t tiffHeaderBE[4] = { 'M', 'M', 0, 42 }; + const uint8_t tiffHeaderLE[4] = { 'I', 'I', 42, 0 }; + for (; exifTiffHeaderOffset < (image->exif.size - 4); ++exifTiffHeaderOffset) { + if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderBE, sizeof(tiffHeaderBE))) { + break; + } + if (!memcmp(&image->exif.data[exifTiffHeaderOffset], tiffHeaderLE, sizeof(tiffHeaderLE))) { + break; + } + } + + if (exifTiffHeaderOffset >= image->exif.size - 4) { + // Couldn't find the TIFF header + return AVIF_RESULT_INVALID_EXIF_PAYLOAD; + } + } + // ----------------------------------------------------------------------- // Pre-fill config boxes based on image (codec can query/update later) @@ -240,7 +263,7 @@ avifResult avifEncoderWrite(avifEncoder * encoder, avifImage * image, avifRWData // :: unsigned int(32) exif_tiff_header_offset; // :: unsigned int(8) exif_payload[]; // :: } - uint32_t exifDataBlockSize = (uint32_t)(sizeof(uint32_t) + exifHeaderSize + image->exif.size); + uint32_t exifDataBlockSize = (uint32_t)(sizeof(uint32_t) + image->exif.size); avifRWStreamWriteU16(&s, exifItemID); // unsigned int(16) item_ID; avifRWStreamWriteU16(&s, 0); // unsigned int(16) data_reference_index; @@ -452,8 +475,7 @@ avifResult avifEncoderWrite(avifEncoder * encoder, avifImage * image, avifRWData avifRWStreamWrite(&s, alphaOBU.data, alphaOBU.size); uint32_t exifOffset = (uint32_t)s.offset; if (image->exif.size > 0) { - avifRWStreamWriteU32(&s, (uint32_t)exifHeaderSize); // unsigned int(32) exif_tiff_header_offset; (Annex A.2.1) - avifRWStreamWrite(&s, (uint8_t *)exifHeader, exifHeaderSize); + avifRWStreamWriteU32(&s, (uint32_t)exifTiffHeaderOffset); // unsigned int(32) exif_tiff_header_offset; (Annex A.2.1) avifRWStreamWrite(&s, image->exif.data, image->exif.size); } uint32_t xmpOffset = (uint32_t)s.offset; From c673f2e884e635ff8e9b2c2951a2dddd2a00ffc3 Mon Sep 17 00:00:00 2001 From: Joe Drago Date: Thu, 21 Nov 2019 16:55:35 -0800 Subject: [PATCH 3/3] v0.5.1 --- CHANGELOG.md | 5 ++++- CMakeLists.txt | 4 ++-- include/avif/avif.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa583cd79b..30e3fd5fc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +## [0.5.1] - 2019-11-21 ### Changed - Fix expectations for Exif payload to better match normal usage @@ -255,7 +257,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Constants `AVIF_VERSION`, `AVIF_VERSION_MAJOR`, `AVIF_VERSION_MINOR`, `AVIF_VERSION_PATCH` - `avifVersion()` function -[Unreleased]: https://github.com/AOMediaCodec/libavif/compare/v0.5.0...HEAD +[Unreleased]: https://github.com/AOMediaCodec/libavif/compare/v0.5.1...HEAD +[0.5.1]: https://github.com/AOMediaCodec/libavif/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/AOMediaCodec/libavif/compare/v0.4.8...v0.5.0 [0.4.8]: https://github.com/AOMediaCodec/libavif/compare/v0.4.7...v0.4.8 [0.4.7]: https://github.com/AOMediaCodec/libavif/compare/v0.4.6...v0.4.7 diff --git a/CMakeLists.txt b/CMakeLists.txt index b2a8203cc1..c9810c841e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: BSD-2-Clause cmake_minimum_required(VERSION 3.5) -project(libavif LANGUAGES C VERSION 0.5.0) +project(libavif LANGUAGES C VERSION 0.5.1) # SOVERSION scheme: CURRENT.AGE.REVISION # If there was an incompatible interface change: @@ -11,7 +11,7 @@ project(libavif LANGUAGES C VERSION 0.5.0) # Increment AGE. Set REVISION to 0 # If the source code was changed, but there were no interface changes: # Increment REVISION. -set(LIBRARY_VERSION "0.1.0") +set(LIBRARY_VERSION "0.1.1") set(LIBRARY_SOVERSION "0") if(CMAKE_C_COMPILER_ID MATCHES "GNU") diff --git a/include/avif/avif.h b/include/avif/avif.h index 0b9c6b30db..4885ee49c6 100644 --- a/include/avif/avif.h +++ b/include/avif/avif.h @@ -16,7 +16,7 @@ extern "C" { #define AVIF_VERSION_MAJOR 0 #define AVIF_VERSION_MINOR 5 -#define AVIF_VERSION_PATCH 0 +#define AVIF_VERSION_PATCH 1 #define AVIF_VERSION (AVIF_VERSION_MAJOR * 10000) + (AVIF_VERSION_MINOR * 100) + AVIF_VERSION_PATCH typedef int avifBool;