exiv2-0.27.0 (#1665246)

This commit is contained in:
Rex Dieter 2019-01-10 15:11:30 -06:00
parent ca955494e2
commit a124f15038
32 changed files with 551 additions and 2200 deletions

4
.gitignore vendored
View File

@ -1,3 +1 @@
/exiv2-0.25.tar.gz
/exiv2-0.26-trunk.tar.gz
/exiv2-0.26.tar.gz
/exiv2-0.27.0-Source.tar.gz

View File

@ -1,25 +0,0 @@
From 2f8681e120d277e418941c4361c83b5028f67fd8 Mon Sep 17 00:00:00 2001
From: clanmills <robin@clanmills.com>
Date: Sat, 27 May 2017 10:18:17 +0100
Subject: [PATCH 6/6] #1296 Fix submitted.
---
src/tiffcomposite.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/tiffcomposite.cpp b/src/tiffcomposite.cpp
index c6b860d..0c9b9c4 100644
--- a/src/tiffcomposite.cpp
+++ b/src/tiffcomposite.cpp
@@ -1611,6 +1611,8 @@ namespace Exiv2 {
uint32_t TiffImageEntry::doWriteImage(IoWrapper& ioWrapper,
ByteOrder /*byteOrder*/) const
{
+ if ( !pValue() ) throw Error(21); // #1296
+
uint32_t len = pValue()->sizeDataArea();
if (len > 0) {
#ifdef DEBUG
--
2.9.4

View File

@ -0,0 +1,41 @@
From d1c609b320eadbe7089b0482353ffef576813ca2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luis=20D=C3=ADaz=20M=C3=A1s?= <piponazo@gmail.com>
Date: Tue, 18 Dec 2018 08:05:16 +0100
Subject: [PATCH 22/70] cmake: man pages only installed with the exiv2 app
---
CMakeLists.txt | 3 ---
src/CMakeLists.txt | 7 +------
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8dfd9d97..e98cfac1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -106,6 +106,3 @@ configure_file(cmake/exiv2.pc.in exiv2.pc @ONLY)
install(FILES ${CMAKE_BINARY_DIR}/exiv2.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
include(cmake/printSummary.cmake)
-
-# That's all Folks!
-##
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ca24006e..0d093924 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -273,11 +273,6 @@ if(EXIV2_BUILD_EXIV2_COMMAND)
endif()
install(TARGETS exiv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+ install( FILES exiv2.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
endif()
-# ******************************************************************************
-# Man page
-install( FILES exiv2.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
-
-# That's all Folks!
-##
--
2.17.2

View File

@ -0,0 +1,64 @@
From e57f311e629762fbf2b08d9a5b1e0cad1035b42f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luis=20D=C3=ADaz=20M=C3=A1s?= <piponazo@gmail.com>
Date: Tue, 18 Dec 2018 10:33:11 +0100
Subject: [PATCH 35/70] cmake: ignore warnings about missing PDB files in 3rd
party libs
---
samples/CMakeLists.txt | 11 +++++++++++
src/CMakeLists.txt | 4 ++++
2 files changed, 15 insertions(+)
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index a3e491e0..4e8c14c6 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -43,6 +43,9 @@ foreach(entry ${SAMPLES})
add_test( ${target}_test ${target} )
target_include_directories(${target} PRIVATE ${CMAKE_SOURCE_DIR}/src) # To find unused.h
install( TARGETS ${target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+ if (MSVC)
+ set_target_properties(${target} PROPERTIES LINK_FLAGS "/ignore:4099")
+ endif()
endforeach()
###################################
@@ -69,6 +72,11 @@ list(APPEND APPLICATIONS exiv2json)
install( TARGETS metacopy pathtest exiv2json RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+if (MSVC)
+ set_target_properties(exiv2json PROPERTIES LINK_FLAGS "/ignore:4099")
+ set_target_properties(metacopy PROPERTIES LINK_FLAGS "/ignore:4099")
+endif()
+
if( EXPAT_FOUND )
add_executable( geotag geotag.cpp)
list(APPEND APPLICATIONS geotag)
@@ -103,6 +111,9 @@ foreach(application ${APPLICATIONS})
if( EXIV2_ENABLE_PNG )
target_link_libraries( ${application} PRIVATE ${ZLIB_LIBRARIES} )
endif()
+ if (MSVC)
+ set_target_properties(${application} PROPERTIES LINK_FLAGS "/ignore:4099")
+ endif()
endforeach()
# ******************************************************************************
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0d093924..adb285b1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -274,5 +274,9 @@ if(EXIV2_BUILD_EXIV2_COMMAND)
install(TARGETS exiv2 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install( FILES exiv2.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
+
+ if (MSVC)
+ set_target_properties(exiv2 PROPERTIES LINK_FLAGS "/ignore:4099")
+ endif()
endif()
--
2.17.2

View File

@ -0,0 +1,82 @@
From 89509d7a3915ba474cbc3f8c85ab9bec4954ceda Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Wed, 2 Jan 2019 10:38:22 +0100
Subject: [PATCH 64/70] cmake: Rename xmp to exiv2-xmp to avoid name conflicts
There is already a libxmp file by the xmp project on https://xmp.sf.net.
To avoid issues prefix with exiv2.
Fixes #624
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
src/CMakeLists.txt | 2 +-
xmpsdk/CMakeLists.txt | 14 +++++++-------
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index adb285b1..2aeae733 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -147,7 +147,7 @@ target_include_directories(exiv2lib_int PRIVATE ${ZLIB_INCLUDE_DIR})
target_include_directories(exiv2lib PRIVATE ${ZLIB_INCLUDE_DIR})
if (EXIV2_ENABLE_XMP)
- target_link_libraries(exiv2lib PUBLIC xmp)
+ target_link_libraries(exiv2lib PUBLIC exiv2-xmp)
elseif(EXIV2_ENABLE_EXTERNAL_XMP)
target_link_libraries(exiv2lib PUBLIC ${XMPSDK_LIBRARY})
target_include_directories(exiv2lib PUBLIC ${XMPSDK_INCLUDE_DIR})
diff --git a/xmpsdk/CMakeLists.txt b/xmpsdk/CMakeLists.txt
index a4c1fe6c..fa521043 100644
--- a/xmpsdk/CMakeLists.txt
+++ b/xmpsdk/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_library(xmp STATIC
+add_library(exiv2-xmp STATIC
src/ExpatAdapter.cpp
src/MD5.cpp
src/ParseRDF.cpp
@@ -26,12 +26,12 @@ add_library(xmp STATIC
include/XMP_Version.h
)
-target_link_libraries(xmp
+target_link_libraries(exiv2-xmp
PRIVATE
${EXPAT_LIBRARY}
)
-target_include_directories(xmp
+target_include_directories(exiv2-xmp
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/xmpsdk/include>
PRIVATE
@@ -39,20 +39,20 @@ target_include_directories(xmp
)
if (MSVC)
- target_compile_definitions(xmp PRIVATE XML_STATIC)
+ target_compile_definitions(exiv2-xmp PRIVATE XML_STATIC)
endif()
check_include_file( "stdint.h" EXV_HAVE_STDINT_H )
if (EXV_HAVE_STDINT_H)
- target_compile_definitions(xmp PRIVATE EXV_HAVE_STDINT_H)
+ target_compile_definitions(exiv2-xmp PRIVATE EXV_HAVE_STDINT_H)
endif()
if (BUILD_SHARED_LIBS)
- set_property(TARGET xmp PROPERTY POSITION_INDEPENDENT_CODE ON)
+ set_property(TARGET exiv2-xmp PROPERTY POSITION_INDEPENDENT_CODE ON)
endif()
# 1119 Install libxmp.a for use by third party applications (Thanks, Emmanuel)
-install(TARGETS xmp EXPORT exiv2Config
+install(TARGETS exiv2-xmp EXPORT exiv2Config
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
--
2.17.2

View File

@ -0,0 +1,111 @@
From 0b34ccb9a3b26cd1c5267c6a5c15e9fa1a665adb Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Wed, 2 Jan 2019 10:59:30 +0100
Subject: [PATCH 65/70] cmake: Install header files without globbing
Fixes #627
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
CMakeLists.txt | 1 +
include/CMakeLists.txt | 1 +
include/exiv2/CMakeLists.txt | 51 ++++++++++++++++++++++++++++++++++++
src/CMakeLists.txt | 4 ---
4 files changed, 53 insertions(+), 4 deletions(-)
create mode 100644 include/CMakeLists.txt
create mode 100644 include/exiv2/CMakeLists.txt
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 183cdd2e..ce4d2202 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -76,6 +76,7 @@ endif()
include(cmake/compilerFlagsExiv2.cmake REQUIRED)
+add_subdirectory( include )
add_subdirectory( src )
if( EXIV2_BUILD_UNIT_TESTS )
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644
index 00000000..01b43a6c
--- /dev/null
+++ b/include/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(exiv2)
diff --git a/include/exiv2/CMakeLists.txt b/include/exiv2/CMakeLists.txt
new file mode 100644
index 00000000..60080f1c
--- /dev/null
+++ b/include/exiv2/CMakeLists.txt
@@ -0,0 +1,51 @@
+install(FILES
+ asfvideo.hpp
+ basicio.hpp
+ bigtiffimage.hpp
+ bmpimage.hpp
+ config.h
+ convert.hpp
+ cr2image.hpp
+ crwimage.hpp
+ datasets.hpp
+ easyaccess.hpp
+ epsimage.hpp
+ error.hpp
+ exif.hpp
+ exiv2.hpp
+ futils.hpp
+ gifimage.hpp
+ http.hpp
+ image.hpp
+ ini.hpp
+ iptc.hpp
+ jp2image.hpp
+ jpgimage.hpp
+ matroskavideo.hpp
+ metadatum.hpp
+ mrwimage.hpp
+ orfimage.hpp
+ pgfimage.hpp
+ pngimage.hpp
+ preview.hpp
+ properties.hpp
+ psdimage.hpp
+ quicktimevideo.hpp
+ rafimage.hpp
+ riffvideo.hpp
+ rw2image.hpp
+ rwlock.hpp
+ slice.hpp
+ ssh.hpp
+ tags.hpp
+ tgaimage.hpp
+ tiffimage.hpp
+ types.hpp
+ utilsvideo.hpp
+ value.hpp
+ version.hpp
+ webpimage.hpp
+ xmp_exiv2.hpp
+ xmpsidecar.hpp
+ DESTINATION
+ ${CMAKE_INSTALL_INCLUDEDIR}/exiv2)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index adb285b1..04d8a2a0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -225,10 +225,6 @@ install(TARGETS exiv2lib EXPORT exiv2Config
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
-install(DIRECTORY ../include/exiv2
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
- FILES_MATCHING PATTERN "*.h*")
-
install(FILES
${CMAKE_BINARY_DIR}/exv_conf.h
${CMAKE_BINARY_DIR}/exiv2lib_export.h
--
2.17.2

View File

@ -0,0 +1,28 @@
From f8f63a8b4033549d47384c6e2b1972ae1a2775fc Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Wed, 2 Jan 2019 10:28:57 +0100
Subject: [PATCH 66/70] cmake: Use correct installation dir for generated docs
Fixes #623
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
cmake/generateDoc.cmake | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cmake/generateDoc.cmake b/cmake/generateDoc.cmake
index a3aea727..16823946 100644
--- a/cmake/generateDoc.cmake
+++ b/cmake/generateDoc.cmake
@@ -21,7 +21,7 @@ macro(generate_documentation DOX_CONFIG_FILE)
set(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG})
- install(DIRECTORY "${PROJECT_BINARY_DIR}/doc/html/" DESTINATION "share/doc/lib${PROJECT_NAME}")
+ install(DIRECTORY "${PROJECT_BINARY_DIR}/doc/html/" DESTINATION ${CMAKE_INSTALL_DOCDIR})
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES doc)
endmacro()
--
2.17.2

View File

@ -0,0 +1,124 @@
From 420e4631da1372da1be06af8f6032429c1f14d02 Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Thu, 3 Jan 2019 10:18:27 +0100
Subject: [PATCH 67/70] cmake: Use correct installation dir for cmake config
files
This is the path cmake will look for those files by default. At least on
UNIX systems.
Fixes #623
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
releasenotes/CYGWIN/ReadMe.txt | 2 +-
releasenotes/Darwin/ReadMe.txt | 2 +-
releasenotes/Linux/ReadMe.txt | 1 +
releasenotes/MinGW/ReadMe.txt | 2 +-
releasenotes/msvc/ReadMe.txt | 2 +-
releasenotes/releasenotes.txt | 5 +++++
src/CMakeLists.txt | 2 +-
7 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/releasenotes/CYGWIN/ReadMe.txt b/releasenotes/CYGWIN/ReadMe.txt
index 9161ca34..bba70fe6 100644
--- a/releasenotes/CYGWIN/ReadMe.txt
+++ b/releasenotes/CYGWIN/ReadMe.txt
@@ -7,9 +7,9 @@ Structure of the bundle:
bin/exiv2.exe exiv2 and sample applications
bin/cygexiv2-27.dll DLL
lib/libexiv2.dll.a & libxmp.a link libraries
+lib/cmake/exiv2 consume CMake files
lib/pkgconfig/exiv2.pc pkg-config file
share/man man pages
-share/exiv2/cmake consume CMake files
samples/exifprint.cpp sample code
logs build and test logs
diff --git a/releasenotes/Darwin/ReadMe.txt b/releasenotes/Darwin/ReadMe.txt
index d3e61177..57910713 100644
--- a/releasenotes/Darwin/ReadMe.txt
+++ b/releasenotes/Darwin/ReadMe.txt
@@ -6,10 +6,10 @@ Structure of the bundle
bin/exiv2 exiv2 and sample applications
lib/libexiv2.0.27.0.0.dylib & libxmp.a libraries
+lib/cmake/exiv2 consume CMake files
lib/pkgconfig/exiv2.pc pkg-config file
include/exiv2/ include files
share/man man pages
-share/exiv2/cmake consume CMake files
samples/exifprint.cpp sample code
logs build and test logs
diff --git a/releasenotes/Linux/ReadMe.txt b/releasenotes/Linux/ReadMe.txt
index 03348302..0737b3a4 100644
--- a/releasenotes/Linux/ReadMe.txt
+++ b/releasenotes/Linux/ReadMe.txt
@@ -7,6 +7,7 @@ Structure of the bundle:
bin/exiv2 exiv2 and sample applications
lib/libexiv2.so.0.27.0.0 & libxmp.a libraries
lib/pkgconfig/exiv2.pc pkg-config file
+lib/cmake/exiv2 consume CMake files
include/exiv2/ include files
share/ man pages
samples/exifprint.cpp sample code
diff --git a/releasenotes/MinGW/ReadMe.txt b/releasenotes/MinGW/ReadMe.txt
index 884d7502..98cd7770 100644
--- a/releasenotes/MinGW/ReadMe.txt
+++ b/releasenotes/MinGW/ReadMe.txt
@@ -7,10 +7,10 @@ Structure of the bundle:
bin/exiv2.exe exiv2 and sample applications
bin/msys-exiv2-27.dll exiv2 dll
lib/libexiv2.dll.a & libxmp.a link libraries
+lib/cmake/exiv2 consume CMake files
lib/pkgconfig/exiv2.pc pkg-config file
include/exiv2/ include files
share/man man pages
-share/exiv2/cmake consume CMake files
samples/exifprint.cpp sample code
logs build and test logs
diff --git a/releasenotes/msvc/ReadMe.txt b/releasenotes/msvc/ReadMe.txt
index de1dcbfe..e625ab49 100644
--- a/releasenotes/msvc/ReadMe.txt
+++ b/releasenotes/msvc/ReadMe.txt
@@ -7,8 +7,8 @@ Structure of the bundle:
bin/exiv2.exe exiv2 and sample applications
bin/exiv2.dll dll
lib/exiv2.lib & xmp.lib link libraries
+lib/cmake/exiv2 consume CMake files
include/exiv2/ include files
-share/exiv2/cmake consume CMake files
samples/exifprint.cpp sample code
logs build and test logs
diff --git a/releasenotes/releasenotes.txt b/releasenotes/releasenotes.txt
index b71b4519..226c078b 100644
--- a/releasenotes/releasenotes.txt
+++ b/releasenotes/releasenotes.txt
@@ -1,3 +1,8 @@
+Exiv2 v0.27.1
+-------------
+
+#623 Use correct installation path for generated docs and cmake config files
+
Exiv2 v0.27.0
-------------
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index adb285b1..4a05ee4f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -234,7 +234,7 @@ install(FILES
${CMAKE_BINARY_DIR}/exiv2lib_export.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/exiv2)
-install(EXPORT exiv2Config DESTINATION "share/exiv2/cmake")
+install(EXPORT exiv2Config DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/exiv2")
# ******************************************************************************
# exiv2 application
--
2.17.2

View File

@ -0,0 +1,34 @@
From e44d1dbe769f3b60a3d671be310f4af4f9490e6b Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Thu, 3 Jan 2019 10:31:25 +0100
Subject: [PATCH 68/70] xmpsdk: Build with -DBanAllEntityUsage=1
Prevent a denial-service-attack related to XML entity expansion
("billion laughs attack").
See https://bugzilla.redhat.com/show_bug.cgi?id=888769
Search for BanAllEntityUsage in xmpsdk/src/ExpatAdapter.cpp
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
xmpsdk/CMakeLists.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/xmpsdk/CMakeLists.txt b/xmpsdk/CMakeLists.txt
index fa521043..ae011dc3 100644
--- a/xmpsdk/CMakeLists.txt
+++ b/xmpsdk/CMakeLists.txt
@@ -38,6 +38,10 @@ target_include_directories(exiv2-xmp
${EXPAT_INCLUDE_DIR}
)
+# Prevent a denial-service-attack related to XML entity expansion
+# ("billion laughs attack").
+# See https://bugzilla.redhat.com/show_bug.cgi?id=888769
+target_compile_definitions(exiv2-xmp PRIVATE BanAllEntityUsage=1)
if (MSVC)
target_compile_definitions(exiv2-xmp PRIVATE XML_STATIC)
endif()
--
2.17.2

View File

@ -0,0 +1,31 @@
From dac6bb6043fc046f7cbad73c281eb258a981267f Mon Sep 17 00:00:00 2001
From: Andreas Schneider <asn@cryptomilk.org>
Date: Thu, 3 Jan 2019 10:41:40 +0100
Subject: [PATCH 69/70] xmpsdk: Fix compile warnings in ExpatAdapter.cpp
The code has been enabled with -DBanAllEntityUsage=1
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
---
xmpsdk/src/ExpatAdapter.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/xmpsdk/src/ExpatAdapter.cpp b/xmpsdk/src/ExpatAdapter.cpp
index 79669f52..09117c75 100644
--- a/xmpsdk/src/ExpatAdapter.cpp
+++ b/xmpsdk/src/ExpatAdapter.cpp
@@ -484,7 +484,10 @@ static void CommentHandler ( void * userData, XMP_StringPtr comment )
static void StartDoctypeDeclHandler ( void * userData, XMP_StringPtr doctypeName,
XMP_StringPtr sysid, XMP_StringPtr pubid, int has_internal_subset )
{
- IgnoreParam(userData);
+ IgnoreParam(doctypeName);
+ IgnoreParam(sysid);
+ IgnoreParam(pubid);
+ IgnoreParam(has_internal_subset);
ExpatAdapter * thiz = (ExpatAdapter*)userData;
--
2.17.2

View File

@ -1,20 +0,0 @@
diff -up exiv2-0.26/src/pentaxmn.cpp.pentax exiv2-0.26/src/pentaxmn.cpp
--- exiv2-0.26/src/pentaxmn.cpp.pentax 2017-04-26 14:16:21.000000000 -0500
+++ exiv2-0.26/src/pentaxmn.cpp 2019-01-10 14:21:00.342499581 -0600
@@ -1254,6 +1254,7 @@ namespace Exiv2 {
unsigned long lensID = 0x3ff;
unsigned long index = 0;
+ // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html#LensData
const ExifData::const_iterator lensInfo = metadata->findKey(ExifKey("Exif.PentaxDng.LensInfo")) != metadata->end()
? metadata->findKey(ExifKey("Exif.PentaxDng.LensInfo"))
: metadata->findKey(ExifKey("Exif.Pentax.LensInfo"))
@@ -1268,8 +1269,6 @@ namespace Exiv2 {
// 0x0207 Pentax LensInfo Undefined 36 3 255 0 0 40 148 71 152 80 6 241 65 237 153 88 36 1 76 107 251 255 255 255 0 0 80 6 241 0 0 0 0 0 0 0 0
unsigned long base = 1;
- // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Pentax.html#LensData
- const ExifData::const_iterator lensInfo = metadata->findKey(ExifKey("Exif.Pentax.LensInfo"));
unsigned int autoAperture = lensInfo->toLong(base+1) & 0x01 ;
unsigned int minAperture = lensInfo->toLong(base+2) & 0x06 ;
unsigned int minFocusDistance = lensInfo->toLong(base+3) & 0xf8 ;

View File

@ -1,41 +0,0 @@
From 1f1715c086d8dcdf5165b19164af9aee7aa12e98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Fri, 6 Oct 2017 00:37:43 +0200
Subject: =?UTF-8?q?Use=20nullptr=20check=20instead=20of=20assertion,=20by?=
=?UTF-8?q?=20Rapha=C3=ABl=20Hertzog?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Source:
https://github.com/Exiv2/exiv2/issues/57#issuecomment-333086302
tc can be a null pointer when the TIFF tag is unknown (the factory
then returns an auto_ptr(0)) => as this can happen for corrupted
files, an explicit check should be used because an assertion can be
turned of in release mode (with NDEBUG defined)
This also fixes #57
diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp
index 74f8d078..4ab733d4 100644
--- a/src/tiffvisitor.cpp
+++ b/src/tiffvisitor.cpp
@@ -1294,11 +1294,12 @@ namespace Exiv2 {
}
uint16_t tag = getUShort(p, byteOrder());
TiffComponent::AutoPtr tc = TiffCreator::create(tag, object->group());
- // The assertion typically fails if a component is not configured in
- // the TIFF structure table
- assert(tc.get());
- tc->setStart(p);
- object->addChild(tc);
+ if (tc.get()) {
+ tc->setStart(p);
+ object->addChild(tc);
+ } else {
+ EXV_WARNING << "Unable to handle tag " << tag << ".\n";
+ }
p += 12;
}

View File

@ -1,36 +0,0 @@
From 6ede8aa1975177705450abb816163f0b8d33a597 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Fri, 6 Oct 2017 23:09:08 +0200
Subject: Fix for CVE-2017-14860
A heap buffer overflow could occur in memcpy when icc.size_ is larger
than data.size_ - pad, as then memcpy would read out of bounds of data.
This commit adds a sanity check to iccLength (= icc.size_): if it is
larger than data.size_ - pad (i.e. an overflow would be caused) an
exception is thrown.
This fixes #71.
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index 1892fd43..09d023e2 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -269,10 +269,15 @@ namespace Exiv2
std::cout << "Exiv2::Jp2Image::readMetadata: "
<< "Color data found" << std::endl;
#endif
- long pad = 3 ; // 3 padding bytes 2 0 0
+ const long pad = 3 ; // 3 padding bytes 2 0 0
DataBuf data(subBox.length+8);
io_->read(data.pData_,data.size_);
- long iccLength = getULong(data.pData_+pad, bigEndian);
+ const long iccLength = getULong(data.pData_+pad, bigEndian);
+ // subtracting pad from data.size_ is safe:
+ // size_ is at least 8 and pad = 3
+ if (iccLength > data.size_ - pad) {
+ throw Error(58);
+ }
DataBuf icc(iccLength);
::memcpy(icc.pData_,data.pData_+pad,icc.size_);
#ifdef DEBUG

View File

@ -1,53 +0,0 @@
From d4e4288d839d0d9546a05986771f8738c382060c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Sat, 7 Oct 2017 23:08:36 +0200
Subject: Fix for CVE-2017-14864, CVE-2017-14862 and CVE-2017-14859
The invalid memory dereference in
Exiv2::getULong()/Exiv2::StringValueBase::read()/Exiv2::DataValue::read()
is caused further up the call-stack, by
v->read(pData, size, byteOrder) in TiffReader::readTiffEntry()
passing an invalid pData pointer (pData points outside of the Tiff
file). pData can be set out of bounds in the (size > 4) branch where
baseOffset() and offset are added to pData_ without checking whether
the result is still in the file. As offset comes from an untrusted
source, an attacker can craft an arbitrarily large offset into the
file.
This commit adds a check into the problematic branch, whether the
result of the addition would be out of bounds of the Tiff
file. Furthermore the whole operation is checked for possible
overflows.
diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp
index 4ab733d4..ef13542e 100644
--- a/src/tiffvisitor.cpp
+++ b/src/tiffvisitor.cpp
@@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$")
#include <iostream>
#include <iomanip>
#include <cassert>
+#include <limits>
// *****************************************************************************
namespace {
@@ -1517,7 +1518,19 @@ namespace Exiv2 {
size = 0;
}
if (size > 4) {
+ // setting pData to pData_ + baseOffset() + offset can result in pData pointing to invalid memory,
+ // as offset can be arbitrarily large
+ if ((static_cast<uintptr_t>(baseOffset()) > std::numeric_limits<uintptr_t>::max() - static_cast<uintptr_t>(offset))
+ || (static_cast<uintptr_t>(baseOffset() + offset) > std::numeric_limits<uintptr_t>::max() - reinterpret_cast<uintptr_t>(pData_)))
+ {
+ throw Error(59);
+ }
+ if (pData_ + static_cast<uintptr_t>(baseOffset()) + static_cast<uintptr_t>(offset) > pLast_) {
+ throw Error(58);
+ }
pData = const_cast<byte*>(pData_) + baseOffset() + offset;
+
+ // check for size being invalid
if (size > static_cast<uint32_t>(pLast_ - pData)) {
#ifndef SUPPRESS_WARNINGS
EXV_ERROR << "Upper boundary of data for "

View File

@ -1,37 +0,0 @@
From 06aa7ab69d0c4f3d14644bd84fc9d1346154430d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Mon, 22 Jan 2018 23:56:08 +0100
Subject: Fix out of bounds read in src/pngchunk_int.cpp by @brianmay
- consider that key is advanced by 8 bytes if stripHeader is true
=> length is reduced by same amount
Fixed by adding offset to the check in the loop
- Rewrote loop so that keysize is checked before the next
iteration (preventing an out of bounds read)
diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index da4ccd01..b54bcdac 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -107,15 +107,17 @@ namespace Exiv2 {
{
// From a tEXt, zTXt, or iTXt chunk,
// we get the key, it's a null terminated string at the chunk start
- if (data.size_ <= (stripHeader ? 8 : 0)) throw Error(14);
- const byte *key = data.pData_ + (stripHeader ? 8 : 0);
+ const int offset = stripHeader ? 8 : 0;
+ if (data.size_ <= offset) throw Error(14);
+ const byte *key = data.pData_ + offset;
// Find null string at end of key.
int keysize=0;
- for ( ; key[keysize] != 0 ; keysize++)
+ while (key[keysize] != 0)
{
+ keysize++;
// look if keysize is valid.
- if (keysize >= data.size_)
+ if (keysize+offset >= data.size_)
throw Error(14);
}

View File

@ -1,107 +0,0 @@
diff --git a/include/exiv2/value.hpp b/include/exiv2/value.hpp
index 64a8ca7..4e9f285 100644
--- a/include/exiv2/value.hpp
+++ b/include/exiv2/value.hpp
@@ -1658,11 +1658,13 @@ namespace Exiv2 {
ok_ = true;
return static_cast<long>(value_[n]);
}
+// #55 crash when value_[n].first == LONG_MIN
+#define LARGE_INT 1000000
// Specialization for rational
template<>
inline long ValueType<Rational>::toLong(long n) const
{
- ok_ = (value_[n].second != 0);
+ ok_ = (value_[n].second != 0 && -LARGE_INT < value_[n].first && value_[n].first < LARGE_INT);
if (!ok_) return 0;
return value_[n].first / value_[n].second;
}
@@ -1670,7 +1672,7 @@ namespace Exiv2 {
template<>
inline long ValueType<URational>::toLong(long n) const
{
- ok_ = (value_[n].second != 0);
+ ok_ = (value_[n].second != 0 && value_[n].first < LARGE_INT);
if (!ok_) return 0;
return value_[n].first / value_[n].second;
}
diff --git a/src/basicio.cpp b/src/basicio.cpp
index 95589cd..f2e1518 100644
--- a/src/basicio.cpp
+++ b/src/basicio.cpp
@@ -990,6 +990,7 @@ namespace Exiv2 {
DataBuf FileIo::read(long rcount)
{
assert(p_->fp_ != 0);
+ if ( (size_t) rcount > size() ) throw Error(57);
DataBuf buf(rcount);
long readCount = read(buf.pData_, buf.size_);
buf.size_ = readCount;
diff --git a/src/error.cpp b/src/error.cpp
index 80378c1..e90a9c0 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -106,6 +106,9 @@ namespace {
{ 52, N_("%1 has invalid XMP value type `%2'") }, // %1=key, %2=value type
{ 53, N_("Not a valid ICC Profile") },
{ 54, N_("Not valid XMP") },
+ { 55, N_("tiff directory length is too large") },
+ { 56, N_("invalid type value detected in Image::printIFDStructure") },
+ { 57, N_("invalid memory allocation request") },
};
}
diff --git a/src/image.cpp b/src/image.cpp
index 0d82804..ec5b873 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -399,7 +399,13 @@ namespace Exiv2 {
;
// if ( offset > io.size() ) offset = 0; // Denial of service?
- DataBuf buf(size*count + pad+20); // allocate a buffer
+
+ // #55 memory allocation crash test/data/POC8
+ long long allocate = (long long) (size*count + pad+20);
+ if ( allocate > (long long) io.size() ) {
+ throw Error(57);
+ }
+ DataBuf buf(allocate); // allocate a buffer
std::memcpy(buf.pData_,dir.pData_+8,4); // copy dir[8:11] into buffer (short strings)
if ( count*size > 4 ) { // read into buffer
size_t restore = io.tell(); // save
diff --git a/test/bugfixes-test.sh b/test/bugfixes-test.sh
index f91c675..c90ae55 100755
--- a/test/bugfixes-test.sh
+++ b/test/bugfixes-test.sh
@@ -602,6 +602,7 @@ source ./functions.source
runTest exiv2 -pX $filename | xmllint --format -
num=1231
+ printf "$num " >&3
for X in a b; do
filename=exiv2-bug$num$X.jpg
echo '------>' Bug $filename '<-------' >&2
@@ -622,6 +623,7 @@ source ./functions.source
runTest exiv2 -pa $filename
num=1252
+ printf "$num " >&3
for X in a b; do
filename=exiv2-bug$num$X.exv
echo '------>' Bug $filename '<-------' >&2
@@ -629,6 +631,13 @@ source ./functions.source
runTest exiv2 -pa --grep lens/i $filename
done
+ num=g55
+ printf "$num " >&3
+ filename=POC8
+ echo '------>' Bug $filename '<-------' >&2
+ copyTestFile $filename
+ runTest exiv2 $filename 2>/dev/null
+
) 3>&1 > $results 2>&1
printf "\n"

View File

@ -1,351 +0,0 @@
From 7c6f59619616a01e242401cf4c8e06428539a035 Mon Sep 17 00:00:00 2001
From: Luis Diaz Mas <piponazo@gmail.com>
Date: Sat, 16 Dec 2017 16:05:08 +0100
Subject: Fix arithmetic operation overflow
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index 09d023e2..a308bfd9 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -41,6 +41,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "error.hpp"
#include "futils.hpp"
#include "types.hpp"
+#include "safe_op.hpp"
// + standard includes
#include <string>
@@ -269,15 +270,16 @@ namespace Exiv2
std::cout << "Exiv2::Jp2Image::readMetadata: "
<< "Color data found" << std::endl;
#endif
+
const long pad = 3 ; // 3 padding bytes 2 0 0
- DataBuf data(subBox.length+8);
+ DataBuf data(Safe::add(subBox.length, static_cast<uint32_t>(8)));
io_->read(data.pData_,data.size_);
const long iccLength = getULong(data.pData_+pad, bigEndian);
// subtracting pad from data.size_ is safe:
// size_ is at least 8 and pad = 3
if (iccLength > data.size_ - pad) {
throw Error(58);
- }
+ }
DataBuf icc(iccLength);
::memcpy(icc.pData_,data.pData_+pad,icc.size_);
#ifdef DEBUG
diff --git a/src/safe_op.hpp b/src/safe_op.hpp
new file mode 100644
index 00000000..55d690e3
--- /dev/null
+++ b/src/safe_op.hpp
@@ -0,0 +1,308 @@
+// ********************************************************* -*- C++ -*-
+/*
+ * Copyright (C) 2004-2017 Exiv2 maintainers
+ *
+ * This program is part of the Exiv2 distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
+ */
+/*!
+ @file safe_op.hpp
+ @brief Overflow checks for integers
+ @author Dan Čermák (D4N)
+ <a href="mailto:dan.cermak@cgc-instruments.com">dan.cermak@cgc-instruments.com</a>
+ @date 14-Dec-17, D4N: created
+ */
+
+#ifndef SAFE_OP_HPP_
+#define SAFE_OP_HPP_
+
+#include <limits>
+#include <stdexcept>
+
+#ifdef _MSC_VER
+#include <Intsafe.h>
+#endif
+
+/*!
+ * @brief Arithmetic operations with overflow checks
+ */
+namespace Safe
+{
+ /*!
+ * @brief Helper structs for providing integer overflow checks.
+ *
+ * This namespace contains the internal helper structs fallback_add_overflow
+ * and builtin_add_overflow. Both have a public static member function add
+ * with the following interface:
+ *
+ * bool add(T summand_1, T summand_2, T& result)
+ *
+ * where T is the type over which the struct is templated.
+ *
+ * The function performs a check whether the addition summand_1 + summand_2
+ * can be performed without an overflow. If the operation would overflow,
+ * true is returned and the addition is not performed if it would result in
+ * undefined behavior. If no overflow occurs, the sum is saved in result and
+ * false is returned.
+ *
+ * fallback_add_overflow implements a portable but slower overflow check.
+ * builtin_add_overflow uses compiler builtins (when available) and should
+ * be considerably faster. As builtins are not available for all types,
+ * builtin_add_overflow falls back to fallback_add_overflow when no builtin
+ * is available.
+ */
+ namespace Internal
+ {
+ /*!
+ * @brief Helper struct to determine whether a type is signed or unsigned
+
+ * This struct is a backport of std::is_signed from C++11. It has a public
+ * enum with the property VALUE which is true when the type is signed or
+ * false if it is unsigned.
+ */
+ template <typename T>
+ struct is_signed
+ {
+ enum
+ {
+ VALUE = T(-1) < T(0)
+ };
+ };
+
+ /*!
+ * @brief Helper struct for SFINAE, from C++11
+
+ * This struct has a public typedef called type typedef'd to T if B is
+ * true. Otherwise there is no typedef.
+ */
+ template <bool B, class T = void>
+ struct enable_if
+ {
+ };
+
+ /*!
+ * @brief Specialization of enable_if for the case B == true
+ */
+ template <class T>
+ struct enable_if<true, T>
+ {
+ typedef T type;
+ };
+
+ /*!
+ * @brief Fallback overflow checker, specialized via SFINAE
+ *
+ * This struct implements a 'fallback' addition with an overflow check,
+ * i.e. it does not rely on compiler intrinsics. It is specialized via
+ * SFINAE for signed and unsigned integer types and provides a public
+ * static member function add.
+ */
+ template <typename T, typename = void>
+ struct fallback_add_overflow;
+
+ /*!
+ * @brief Overload of fallback_add_overflow for signed integers
+ */
+ template <typename T>
+ struct fallback_add_overflow<T, typename enable_if<is_signed<T>::VALUE>::type>
+ {
+ /*!
+ * @brief Adds the two summands only if no overflow occurs
+ *
+ * This function performs a check if summand_1 + summand_2 would
+ * overflow and returns true in that case. If no overflow occurs,
+ * the sum is saved in result and false is returned.
+ *
+ * @return true on overflow, false on no overflow
+ *
+ * The check for an overflow is performed before the addition to
+ * ensure that no undefined behavior occurs. The value in result is
+ * only valid when the function returns false.
+ *
+ * Further information:
+ * https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
+ */
+ static bool add(T summand_1, T summand_2, T& result)
+ {
+ if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
+ ((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
+ return true;
+ } else {
+ result = summand_1 + summand_2;
+ return false;
+ }
+ }
+ };
+
+ /*!
+ * @brief Overload of fallback_add_overflow for unsigned integers
+ */
+ template <typename T>
+ struct fallback_add_overflow<T, typename enable_if<!is_signed<T>::VALUE>::type>
+ {
+ /*!
+ * @brief Adds the two summands only if no overflow occurs
+ *
+ * This function performs a check if summand_1 + summand_2 would
+ * overflow and returns true in that case. If no overflow occurs,
+ * the sum is saved in result and false is returned.
+ *
+ * @return true on overflow, false on no overflow
+ *
+ * Further information:
+ * https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
+ */
+ static bool add(T summand_1, T summand_2, T& result)
+ {
+ if (summand_1 > std::numeric_limits<T>::max() - summand_2) {
+ return true;
+ } else {
+ result = summand_1 + summand_2;
+ return false;
+ }
+ }
+ };
+
+ /*!
+ * @brief Overflow checker using compiler intrinsics
+ *
+ * This struct provides an add function with the same interface &
+ * behavior as fallback_add_overload::add but it relies on compiler
+ * intrinsics instead. This version should be considerably faster than
+ * the fallback version as it can fully utilize available CPU
+ * instructions & the compiler's diagnostic.
+ *
+ * However, as some compilers don't provide intrinsics for certain
+ * types, the default implementation of add is the version from falback.
+ *
+ * The struct is explicitly specialized for each type via #ifdefs for
+ * each compiler.
+ */
+ template <typename T>
+ struct builtin_add_overflow
+ {
+ /*!
+ * @brief Add summand_1 and summand_2 and check for overflows.
+ *
+ * This is the default add() function that uses
+ * fallback_add_overflow<T>::add(). All specializations must have
+ * exactly the same interface and behave the same way.
+ */
+ static inline bool add(T summand_1, T summand_2, T& result)
+ {
+ return fallback_add_overflow<T>::add(summand_1, summand_2, result);
+ }
+ };
+
+#if defined(__GNUC__) || defined(__clang__)
+
+/*!
+ * This macro pastes a specialization of builtin_add_overflow using gcc's &
+ * clang's __builtin_(s/u)add(l)(l)_overlow()
+ *
+ * The add function is implemented by forwarding the parameters to the intrinsic
+ * and returning its value.
+ *
+ * The intrinsics are documented here:
+ * https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html#Integer-Overflow-Builtins
+ */
+#define SPECIALIZE_builtin_add_overflow(type, builtin_name) \
+ template <> \
+ struct builtin_add_overflow<type> \
+ { \
+ static inline bool add(type summand_1, type summand_2, type& result) \
+ { \
+ return builtin_name(summand_1, summand_2, &result); \
+ } \
+ }
+
+ SPECIALIZE_builtin_add_overflow(int, __builtin_sadd_overflow);
+ SPECIALIZE_builtin_add_overflow(long, __builtin_saddl_overflow);
+ SPECIALIZE_builtin_add_overflow(long long, __builtin_saddll_overflow);
+
+ SPECIALIZE_builtin_add_overflow(unsigned int, __builtin_uadd_overflow);
+ SPECIALIZE_builtin_add_overflow(unsigned long, __builtin_uaddl_overflow);
+ SPECIALIZE_builtin_add_overflow(unsigned long long, __builtin_uaddll_overflow);
+
+#undef SPECIALIZE_builtin_add_overflow
+
+#elif defined(_MSC_VER)
+
+/*!
+ * This macro pastes a specialization of builtin_add_overflow using MSVC's
+ * U(Int/Long/LongLong)Add.
+ *
+ * The add function is implemented by forwarding the parameters to the
+ * intrinsic. As MSVC's intrinsics return S_OK on success, this specialization
+ * returns whether the intrinsics return value does not equal S_OK. This ensures
+ * a uniform interface of the add function (false is returned when no overflow
+ * occurs, true on overflow).
+ *
+ * The intrinsics are documented here:
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ff516460(v=vs.85).aspx
+ */
+#define SPECIALIZE_builtin_add_overflow_WIN(type, builtin_name) \
+ template <> \
+ struct builtin_add_overflow<type> \
+ { \
+ static inline bool add(type summand_1, type summand_2, type& result) \
+ { \
+ return builtin_name(summand_1, summand_2, &result) != S_OK; \
+ } \
+ }
+
+ SPECIALIZE_builtin_add_overflow_WIN(unsigned int, UIntAdd);
+ SPECIALIZE_builtin_add_overflow_WIN(unsigned long, ULongAdd);
+ SPECIALIZE_builtin_add_overflow_WIN(unsigned long long, ULongLongAdd);
+
+#undef SPECIALIZE_builtin_add_overflow_WIN
+
+#endif
+
+ } // namespace Internal
+
+ /*!
+ * @brief Safe addition, throws an exception on overflow.
+ *
+ * This function returns the result of summand_1 and summand_2 only when the
+ * operation would not overflow, otherwise an exception of type
+ * std::overflow_error is thrown.
+ *
+ * @param[in] summand_1, summand_2 summands to be summed up
+ * @return the sum of summand_1 and summand_2
+ * @throws std::overflow_error if the addition would overflow
+ *
+ * This function utilizes compiler builtins when available and should have a
+ * very small performance hit then. When builtins are unavailable, a more
+ * extensive check is required.
+ *
+ * Builtins are available for the following configurations:
+ * - GCC/Clang for signed and unsigned int, long and long long (not char & short)
+ * - MSVC for unsigned int, long and long long
+ */
+ template <typename T>
+ T add(T summand_1, T summand_2)
+ {
+ T res = 0;
+ if (Internal::builtin_add_overflow<T>::add(summand_1, summand_2, res)) {
+ throw std::overflow_error("Overflow in addition");
+ }
+ return res;
+ }
+
+} // namespace Safe
+
+#endif // SAFE_OP_HPP_

View File

@ -1,344 +0,0 @@
diff --git a/include/exiv2/error.hpp b/include/exiv2/error.hpp
index 24a70bf6..cc67725b 100644
--- a/include/exiv2/error.hpp
+++ b/include/exiv2/error.hpp
@@ -192,6 +192,74 @@ namespace Exiv2 {
return os << error.what();
}
+ //! Complete list of all Exiv2 error codes
+ enum ErrorCode {
+ kerGeneralError = -1,
+ kerSuccess = 0,
+ kerErrorMessage,
+ kerCallFailed,
+ kerNotAnImage,
+ kerInvalidDataset,
+ kerInvalidRecord,
+ kerInvalidKey,
+ kerInvalidTag,
+ kerValueNotSet,
+ kerDataSourceOpenFailed,
+ kerFileOpenFailed,
+ kerFileContainsUnknownImageType,
+ kerMemoryContainsUnknownImageType,
+ kerUnsupportedImageType,
+ kerFailedToReadImageData,
+ kerNotAJpeg,
+ kerFailedToMapFileForReadWrite,
+ kerFileRenameFailed,
+ kerTransferFailed,
+ kerMemoryTransferFailed,
+ kerInputDataReadFailed,
+ kerImageWriteFailed,
+ kerNoImageInInputData,
+ kerInvalidIfdId,
+ //! Entry::setValue: Value too large
+ kerValueTooLarge,
+ //! Entry::setDataArea: Value too large
+ kerDataAreaValueTooLarge,
+ kerOffsetOutOfRange,
+ kerUnsupportedDataAreaOffsetType,
+ kerInvalidCharset,
+ kerUnsupportedDateFormat,
+ kerUnsupportedTimeFormat,
+ kerWritingImageFormatUnsupported,
+ kerInvalidSettingForImage,
+ kerNotACrwImage,
+ kerFunctionNotSupported,
+ kerNoNamespaceInfoForXmpPrefix,
+ kerNoPrefixForNamespace,
+ kerTooLargeJpegSegment,
+ kerUnhandledXmpdatum,
+ kerUnhandledXmpNode,
+ kerXMPToolkitError,
+ kerDecodeLangAltPropertyFailed,
+ kerDecodeLangAltQualifierFailed,
+ kerEncodeLangAltPropertyFailed,
+ kerPropertyNameIdentificationFailed,
+ kerSchemaNamespaceNotRegistered,
+ kerNoNamespaceForPrefix,
+ kerAliasesNotSupported,
+ kerInvalidXmpText,
+ kerTooManyTiffDirectoryEntries,
+ kerMultipleTiffArrayElementTagsInDirectory,
+ kerWrongTiffArrayElementTagType,
+ kerInvalidKeyXmpValue,
+ kerInvalidIccProfile,
+ kerInvalidXMP,
+ kerTiffDirectoryTooLarge,
+ kerInvalidTypeValue,
+ kerInvalidMalloc,
+ kerCorruptedMetadata,
+ kerArithmeticOverflow,
+ kerMallocFailed,
+ };
+
/*!
@brief Simple error class used for exceptions. An output operator is
provided to print errors to a stream.
diff --git a/src/enforce.hpp b/src/enforce.hpp
new file mode 100644
index 00000000..b2d77eea
--- /dev/null
+++ b/src/enforce.hpp
@@ -0,0 +1,96 @@
+// ********************************************************* -*- C++ -*-
+/*
+ * Copyright (C) 2004-2018 Exiv2 maintainers
+ *
+ * This program is part of the Exiv2 distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
+ */
+/*!
+ @file enforce.hpp
+ @brief Port of D's enforce() to C++ & Exiv2
+ @author Dan Čermák (D4N)
+ <a href="mailto:dan.cermak@cgc-instruments.com">dan.cermak@cgc-instruments.com</a>
+ @date 11-March-18, D4N: created
+ */
+
+#include <string>
+
+#include "error.hpp"
+
+/*!
+ * @brief Ensure that condition is true, otherwise throw an exception of the
+ * type exception_t
+ *
+ * @tparam exception_t Exception type that is thrown, must provide a
+ * constructor that accepts a single argument to which arg1 is forwarded.
+ *
+ * @todo once we have C++>=11 use variadic templates and std::forward to remove
+ * all overloads of enforce
+ */
+template <typename exception_t, typename T>
+inline void enforce(bool condition, const T& arg1)
+{
+ if (!condition) {
+ throw exception_t(arg1);
+ }
+}
+
+/*!
+ * @brief Ensure that condition is true, otherwise throw an Exiv2::Error with
+ * the given error_code.
+ */
+inline void enforce(bool condition, Exiv2::ErrorCode err_code)
+{
+ if (!condition) {
+ throw Exiv2::Error(err_code);
+ }
+}
+
+/*!
+ * @brief Ensure that condition is true, otherwise throw an Exiv2::Error with
+ * the given error_code & arg1.
+ */
+template <typename T>
+inline void enforce(bool condition, Exiv2::ErrorCode err_code, const T& arg1)
+{
+ if (!condition) {
+ throw Exiv2::Error(err_code, arg1);
+ }
+}
+
+/*!
+ * @brief Ensure that condition is true, otherwise throw an Exiv2::Error with
+ * the given error_code, arg1 & arg2.
+ */
+template <typename T, typename U>
+inline void enforce(bool condition, Exiv2::ErrorCode err_code, const T& arg1, const U& arg2)
+{
+ if (!condition) {
+ throw Exiv2::Error(err_code, arg1, arg2);
+ }
+}
+
+/*!
+ * @brief Ensure that condition is true, otherwise throw an Exiv2::Error with
+ * the given error_code, arg1, arg2 & arg3.
+ */
+template <typename T, typename U, typename V>
+inline void enforce(bool condition, Exiv2::ErrorCode err_code, const T& arg1, const U& arg2, const V& arg3)
+{
+ if (!condition) {
+ throw Exiv2::Error(err_code, arg1, arg2, arg3);
+ }
+}
diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index 4dcca4d..aae0f5f 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -37,6 +37,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "iptc.hpp"
#include "image.hpp"
#include "error.hpp"
+#include "enforce.hpp"
// + standard includes
#include <sstream>
@@ -46,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$")
#include <iostream>
#include <cassert>
#include <cstdio>
+#include <algorithm>
#include <zlib.h> // To uncompress or compress text chunk
@@ -86,7 +88,7 @@ namespace Exiv2 {
#ifdef DEBUG
std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk data: "
- << std::string((const char*)arr.pData_, arr.size_) << "\n";
+ << std::string((const char*)arr.pData_, arr.size_) << std::endl;
#endif
parseChunkContent(pImage, key.pData_, key.size_, arr);
@@ -99,7 +101,7 @@ namespace Exiv2 {
#ifdef DEBUG
std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk key: "
- << std::string((const char*)key.pData_, key.size_) << "\n";
+ << std::string((const char*)key.pData_, key.size_) << std::endl;
#endif
return parseTXTChunk(data, key.size_, type);
@@ -164,12 +166,18 @@ namespace Exiv2 {
}
else if(type == iTXt_Chunk)
{
+ const int nullSeparators = std::count(&data.pData_[keysize+3], &data.pData_[data.size_], '\0');
+
+ enforce(nullSeparators >= 2, Exiv2::kerCorruptedMetadata);
+
// Extract a deflate compressed or uncompressed UTF-8 text chunk
// we get the compression flag after the key
- const byte* compressionFlag = data.pData_ + keysize + 1;
+ const byte compressionFlag = data.pData_[keysize + 1];
// we get the compression method after the compression flag
- const byte* compressionMethod = data.pData_ + keysize + 2;
+ const byte compressionMethod = data.pData_[keysize + 2];
+ enforce(compressionFlag == 0x00 || compressionFlag == 0x01, Exiv2::kerCorruptedMetadata);
+ enforce(compressionMethod == 0x00, Exiv2::kerCorruptedMetadata);
// language description string after the compression technique spec
std::string languageText((const char*)(data.pData_ + keysize + 3));
unsigned int languageTextSize = static_cast<unsigned int>(languageText.size());
@@ -177,7 +185,7 @@ namespace Exiv2 {
std::string translatedKeyText((const char*)(data.pData_ + keysize + 3 + languageTextSize +1));
unsigned int translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
- if ( compressionFlag[0] == 0x00 )
+ if ( compressionFlag == 0x00 )
{
// then it's an uncompressed iTXt chunk
#ifdef DEBUG
@@ -191,7 +199,7 @@ namespace Exiv2 {
arr.alloc(textsize);
arr = DataBuf(text, textsize);
}
- else if ( compressionFlag[0] == 0x01 && compressionMethod[0] == 0x00 )
+ else if ( compressionFlag == 0x01 && compressionMethod == 0x00 )
{
// then it's a zlib compressed iTXt chunk
#ifdef DEBUG
diff --git a/src/pngimage.cpp b/src/pngimage.cpp
index ed7399a..991da6c 100644
--- a/src/pngimage.cpp
+++ b/src/pngimage.cpp
@@ -375,7 +375,7 @@ namespace Exiv2 {
void PngImage::readMetadata()
{
#ifdef DEBUG
- std::cerr << "Exiv2::PngImage::readMetadata: Reading PNG file " << io_->path() << "\n";
+ std::cerr << "Exiv2::PngImage::readMetadata: Reading PNG file " << io_->path() << std::endl;
#endif
if (io_->open() != 0)
{
@@ -398,7 +398,7 @@ namespace Exiv2 {
// Read chunk header.
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Position: " << io_->tell() << "\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Position: " << io_->tell() << std::endl;
#endif
std::memset(cheaderBuf.pData_, 0x0, cheaderBuf.size_);
long bufRead = io_->read(cheaderBuf.pData_, cheaderBuf.size_);
@@ -432,14 +432,14 @@ namespace Exiv2 {
{
// Last chunk found: we stop parsing.
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Found IEND chunk (length: " << dataOffset << ")\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Found IEND chunk with length: " << dataOffset << std::endl;
#endif
return;
}
else if (!memcmp(cheaderBuf.pData_ + 4, "IHDR", 4))
{
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Found IHDR chunk (length: " << dataOffset << ")\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Found IHDR chunk with length: " << dataOffset << std::endl;
#endif
if (cdataBuf.size_ >= 8) {
PngChunk::decodeIHDRChunk(cdataBuf, &pixelWidth_, &pixelHeight_);
@@ -448,21 +448,21 @@ namespace Exiv2 {
else if (!memcmp(cheaderBuf.pData_ + 4, "tEXt", 4))
{
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Found tEXt chunk (length: " << dataOffset << ")\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Found tEXt chunk with length: " << dataOffset << std::endl;
#endif
PngChunk::decodeTXTChunk(this, cdataBuf, PngChunk::tEXt_Chunk);
}
else if (!memcmp(cheaderBuf.pData_ + 4, "zTXt", 4))
{
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Found zTXt chunk (length: " << dataOffset << ")\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Found zTXt chunk with length: " << dataOffset << std::endl;
#endif
PngChunk::decodeTXTChunk(this, cdataBuf, PngChunk::zTXt_Chunk);
}
else if (!memcmp(cheaderBuf.pData_ + 4, "iTXt", 4))
{
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Found iTXt chunk (length: " << dataOffset << ")\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Found iTXt chunk with length: " << dataOffset << std::endl;
#endif
PngChunk::decodeTXTChunk(this, cdataBuf, PngChunk::iTXt_Chunk);
}
@@ -481,7 +481,7 @@ namespace Exiv2 {
// Move to the next chunk: chunk data size + 4 CRC bytes.
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::readMetadata: Seek to offset: " << dataOffset + 4 << "\n";
+ std::cout << "Exiv2::PngImage::readMetadata: Seek to offset: " << dataOffset + 4 << std::endl;
#endif
io_->seek(dataOffset + 4 , BasicIo::cur);
if (io_->error() || io_->eof()) throw Error(14);
@@ -511,8 +511,8 @@ namespace Exiv2 {
if (!outIo.isopen()) throw Error(21);
#ifdef DEBUG
- std::cout << "Exiv2::PngImage::doWriteMetadata: Writing PNG file " << io_->path() << "\n";
- std::cout << "Exiv2::PngImage::doWriteMetadata: tmp file created " << outIo.path() << "\n";
+ std::cout << "Exiv2::PngImage::doWriteMetadata: Writing PNG file " << io_->path() << std::endl;
+ std::cout << "Exiv2::PngImage::doWriteMetadata: tmp file created " << outIo.path() << std::endl;
#endif
// Ensure that this is the correct image type

View File

@ -1,61 +0,0 @@
diff --git a/src/exiv2.cpp b/src/exiv2.cpp
index d6a45e1..dbd2834 100644
--- a/src/exiv2.cpp
+++ b/src/exiv2.cpp
@@ -150,31 +150,35 @@ int main(int argc, char* const argv[])
return 0;
}
- // Create the required action class
- Action::TaskFactory& taskFactory = Action::TaskFactory::instance();
- Action::Task::AutoPtr task
- = taskFactory.create(Action::TaskType(params.action_));
- assert(task.get());
-
- // Process all files
int rc = 0;
- int n = 1;
- int s = static_cast<int>(params.files_.size());
- int w = s > 9 ? s > 99 ? 3 : 2 : 1;
- for (Params::Files::const_iterator i = params.files_.begin();
- i != params.files_.end(); ++i) {
- if (params.verbose_) {
- std::cout << _("File") << " " << std::setw(w) << std::right << n++ << "/" << s << ": "
- << *i << std::endl;
+ try {
+ // Create the required action class
+ Action::TaskFactory& taskFactory = Action::TaskFactory::instance();
+ Action::Task::AutoPtr task = taskFactory.create(Action::TaskType(params.action_));
+ assert(task.get());
+
+ // Process all files
+ int n = 1;
+ int s = static_cast<int>(params.files_.size());
+ int w = s > 9 ? s > 99 ? 3 : 2 : 1;
+ for (Params::Files::const_iterator i = params.files_.begin(); i != params.files_.end(); ++i) {
+ if (params.verbose_) {
+ std::cout << _("File") << " " << std::setw(w) << std::right << n++ << "/" << s << ": " << *i
+ << std::endl;
+ }
+ int ret = task->run(*i);
+ if (rc == 0)
+ rc = ret;
}
- int ret = task->run(*i);
- if (rc == 0) rc = ret;
- }
- taskFactory.cleanup();
- params.cleanup();
- Exiv2::XmpParser::terminate();
+ taskFactory.cleanup();
+ params.cleanup();
+ Exiv2::XmpParser::terminate();
+ } catch (const std::exception& exc) {
+ std::cerr << "Uncaught exception: " << exc.what() << std::endl;
+ rc = 1;
+ }
// Return a positive one byte code for better consistency across platforms
return static_cast<unsigned int>(rc) % 256;
} // main

View File

@ -1,31 +0,0 @@
diff --git a/src/preview.cpp b/src/preview.cpp
index c34c8bd..69f8e01 100644
--- a/src/preview.cpp
+++ b/src/preview.cpp
@@ -36,6 +36,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "preview.hpp"
#include "futils.hpp"
+#include "enforce.hpp"
#include "image.hpp"
#include "cr2image.hpp"
@@ -807,13 +808,14 @@ namespace {
else {
// FIXME: the buffer is probably copied twice, it should be optimized
DataBuf buf(size_);
- Exiv2::byte* pos = buf.pData_;
+ uint32_t idxBuf = 0;
for (int i = 0; i < sizes.count(); i++) {
uint32_t offset = dataValue.toLong(i);
uint32_t size = sizes.toLong(i);
- if (offset + size <= static_cast<uint32_t>(io.size()))
- memcpy(pos, base + offset, size);
- pos += size;
+ enforce(idxBuf + size < size_, kerCorruptedMetadata);
+ if (size!=0 && offset + size <= static_cast<uint32_t>(io.size()))
+ memcpy(&buf.pData_[idxBuf], base + offset, size);
+ idxBuf += size;
}
dataValue.setDataArea(buf.pData_, buf.size_);
}

View File

@ -1,60 +0,0 @@
diff --git a/src/preview.cpp b/src/preview.cpp
index 69f8e01..d20de04 100644
--- a/src/preview.cpp
+++ b/src/preview.cpp
@@ -37,6 +37,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "preview.hpp"
#include "futils.hpp"
#include "enforce.hpp"
+#include "safe_op.hpp"
#include "image.hpp"
#include "cr2image.hpp"
@@ -386,7 +387,7 @@ namespace {
return AutoPtr();
if (loaderList_[id].imageMimeType_ &&
- std::string(loaderList_[id].imageMimeType_) != std::string(image.mimeType()))
+ std::string(loaderList_[id].imageMimeType_) != image.mimeType())
return AutoPtr();
AutoPtr loader = loaderList_[id].create_(id, image, loaderList_[id].parIdx_);
@@ -548,7 +549,8 @@ namespace {
}
}
- if (offset_ + size_ > static_cast<uint32_t>(image_.io().size())) return;
+ if (Safe::add(offset_, size_) > static_cast<uint32_t>(image_.io().size()))
+ return;
valid_ = true;
}
@@ -802,7 +804,7 @@ namespace {
// this saves one copying of the buffer
uint32_t offset = dataValue.toLong(0);
uint32_t size = sizes.toLong(0);
- if (offset + size <= static_cast<uint32_t>(io.size()))
+ if (Safe::add(offset, size) <= static_cast<uint32_t>(io.size()))
dataValue.setDataArea(base + offset, size);
}
else {
@@ -812,8 +814,8 @@ namespace {
for (int i = 0; i < sizes.count(); i++) {
uint32_t offset = dataValue.toLong(i);
uint32_t size = sizes.toLong(i);
- enforce(idxBuf + size < size_, kerCorruptedMetadata);
- if (size!=0 && offset + size <= static_cast<uint32_t>(io.size()))
+ enforce(Safe::add(idxBuf, size) < size_, kerCorruptedMetadata);
+ if (size!=0 && Safe::add(offset, size) <= static_cast<uint32_t>(io.size()))
memcpy(&buf.pData_[idxBuf], base + offset, size);
idxBuf += size;
}
@@ -930,7 +932,7 @@ namespace {
DataBuf decodeBase64(const std::string& src)
{
- const unsigned long srcSize = static_cast<const unsigned long>(src.size());
+ const unsigned long srcSize = src.size();
// create decoding table
unsigned long invalid = 64;

View File

@ -1,49 +0,0 @@
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index e4057d6..f1dd77c 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -44,6 +44,8 @@
#include "tiffimage.hpp"
#include "tiffimage_int.hpp"
#include "convert.hpp"
+#include "enforce.hpp"
+
#include <cmath>
#include <iomanip>
#include <string>
@@ -516,6 +518,8 @@ namespace Exiv2 {
DataBuf payload(size);
if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8X) && !has_canvas_data) {
+ enforce(size >= 10, Exiv2::kerCorruptedMetadata);
+
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];
@@ -531,6 +535,8 @@ namespace Exiv2 {
size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8) && !has_canvas_data) {
+ enforce(size >= 10, Exiv2::kerCorruptedMetadata);
+
has_canvas_data = true;
io_->read(payload.pData_, payload.size_);
byte size_buf[WEBP_TAG_SIZE];
@@ -547,6 +553,8 @@ namespace Exiv2 {
size_buf[3] = 0;
pixelHeight_ = Exiv2::getULong(size_buf, littleEndian) & 0x3fff;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_VP8L) && !has_canvas_data) {
+ enforce(size >= 5, Exiv2::kerCorruptedMetadata);
+
has_canvas_data = true;
byte size_buf_w[2];
byte size_buf_h[3];
@@ -564,6 +572,8 @@ namespace Exiv2 {
size_buf_h[1] = ((size_buf_h[1] >> 6) & 0x3) | ((size_buf_h[2] & 0xF) << 0x2);
pixelHeight_ = Exiv2::getUShort(size_buf_h, littleEndian) + 1;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_ANMF) && !has_canvas_data) {
+ enforce(size >= 12, Exiv2::kerCorruptedMetadata);
+
has_canvas_data = true;
byte size_buf[WEBP_TAG_SIZE];

View File

@ -1,76 +0,0 @@
diff --git a/src/cr2image.cpp b/src/cr2image.cpp
index 2907426..b6fa315 100644
--- a/src/cr2image.cpp
+++ b/src/cr2image.cpp
@@ -107,8 +107,6 @@ namespace Exiv2 {
throw Error(3, "CR2");
}
clearMetadata();
- std::ofstream devnull;
- printStructure(devnull, kpsRecursive, 0);
ByteOrder bo = Cr2Parser::decode(exifData_,
iptcData_,
xmpData_,
diff --git a/src/crwimage.cpp b/src/crwimage.cpp
index ca79aa7..11cd14c 100644
--- a/src/crwimage.cpp
+++ b/src/crwimage.cpp
@@ -131,15 +131,8 @@ namespace Exiv2 {
throw Error(33);
}
clearMetadata();
- // read all metadata into memory
- // we should put this into clearMetadata(), however it breaks the test suite!
- try {
- std::ofstream devnull;
- printStructure(devnull,kpsRecursive,0);
- } catch (Exiv2::Error& /* e */) {
- DataBuf file(io().size());
- io_->read(file.pData_,file.size_);
- }
+ DataBuf file( (long) io().size());
+ io_->read(file.pData_,file.size_);
CrwParser::decode(this, io_->mmap(), io_->size());
diff --git a/src/orfimage.cpp b/src/orfimage.cpp
index c516591..9a17a50 100644
--- a/src/orfimage.cpp
+++ b/src/orfimage.cpp
@@ -119,8 +119,6 @@ namespace Exiv2 {
throw Error(3, "ORF");
}
clearMetadata();
- std::ofstream devnull;
- printStructure(devnull, kpsRecursive, 0);
ByteOrder bo = OrfParser::decode(exifData_,
iptcData_,
xmpData_,
diff --git a/src/rw2image.cpp b/src/rw2image.cpp
index 95f3b28..764de6f 100644
--- a/src/rw2image.cpp
+++ b/src/rw2image.cpp
@@ -130,8 +130,6 @@ namespace Exiv2 {
throw Error(3, "RW2");
}
clearMetadata();
- std::ofstream devnull;
- printStructure(devnull, kpsRecursive, 0);
ByteOrder bo = Rw2Parser::decode(exifData_,
iptcData_,
xmpData_,
diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp
index f20c69e..9e6eda4 100644
--- a/src/tiffimage.cpp
+++ b/src/tiffimage.cpp
@@ -185,10 +185,6 @@ namespace Exiv2 {
}
clearMetadata();
- // recursively print the structure to /dev/null to ensure all metadata is in memory
- // must be recursive to handle NEFs which stores the raw image in a subIFDs
- std::ofstream devnull;
- printStructure(devnull,kpsRecursive,0);
ByteOrder bo = TiffParser::decode(exifData_,
iptcData_,
xmpData_,

View File

@ -1,466 +0,0 @@
diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp
index 9afcb58..ca83f14 100644
--- a/src/jpgimage.cpp
+++ b/src/jpgimage.cpp
@@ -34,6 +34,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "image_int.hpp"
#include "error.hpp"
#include "futils.hpp"
+#include "enforce.hpp"
#ifdef WIN32
#include <windows.h>
@@ -328,12 +329,14 @@ namespace Exiv2 {
int c = -1;
// Skips potential padding between markers
while ((c=io_->getb()) != 0xff) {
- if (c == EOF) return -1;
+ if (c == EOF)
+ return -1;
}
// Markers can start with any number of 0xff
while ((c=io_->getb()) == 0xff) {
- if (c == EOF) return -2;
+ if (c == EOF)
+ return -2;
}
return c;
}
@@ -564,85 +567,88 @@ namespace Exiv2 {
out << Internal::stringFormat("%8ld | 0xff%02x %-5s", \
io_->tell()-2,marker,nm[marker].c_str())
- void JpegBase::printStructure(std::ostream& out, PrintStructureOption option,int depth)
+ void JpegBase::printStructure(std::ostream& out, PrintStructureOption option, int depth)
{
- if (io_->open() != 0) throw Error(9, io_->path(), strError());
+ if (io_->open() != 0)
+ throw Error(9, io_->path(), strError());
// Ensure that this is the correct image type
if (!isThisType(*io_, false)) {
- if (io_->error() || io_->eof()) throw Error(14);
+ if (io_->error() || io_->eof())
+ throw Error(14);
throw Error(15);
}
- bool bPrint = option==kpsBasic || option==kpsRecursive;
+ bool bPrint = option == kpsBasic || option == kpsRecursive;
Exiv2::Uint32Vector iptcDataSegs;
- if ( bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase ) {
+ if (bPrint || option == kpsXMP || option == kpsIccProfile || option == kpsIptcErase) {
// nmonic for markers
- std::string nm[256] ;
- nm[0xd8]="SOI" ;
- nm[0xd9]="EOI" ;
- nm[0xda]="SOS" ;
- nm[0xdb]="DQT" ;
- nm[0xdd]="DRI" ;
- nm[0xfe]="COM" ;
+ std::string nm[256];
+ nm[0xd8] = "SOI";
+ nm[0xd9] = "EOI";
+ nm[0xda] = "SOS";
+ nm[0xdb] = "DQT";
+ nm[0xdd] = "DRI";
+ nm[0xfe] = "COM";
// 0xe0 .. 0xef are APPn
// 0xc0 .. 0xcf are SOFn (except 4)
- nm[0xc4]="DHT" ;
- for ( int i = 0 ; i <= 15 ; i++ ) {
+ nm[0xc4] = "DHT";
+ for (int i = 0; i <= 15; i++) {
char MN[10];
- sprintf(MN,"APP%d",i);
- nm[0xe0+i] = MN;
- if ( i != 4 ) {
- sprintf(MN,"SOF%d",i);
- nm[0xc0+i] = MN;
+ sprintf(MN, "APP%d", i);
+ nm[0xe0 + i] = MN;
+ if (i != 4) {
+ sprintf(MN, "SOF%d", i);
+ nm[0xc0 + i] = MN;
}
}
// which markers have a length field?
bool mHasLength[256];
- for ( int i = 0 ; i < 256 ; i ++ )
- mHasLength[i]
- = ( i >= sof0_ && i <= sof15_)
- || ( i >= app0_ && i <= (app0_ | 0x0F))
- || ( i == dht_ || i == dqt_ || i == dri_ || i == com_ || i == sos_ )
- ;
+ for (int i = 0; i < 256; i++)
+ mHasLength[i] = (i >= sof0_ && i <= sof15_) || (i >= app0_ && i <= (app0_ | 0x0F)) ||
+ (i == dht_ || i == dqt_ || i == dri_ || i == com_ || i == sos_);
// Container for the signature
- bool bExtXMP = false;
- long bufRead = 0;
- const long bufMinSize = 36;
- DataBuf buf(bufMinSize);
+ bool bExtXMP = false;
+ long bufRead = 0;
+ const long bufMinSize = 36;
+ DataBuf buf(bufMinSize);
// Read section marker
int marker = advanceToMarker();
- if (marker < 0) throw Error(15);
+ if (marker < 0)
+ throw Error(15);
- bool done = false;
- bool first= true;
+ bool done = false;
+ bool first = true;
while (!done) {
// print marker bytes
- if ( first && bPrint ) {
+ if (first && bPrint) {
out << "STRUCTURE OF JPEG FILE: " << io_->path() << std::endl;
- out << " address | marker | length | data" << std::endl ;
+ out << " address | marker | length | data" << std::endl;
REPORT_MARKER;
}
- first = false;
+ first = false;
bool bLF = bPrint;
// Read size and signature
std::memset(buf.pData_, 0x0, buf.size_);
bufRead = io_->read(buf.pData_, bufMinSize);
- if (io_->error()) throw Error(14);
- if (bufRead < 2) throw Error(15);
- uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0 ;
- if ( bPrint && mHasLength[marker] ) out << Internal::stringFormat(" | %7d ", size);
+ if (io_->error())
+ throw Error(14);
+ if (bufRead < 2)
+ throw Error(15);
+ uint16_t size = mHasLength[marker] ? getUShort(buf.pData_, bigEndian) : 0;
+ if (bPrint && mHasLength[marker])
+ out << Internal::stringFormat(" | %7d ", size);
// print signature for APPn
if (marker >= app0_ && marker <= (app0_ | 0x0F)) {
// http://www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf p75
- const char* signature = (const char*) buf.pData_+2;
+ const char* signature = (const char*)buf.pData_ + 2;
// 728 rmills@rmillsmbp:~/gnu/exiv2/ttt $ exiv2 -pS test/data/exiv2-bug922.jpg
// STRUCTURE OF JPEG FILE: test/data/exiv2-bug922.jpg
@@ -651,13 +657,13 @@ namespace Exiv2 {
// 2 | 0xe1 APP1 | 911 | Exif..MM.*.......%.........#....
// 915 | 0xe1 APP1 | 870 | http://ns.adobe.com/xap/1.0/.<x:
// 1787 | 0xe1 APP1 | 65460 | http://ns.adobe.com/xmp/extensio
- if ( option == kpsXMP && std::string(signature).find("http://ns.adobe.com/x")== 0 ) {
+ if (option == kpsXMP && std::string(signature).find("http://ns.adobe.com/x") == 0) {
// extract XMP
- if ( size > 0 ) {
- io_->seek(-bufRead , BasicIo::cur);
- byte* xmp = new byte[size+1];
- io_->read(xmp,size);
- int start = 0 ;
+ if (size > 0) {
+ io_->seek(-bufRead, BasicIo::cur);
+ byte* xmp = new byte[size + 1];
+ io_->read(xmp, size);
+ int start = 0;
// http://wwwimages.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
// if we find HasExtendedXMP, set the flag and ignore this block
@@ -666,79 +672,80 @@ namespace Exiv2 {
// we could implement out of sequence with a dictionary of sequence/offset
// and dumping the XMP in a post read operation similar to kpsIptcErase
// for the moment, dumping 'on the fly' is working fine
- if ( ! bExtXMP ) {
- while (xmp[start]) start++;
+ if (!bExtXMP) {
+ while (xmp[start])
+ start++;
start++;
- if ( ::strstr((char*)xmp+start,"HasExtendedXMP") ) {
- start = size ; // ignore this packet, we'll get on the next time around
+ if (::strstr((char*)xmp + start, "HasExtendedXMP")) {
+ start = size; // ignore this packet, we'll get on the next time around
bExtXMP = true;
}
} else {
- start = 2+35+32+4+4; // Adobe Spec, p19
+ start = 2 + 35 + 32 + 4 + 4; // Adobe Spec, p19
}
- out.write((const char*)(xmp+start),size-start);
- delete [] xmp;
+ out.write((const char*)(xmp + start), size - start);
+ delete[] xmp;
bufRead = size;
done = !bExtXMP;
}
- } else if ( option == kpsIccProfile && std::strcmp(signature,iccId_) == 0 ) {
+ } else if (option == kpsIccProfile && std::strcmp(signature, iccId_) == 0) {
// extract ICCProfile
- if ( size > 0 ) {
- io_->seek(-bufRead, BasicIo::cur); // back to buffer (after marker)
- io_->seek( 14+2, BasicIo::cur); // step over header
- DataBuf icc(size-(14+2));
- io_->read( icc.pData_,icc.size_);
- out.write((const char*)icc.pData_,icc.size_);
+ if (size > 0) {
+ io_->seek(-bufRead, BasicIo::cur); // back to buffer (after marker)
+ io_->seek(14 + 2, BasicIo::cur); // step over header
+ DataBuf icc(size - (14 + 2));
+ io_->read(icc.pData_, icc.size_);
+ out.write((const char*)icc.pData_, icc.size_);
#ifdef DEBUG
std::cout << "iccProfile size = " << icc.size_ << std::endl;
#endif
bufRead = size;
}
- } else if ( option == kpsIptcErase && std::strcmp(signature,"Photoshop 3.0") == 0 ) {
+ } else if (option == kpsIptcErase && std::strcmp(signature, "Photoshop 3.0") == 0) {
// delete IPTC data segment from JPEG
- if ( size > 0 ) {
- io_->seek(-bufRead , BasicIo::cur);
+ if (size > 0) {
+ io_->seek(-bufRead, BasicIo::cur);
iptcDataSegs.push_back(io_->tell());
iptcDataSegs.push_back(size);
}
- } else if ( bPrint ) {
- out << "| " << Internal::binaryToString(buf,size>32?32:size,size>0?2:0);
- if ( std::strcmp(signature,iccId_) == 0 ) {
- int chunk = (int) signature[12];
- int chunks = (int) signature[13];
- out << Internal::stringFormat(" chunk %d/%d",chunk,chunks);
+ } else if (bPrint) {
+ out << "| " << Internal::binaryToString(buf, size > 32 ? 32 : size, size > 0 ? 2 : 0);
+ if (std::strcmp(signature, iccId_) == 0) {
+ int chunk = (int)signature[12];
+ int chunks = (int)signature[13];
+ out << Internal::stringFormat(" chunk %d/%d", chunk, chunks);
}
}
// for MPF: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/MPF.html
// for FLIR: http://owl.phy.queensu.ca/~phil/exiftool/TagNames/FLIR.html
- bool bFlir = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"FLIR")==0;
- bool bExif = option == kpsRecursive && marker == (app0_+1) && std::strcmp(signature,"Exif")==0;
- bool bMPF = option == kpsRecursive && marker == (app0_+2) && std::strcmp(signature,"MPF")==0;
- bool bPS = option == kpsRecursive && std::strcmp(signature,"Photoshop 3.0")==0;
- if( bFlir || bExif || bMPF || bPS ) {
+ bool bFlir = option == kpsRecursive && marker == (app0_ + 1) && std::strcmp(signature, "FLIR") == 0;
+ bool bExif = option == kpsRecursive && marker == (app0_ + 1) && std::strcmp(signature, "Exif") == 0;
+ bool bMPF = option == kpsRecursive && marker == (app0_ + 2) && std::strcmp(signature, "MPF") == 0;
+ bool bPS = option == kpsRecursive && std::strcmp(signature, "Photoshop 3.0") == 0;
+ if (bFlir || bExif || bMPF || bPS) {
// extract Exif data block which is tiff formatted
- if ( size > 0 ) {
+ if (size > 0) {
out << std::endl;
// allocate storage and current file position
- byte* exif = new byte[size];
- uint32_t restore = io_->tell();
+ byte* exif = new byte[size];
+ uint32_t restore = io_->tell();
// copy the data to memory
- io_->seek(-bufRead , BasicIo::cur);
- io_->read(exif,size);
- uint32_t start = std::strcmp(signature,"Exif")==0 ? 8 : 6;
- uint32_t max = (uint32_t) size -1;
+ io_->seek(-bufRead, BasicIo::cur);
+ io_->read(exif, size);
+ uint32_t start = std::strcmp(signature, "Exif") == 0 ? 8 : 6;
+ uint32_t max = (uint32_t)size - 1;
// is this an fff block?
- if ( bFlir ) {
- start = 0 ;
+ if (bFlir) {
+ start = 0;
bFlir = false;
- while ( start < max ) {
- if ( std::strcmp((const char*)(exif+start),"FFF")==0 ) {
- bFlir = true ;
+ while (start < max) {
+ if (std::strcmp((const char*)(exif + start), "FFF") == 0) {
+ bFlir = true;
break;
}
start++;
@@ -747,78 +754,90 @@ namespace Exiv2 {
// there is a header in FLIR, followed by a tiff block
// Hunt down the tiff using brute force
- if ( bFlir ) {
+ if (bFlir) {
// FLIRFILEHEAD* pFFF = (FLIRFILEHEAD*) (exif+start) ;
- while ( start < max ) {
- if ( exif[start] == 'I' && exif[start+1] == 'I' ) break;
- if ( exif[start] == 'M' && exif[start+1] == 'M' ) break;
+ while (start < max) {
+ if (exif[start] == 'I' && exif[start + 1] == 'I')
+ break;
+ if (exif[start] == 'M' && exif[start + 1] == 'M')
+ break;
start++;
}
- if ( start < max ) std::cout << " FFF start = " << start << std::endl ;
+ if ( start < max )
+ std::cout << " FFF start = " << start << std::endl;
// << " index = " << pFFF->dwIndexOff << std::endl;
}
- if ( bPS ) {
- IptcData::printStructure(out,exif,size,depth);
+ if (bPS) {
+ IptcData::printStructure(out, exif, size, depth);
} else {
// create a copy on write memio object with the data, then print the structure
- BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif+start,size-start));
- if ( start < max ) printTiffStructure(*p,out,option,depth);
+ BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif + start, size - start));
+ if (start < max)
+ printTiffStructure(*p, out, option, depth);
}
// restore and clean up
- io_->seek(restore,Exiv2::BasicIo::beg);
- delete [] exif;
- bLF = false;
+ io_->seek(restore, Exiv2::BasicIo::beg);
+ delete[] exif;
+ bLF = false;
}
}
}
// print COM marker
- if ( bPrint && marker == com_ ) {
- int n = (size-2)>32?32:size-2; // size includes 2 for the two bytes for size!
- out << "| " << Internal::binaryToString(buf,n,2); // start after the two bytes
+ if (bPrint && marker == com_) {
+ int n = (size - 2) > 32 ? 32 : size - 2; // size includes 2 for the two bytes for size!
+ out << "| " << Internal::binaryToString(buf, n, 2); // start after the two bytes
}
// Skip the segment if the size is known
- if (io_->seek(size - bufRead, BasicIo::cur)) throw Error(14);
+ if (io_->seek(size - bufRead, BasicIo::cur))
+ throw Error(14);
- if ( bLF ) out << std::endl;
+ if (bLF)
+ out << std::endl;
if (marker != sos_) {
// Read the beginning of the next segment
marker = advanceToMarker();
+ enforce(marker>=0, kerNoImageInInputData);
REPORT_MARKER;
}
done |= marker == eoi_ || marker == sos_;
- if ( done && bPrint ) out << std::endl;
+ if (done && bPrint)
+ out << std::endl;
}
}
- if ( option == kpsIptcErase && iptcDataSegs.size() ) {
+ if (option == kpsIptcErase && iptcDataSegs.size()) {
#ifdef DEBUG
std::cout << "iptc data blocks: " << iptcDataSegs.size() << std::endl;
- uint32_t toggle = 0 ;
- for ( Uint32Vector_i i = iptcDataSegs.begin(); i != iptcDataSegs.end() ; i++ ) {
- std::cout << *i ;
- if ( toggle++ % 2 ) std::cout << std::endl; else std::cout << ' ' ;
+ uint32_t toggle = 0;
+ for (Uint32Vector_i i = iptcDataSegs.begin(); i != iptcDataSegs.end(); i++) {
+ std::cout << *i;
+ if (toggle++ % 2)
+ std::cout << std::endl;
+ else
+ std::cout << ' ';
}
#endif
- uint32_t count = (uint32_t) iptcDataSegs.size();
+ uint32_t count = (uint32_t)iptcDataSegs.size();
// figure out which blocks to copy
- uint64_t* pos = new uint64_t[count+2];
- pos[0] = 0 ;
+ uint64_t* pos = new uint64_t[count + 2];
+ pos[0] = 0;
// copy the data that is not iptc
Uint32Vector_i it = iptcDataSegs.begin();
- for ( uint64_t i = 0 ; i < count ; i++ ) {
- bool bOdd = (i%2)!=0;
- bool bEven = !bOdd;
- pos[i+1] = bEven ? *it : pos[i] + *it;
+ for (uint64_t i = 0; i < count; i++) {
+ bool bOdd = (i % 2) != 0;
+ bool bEven = !bOdd;
+ pos[i + 1] = bEven ? *it : pos[i] + *it;
it++;
}
- pos[count+1] = io_->size() - pos[count];
+ pos[count + 1] = io_->size() - pos[count];
#ifdef DEBUG
- for ( uint64_t i = 0 ; i < count+2 ; i++ ) std::cout << pos[i] << " " ;
+ for (uint64_t i = 0; i < count + 2; i++)
+ std::cout << pos[i] << " ";
std::cout << std::endl;
#endif
// $ dd bs=1 skip=$((0)) count=$((13164)) if=ETH0138028.jpg of=E1.jpg
@@ -829,29 +848,30 @@ namespace Exiv2 {
// binary copy io_ to a temporary file
BasicIo::AutoPtr tempIo(new MemIo);
- assert (tempIo.get() != 0);
- for ( uint64_t i = 0 ; i < (count/2)+1 ; i++ ) {
- uint64_t start = pos[2*i]+2 ; // step JPG 2 byte marker
- if ( start == 2 ) start = 0 ; // read the file 2 byte SOI
- long length = (long) (pos[2*i+1] - start) ;
- if ( length ) {
+ assert(tempIo.get() != 0);
+ for (uint64_t i = 0; i < (count / 2) + 1; i++) {
+ uint64_t start = pos[2 * i] + 2; // step JPG 2 byte marker
+ if (start == 2)
+ start = 0; // read the file 2 byte SOI
+ long length = (long)(pos[2 * i + 1] - start);
+ if (length) {
#ifdef DEBUG
- std::cout << start <<":"<< length << std::endl;
+ std::cout << start << ":" << length << std::endl;
#endif
- io_->seek(start,BasicIo::beg);
+ io_->seek(start, BasicIo::beg);
DataBuf buf(length);
- io_->read(buf.pData_,buf.size_);
- tempIo->write(buf.pData_,buf.size_);
+ io_->read(buf.pData_, buf.size_);
+ tempIo->write(buf.pData_, buf.size_);
}
}
- delete [] pos;
+ delete[] pos;
io_->seek(0, BasicIo::beg);
- io_->transfer(*tempIo); // may throw
+ io_->transfer(*tempIo); // may throw
io_->seek(0, BasicIo::beg);
readMetadata();
}
- } // JpegBase::printStructure
+ } // JpegBase::printStructure
void JpegBase::writeMetadata()
{

View File

@ -1,21 +0,0 @@
diff --git a/src/canonmn.cpp b/src/canonmn.cpp
index 450c7d9..f768c05 100644
--- a/src/canonmn.cpp
+++ b/src/canonmn.cpp
@@ -1774,9 +1774,13 @@ namespace Exiv2 {
{
try {
// 1140
- if( metadata->findKey(ExifKey("Exif.Image.Model" ))->value().toString() == "Canon EOS 30D"
- && metadata->findKey(ExifKey("Exif.CanonCs.Lens" ))->value().toString() == "24 24 1"
- && metadata->findKey(ExifKey("Exif.CanonCs.MaxAperture"))->value().toString() == "95" // F2.8
+ const ExifData::const_iterator itModel = metadata->findKey(ExifKey("Exif.Image.Model"));
+ const ExifData::const_iterator itLens = metadata->findKey(ExifKey("Exif.CanonCs.Lens"));
+ const ExifData::const_iterator itApert = metadata->findKey(ExifKey("Exif.CanonCs.MaxAperture"));
+
+ if( itModel != metadata->end() && itModel->value().toString() == "Canon EOS 30D"
+ && itLens != metadata->end() && itLens->value().toString() == "24 24 1"
+ && itApert != metadata->end() && itApert->value().toString() == "95" // F2.8
){
return os << "Canon EF-S 24mm f/2.8 STM" ;
}

View File

@ -1,176 +0,0 @@
diff --git a/src/actions.cpp b/src/actions.cpp
index 0ebe850..3cd398e 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -59,6 +59,7 @@ EXIV2_RCSID("@(#) $Id$")
#include <ctime>
#include <cmath>
#include <cassert>
+#include <stdexcept>
#include <sys/types.h> // for stat()
#include <sys/stat.h> // for stat()
#ifdef EXV_HAVE_UNISTD_H
@@ -236,33 +237,43 @@ namespace Action {
}
int Print::run(const std::string& path)
- try {
- path_ = path;
- int rc = 0;
- Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
- switch (Params::instance().printMode_) {
- case Params::pmSummary: rc = printSummary(); break;
- case Params::pmList: rc = printList(); break;
- case Params::pmComment: rc = printComment(); break;
- case Params::pmPreview: rc = printPreviewList(); break;
- case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic) ; break;
- case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive) ; break;
-
- case Params::pmXMP:
- option = option == Exiv2::kpsNone ? Exiv2::kpsXMP : option; // drop
- case Params::pmIccProfile:{
- option = option == Exiv2::kpsNone ? Exiv2::kpsIccProfile : option;
- _setmode(_fileno(stdout),O_BINARY);
- rc = printStructure(std::cout,option);
- } break;
+ {
+ try {
+ path_ = path;
+ int rc = 0;
+ Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
+ switch (Params::instance().printMode_) {
+ case Params::pmSummary: rc = printSummary(); break;
+ case Params::pmList: rc = printList(); break;
+ case Params::pmComment: rc = printComment(); break;
+ case Params::pmPreview: rc = printPreviewList(); break;
+ case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic) ; break;
+ case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive) ; break;
+
+ case Params::pmXMP:
+ if (option == Exiv2::kpsNone)
+ option = Exiv2::kpsXMP;
+ // drop
+ case Params::pmIccProfile:
+ if (option == Exiv2::kpsNone)
+ option = Exiv2::kpsIccProfile;
+ _setmode(_fileno(stdout),O_BINARY);
+ rc = printStructure(std::cout,option);
+ break;
+ }
+ return rc;
}
- return rc;
- }
- catch(const Exiv2::AnyError& e) {
- std::cerr << "Exiv2 exception in print action for file "
- << path << ":\n" << e << "\n";
- return 1;
- } // Print::run
+ catch(const Exiv2::AnyError& e) {
+ std::cerr << "Exiv2 exception in print action for file "
+ << path << ":\n" << e << "\n";
+ return 1;
+ }
+ catch(const std::overflow_error& e) {
+ std::cerr << "std::overflow_error exception in print action for file "
+ << path << ":\n" << e.what() << "\n";
+ return 1;
+ }
+ }
int Print::printStructure(std::ostream& out, Exiv2::PrintStructureOption option)
{
diff --git a/src/error.cpp b/src/error.cpp
index e90a9c0..5d63957 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -109,6 +109,8 @@ namespace {
{ 55, N_("tiff directory length is too large") },
{ 56, N_("invalid type value detected in Image::printIFDStructure") },
{ 57, N_("invalid memory allocation request") },
+ { 58, N_("corrupted image metadata") },
+ { 59, N_("Arithmetic operation overflow") },
};
}
diff --git a/src/nikonmn.cpp b/src/nikonmn.cpp
index 571ab80..34bf601 100644
--- a/src/nikonmn.cpp
+++ b/src/nikonmn.cpp
@@ -299,6 +299,8 @@ namespace Exiv2 {
const Value& value,
const ExifData* exifData)
{
+ if ( ! exifData ) return os << "undefined" ;
+
if ( value.count() >= 9 ) {
ByteOrder bo = getKeyString("Exif.MakerNote.ByteOrder",exifData) == "MM" ? bigEndian : littleEndian;
byte p[4];
diff --git a/src/pentaxmn.cpp b/src/pentaxmn.cpp
index 4fc38be..b22cb43 100644
--- a/src/pentaxmn.cpp
+++ b/src/pentaxmn.cpp
@@ -1167,6 +1167,8 @@ namespace Exiv2 {
std::ostream& PentaxMakerNote::printShutterCount(std::ostream& os, const Value& value, const ExifData* metadata)
{
+ if ( ! metadata ) return os << "undefined" ;
+
ExifData::const_iterator dateIt = metadata->findKey(
ExifKey("Exif.PentaxDng.Date"));
if (dateIt == metadata->end()) {
diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index da4ccd0..4dcca4d 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -68,6 +68,8 @@ namespace Exiv2 {
int* outWidth,
int* outHeight)
{
+ assert(data.size_ >= 8);
+
// Extract image width and height from IHDR chunk.
*outWidth = getLong((const byte*)data.pData_, bigEndian);
diff --git a/src/pngimage.cpp b/src/pngimage.cpp
index 11b4198..ed7399a 100644
--- a/src/pngimage.cpp
+++ b/src/pngimage.cpp
@@ -441,7 +441,9 @@ namespace Exiv2 {
#ifdef DEBUG
std::cout << "Exiv2::PngImage::readMetadata: Found IHDR chunk (length: " << dataOffset << ")\n";
#endif
- PngChunk::decodeIHDRChunk(cdataBuf, &pixelWidth_, &pixelHeight_);
+ if (cdataBuf.size_ >= 8) {
+ PngChunk::decodeIHDRChunk(cdataBuf, &pixelWidth_, &pixelHeight_);
+ }
}
else if (!memcmp(cheaderBuf.pData_ + 4, "tEXt", 4))
{
diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp
index 74f8d07..fad39b6 100644
--- a/src/tiffvisitor.cpp
+++ b/src/tiffvisitor.cpp
@@ -1493,6 +1493,11 @@ namespace Exiv2 {
}
p += 4;
uint32_t isize= 0; // size of Exif.Sony1.PreviewImage
+
+ if (count > std::numeric_limits<uint32_t>::max() / typeSize) {
+ throw Error(59);
+ }
+
uint32_t size = typeSize * count;
uint32_t offset = getLong(p, byteOrder());
byte* pData = p;
@@ -1536,7 +1541,9 @@ namespace Exiv2 {
}
}
Value::AutoPtr v = Value::create(typeId);
- assert(v.get());
+ if (!v.get()) {
+ throw Error(58);
+ }
if ( !isize ) {
v->read(pData, size, byteOrder());
} else {

View File

@ -1,21 +0,0 @@
diff -up exiv2-trunk/config/Doxyfile.doxygen exiv2-trunk/config/Doxyfile
--- exiv2-trunk/config/Doxyfile.doxygen 2017-05-02 09:17:33.631909015 -0500
+++ exiv2-trunk/config/Doxyfile 2017-05-02 09:18:03.019200824 -0500
@@ -1688,7 +1688,7 @@ HIDE_UNDOC_RELATIONS = YES
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)
-HAVE_DOT = YES
+#HAVE_DOT = YES
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
@@ -1705,7 +1705,7 @@ DOT_NUM_THREADS = 0
# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font.
-DOT_FONTNAME = Arial
+#DOT_FONTNAME = Arial
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.

View File

@ -1,84 +0,0 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7034bb6..27e90de 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -217,13 +217,16 @@ ADD_CUSTOM_TARGET(geotag-test COMMAND env EXIV2_BINDIR="${CMAKE_BINARY_DIR}"/bin
# effectively does a make doc on the root directory
# has to run 'make config' and './configure'
# and copy bin/taglist to <exiv2dir>/bin/taglist for use by 'make doc'
-IF( MINGW OR UNIX OR APPLE)
- ADD_CUSTOM_TARGET(doc
- WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/doc"
- COMMAND chmod +x ./cmake_doc.sh
- COMMAND ./cmake_doc.sh "${CMAKE_BINARY_DIR}"
- )
-ENDIF()
+# IF( MINGW OR UNIX OR APPLE)
+# ADD_CUSTOM_TARGET(doc
+# WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/doc"
+# COMMAND chmod +x ./cmake_doc.sh
+# COMMAND ./cmake_doc.sh "${CMAKE_BINARY_DIR}"
+# )
+# ENDIF()
+
+include(config/generateDoc.cmake REQUIRED)
+generate_documentation("${PROJECT_SOURCE_DIR}/config/Doxyfile")
# That's all Folks!
##
diff --git a/config/Doxyfile b/config/Doxyfile
index db62e1d..5d357a7 100644
--- a/config/Doxyfile
+++ b/config/Doxyfile
@@ -52,7 +52,7 @@ PROJECT_LOGO =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY =
+OUTPUT_DIRECTORY = doc
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -1637,7 +1637,7 @@ TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.
-GENERATE_TAGFILE = html/exiv2.xml
+GENERATE_TAGFILE = doc/html/exiv2.xml
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
diff --git a/config/generateDoc.cmake b/config/generateDoc.cmake
new file mode 100644
index 0000000..2b66078
--- /dev/null
+++ b/config/generateDoc.cmake
@@ -0,0 +1,28 @@
+# -helper macro to add a "doc" target with CMake build system.
+# and configure doxy.config.in to doxy.config
+#
+# target "doc" allows building the documentation with doxygen/dot on WIN32, Linux and Mac
+#
+
+find_package(Doxygen REQUIRED)
+
+macro(generate_documentation DOX_CONFIG_FILE)
+ if(NOT EXISTS "${DOX_CONFIG_FILE}")
+ message(FATAL_ERROR "Configuration file for doxygen not found")
+ endif()
+
+ #Define variables
+ set(INCDIR "${PROJECT_SOURCE_DIR}/include/exiv2")
+ set(SRCDIR "${PROJECT_SOURCE_DIR}/src")
+ set(ROOTDIR "${PROJECT_SOURCE_DIR}")
+ #set(TESTSDIR "${PROJECT_SOURCE_DIR}/tests")
+
+ configure_file(${DOX_CONFIG_FILE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config @ONLY) #OUT-OF-PLACE LOCATION
+ set(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
+ add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG})
+
+ install(DIRECTORY "${PROJECT_BINARY_DIR}/doc/html/" DESTINATION "share/doc/html/lib${PROJECT_NAME}")
+
+ set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES doc)
+endmacro()
+

View File

@ -1,43 +0,0 @@
From f9e3c712fe23a9cb661c998fc4fd14e7e5d641f5 Mon Sep 17 00:00:00 2001
From: Luis Diaz Mas <piponazo@gmail.com>
Date: Thu, 17 Aug 2017 22:40:50 +0200
Subject: Simplify compiler info handling in CMake
(cherry picked from commit 69fb40fdc6d5797d10a025b9f5123978dda3bfa4)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f2103c44..e49fb78b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -67,8 +67,8 @@ ENDIF()
# set include path for FindXXX.cmake files
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/config/")
-IF( MINGW OR UNIX )
- IF ( CMAKE_CXX_COMPILER STREQUAL "g++" OR CMAKE_C_COMPILER STREQUAL "gcc" )
+if( MINGW OR UNIX )
+ if (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU)
ADD_DEFINITIONS(-Wall
-Wcast-align
-Wpointer-arith
@@ -79,18 +79,8 @@ IF( MINGW OR UNIX )
)
ENDIF()
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE COMPILER_VERSION)
- string(REGEX MATCHALL "[a-z\+]+" GCC_COMPILER_COMPONENTS ${COMPILER_VERSION})
- list(GET GCC_COMPILER_COMPONENTS 0 COMPILER)
-
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
- string(REGEX MATCHALL "[0-9]+" GCC_VERSION_COMPONENTS ${GCC_VERSION})
- list(GET GCC_VERSION_COMPONENTS 0 GCC_MAJOR)
- list(GET GCC_VERSION_COMPONENTS 1 GCC_MINOR)
-
- message(STATUS Compiler: ${COMPILER} " Major:" ${GCC_MAJOR} " Minor:" ${GCC_MINOR})
-
- IF ( CYGWIN OR ( ${GCC_MAJOR} GREATER 5 ))
+ message(STATUS "Compiler info: ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER}) ; version: ${CMAKE_CXX_COMPILER_VERSION}")
+ IF ( CYGWIN OR (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0))
ADD_DEFINITIONS( -std=gnu++98 ) # to support snprintf
ELSE()
ADD_DEFINITIONS( -std=c++98 )

View File

@ -1,39 +0,0 @@
From 1e07c98dfcbd8ac10ee02088f08235f5e1700148 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20=C4=8Cerm=C3=A1k?= <dan.cermak@cgc-instruments.com>
Date: Wed, 27 Sep 2017 23:38:49 +0200
Subject: Fixed wrong brackets: size*count + pad can overflow before the cast
=> Should fix #76 (most of the work has been done by Robin Mills in
6e3855aed7ba8bb4731fc4087ca7f9078b2f3d97)
The problem with #76 is the contents of the 26th IFD, with the
following contents:
tag: 0x8649
type: 0x1
count: 0xffff ffff
offset: 0x4974
The issue is the size of count (uint32_t), as adding anything to it
causes an overflow. Especially the expression:
(size*count + pad+20)
results in an overflow and gives 20 as a result instead of
0x100000014, thus the condition in the if in the next line is false
and the program continues to run (until it crashes at io.read).
To properly account for the overflow, the brackets have to be removed,
as then the result is saved in the correctly sized type and not cast
after being calculated in the smaller type.
diff --git a/src/image.cpp b/src/image.cpp
index ec5b873e..199671b9 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -401,7 +401,7 @@ namespace Exiv2 {
// if ( offset > io.size() ) offset = 0; // Denial of service?
// #55 memory allocation crash test/data/POC8
- long long allocate = (long long) (size*count + pad+20);
+ long long allocate = (long long) size*count + pad+20;
if ( allocate > (long long) io.size() ) {
throw Error(57);
}

View File

@ -1,48 +1,23 @@
## enable experimental cmake build support (or not)
# still a bit buggy (e.g. out-of-tree and translations broken)
#global cmake_build 1
Summary: Exif and Iptc metadata manipulation library
Name: exiv2
Version: 0.26
Release: 13%{?dist}
Version: 0.27.0
Release: 1%{?dist}
License: GPLv2+
URL: http://www.exiv2.org/
Source0: https://github.com/Exiv2/%{name}/archive/exiv2-%{version}.tar.gz
#Source0: https://github.com/Exiv2/%{name}/archive/exiv2-%{version}.tar.gz
Source0: http://exiv2.org/builds/%{name}-%{version}-Source.tar.gz
Patch0: exiv2-simplify-compiler-info-in-cmake.patch
Patch1: exiv2-fix-documentation-build.patch
## upstream patches (lookaside cache)
Patch6: 0006-1296-Fix-submitted.patch
# Security fixes
Patch10: exiv2-CVE-2017-17723.patch
Patch11: exiv2-wrong-brackets.patch
Patch12: exiv2-CVE-2017-11683.patch
Patch13: exiv2-CVE-2017-14860.patch
Patch14: exiv2-CVE-2017-14864-CVE-2017-14862-CVE-2017-14859.patch
Patch15: exiv2-CVE-2017-17725.patch
Patch16: exiv2-CVE-2017-17669.patch
Patch17: exiv2-additional-security-fixes.patch
Patch18: exiv2-CVE-2018-10958.patch
Patch19: exiv2-CVE-2018-10998.patch
Patch20: exiv2-CVE-2018-11531.patch
Patch21: exiv2-CVE-2018-12264-CVE-2018-12265.patch
Patch22: exiv2-CVE-2018-14046.patch
Patch23: exiv2-CVE-2018-5772.patch
Patch24: exiv2-CVE-2018-8976.patch
Patch25: exiv2-CVE-2018-8977.patch
## upstreamable patches
Patch100: exiv2-doxygen.patch
## upstream backports
# https://bugzilla.redhat.com/show_bug.cgi?id=1585514
# https://github.com/Exiv2/exiv2/issues/201
Patch200: exiv2-0.26-pentax_backport.patch
## upstream patches
Patch22: 0022-cmake-man-pages-only-installed-with-the-exiv2-app.patch
Patch35: 0035-cmake-ignore-warnings-about-missing-PDB-files-in-3rd.patch
Patch64: 0064-cmake-Rename-xmp-to-exiv2-xmp-to-avoid-name-conflict.patch
Patch65: 0065-cmake-Install-header-files-without-globbing.patch
Patch66: 0066-cmake-Use-correct-installation-dir-for-generated-doc.patch
Patch67: 0067-cmake-Use-correct-installation-dir-for-cmake-config-.patch
Patch68: 0068-xmpsdk-Build-with-DBanAllEntityUsage-1.patch
Patch69: 0069-xmpsdk-Fix-compile-warnings-in-ExpatAdapter.cpp.patch
BuildRequires: cmake
BuildRequires: expat-devel
@ -96,23 +71,20 @@ BuildArch: noarch
%prep
%autosetup -n %{name}-%{version} -p1
%autosetup -n %{name}-%{version}-Source -p1
%build
# exiv2: embedded copy of exempi should be compiled with BanAllEntityUsage
# https://bugzilla.redhat.com/show_bug.cgi?id=888769
export CPPFLAGS="-DBanAllEntityUsage=1"
%{cmake} \
-DEXIV2_ENABLE_BUILD_PO:BOOL=ON \
-DEXIV2_ENABLE_BUILD_SAMPLES:BOOL=OFF \
-DEXIV2_ENABLE_LIBXMP:BOOL=ON .
# FIXME: build this because it adds Threads library and it doesn't build without
# it from some reason
%{cmake} . \
-DCMAKE_INSTALL_DOCDIR="%{_pkgdocdir}" \
-DEXIV2_BUILD_DOC:BOOL=ON \
-DEXIV2_BUILD_PO:BOOL=ON \
-DEXIV2_BUILD_SAMPLES:BOOL=OFF
%make_build
%make_build doc
make %{?_smp_mflags}
make doc -k ||:
%install
make install/fast DESTDIR=%{buildroot}
@ -121,8 +93,8 @@ make install/fast DESTDIR=%{buildroot}
## unpackaged files
rm -fv %{buildroot}%{_libdir}/libexiv2.la
rm -fv %{buildroot}%{_libdir}/libxmp.a
rm -fv %{buildroot}%{_libdir}/pkgconfig//exiv2.lsm
#rm -fv %{buildroot}%{_libdir}/pkgconfig/exiv2.lsm
%check
export PKG_CONFIG_PATH=%{buildroot}%{_libdir}/pkgconfig
@ -134,25 +106,32 @@ test -x %{buildroot}%{_libdir}/libexiv2.so
%license COPYING
%doc doc/ChangeLog
# README is mostly installation instructions
#doc README
#doc README.md
%{_bindir}/exiv2
%{_mandir}/man1/exiv2*.1*
%ldconfig_scriptlets libs
%files libs
%{_libdir}/libexiv2.so.26*
%{_libdir}/libexiv2.so.27*
%{_libdir}/libexiv2.so.%{version}
%files devel
%{_includedir}/exiv2/
%{_libdir}/libexiv2.so
%{_libdir}/pkgconfig/exiv2.pc
%{_libdir}/cmake/exiv2/
# todo: -static subpkg? -- rex
%{_libdir}/libexiv2-xmp.a
%files doc
%{_datadir}/doc/html/
%{_pkgdocdir}/
%changelog
* Thu Jan 10 2019 Rex Dieter <rdieter@fedoraproject.org> - 0.27.0-1
- exiv2-0.27.0 (#1665246)
* Thu Jan 10 2019 Rex Dieter <rdieter@fedoraproject.org> - 0.26-13
- backport pentax DNG crasher (#1585514, exiv2#201)

View File

@ -1 +1 @@
SHA512 (exiv2-0.26.tar.gz) = 559455d792d7ad9bf7fbeed6268b90c5fe72e3f094770599e20983a6113039f3c12f31849e15752a4bd68610e129f5dab98e29888c0e2141613ea34582beffd7
SHA512 (exiv2-0.27.0-Source.tar.gz) = 3037d8e84b414e3915b807c5bea39f903668c0774f9dbc1367e23c595d5abaf318c746009e994234bcaf0088ad32a820ea42c9c77c9a53c65a7b5d7781a2c6d4