Fix issues detected with PVS-Studio + other little improvements (#1689)

* avoid re-declaration of constant variables

* Replace pthreads critical section with std::mutex

* ci - better naming

* cmake - increase minimum version to 3.11. Use project DESCRIPTION

* fix - do not treat string::find() return type as bool

* remove conditions that were always true

* remove condition that were always false

* Remove EXV_HAVE_GMTIME_R which is not used anymore

* pixelWidth_ was inherited from Exiv2::Image

The width & height variables in the TiffImage class need to be mutable
to be able to change their values on the getters pixelHeight() and
pixelWidth() ... Do not ask me why ...

* Remove superfluous if

* pvs:V766 item with identical key added already

* pvs:V730 not all members were initialized (time)

* pvs:V730 not all members are initialized

* pvs:v668 no point in testing pointer against null after new

* pvs:V1048 variable assigned the same value

* replace c-style dynamic vector with std one

* pvs:547 fakeData is always true

* Remove useless constructor in derived class

* pvs:V690 modern way to disable copy-ctor

* Replace malloc/free with new/delete. No need to check for null

* pvs:V1028 cast operands and not result

* Remove custom MIN/MAX functions

* pvs:V595 pointer used before verified against null

* pvs: index used before being checked

* pvs:V1028 possible overflow. Cast operands

* pvs:v575 potential null pointer passed to other functions

* pvs:V547 deal with always true/false expressions

* pvs:V560 part of conditional expressions always false or true

* pvs:V701 possible break in realloc -> move to std::vector

* Make some classes 'final'

* Replace sprintf with std::to_string()

* fix compilation on windows
This commit is contained in:
Luis Díaz Más 2021-06-01 12:39:10 +02:00 committed by GitHub
parent 024830a72c
commit f30022d73d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 118 additions and 201 deletions

View File

@ -49,7 +49,7 @@ jobs:
cmake --build .
- name: Unit Test
- name: Test
run: |
cd build
ctest --output-on-failure
@ -80,7 +80,7 @@ jobs:
cmake -GNinja -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_BMFF=ON -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON ..
cmake --build .
- name: Unit Test
- name: Test
run: |
cd build
ctest --output-on-failure
@ -112,7 +112,7 @@ jobs:
cmake -GNinja -DEXIV2_ENABLE_WEBREADY=ON -DEXIV2_ENABLE_CURL=ON -DEXIV2_BUILD_UNIT_TESTS=ON -DEXIV2_ENABLE_BMFF=ON -DEXIV2_TEAM_WARNINGS_AS_ERRORS=ON -DCMAKE_INSTALL_PREFIX=install -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" ..
cmake --build .
- name: Unit Test
- name: Test
run: |
cd build
ctest --output-on-failure

View File

@ -1,4 +1,5 @@
cmake_minimum_required( VERSION 3.5.0 )
# Minimum version imposed by Centos:8
cmake_minimum_required( VERSION 3.11.0 )
project(exiv2 # use TWEAK to categorize the build
VERSION 1.00.0.9 # 1.00.0 = GM (tagged and released)
@ -7,6 +8,7 @@ project(exiv2 # use TWEAK to categorize the build
# 1.00.0.2 = RC2 (tagged and released)
# 1.00.0.20 = RC2 Preview
# 1.00.0.29 = RC2 Development
DESCRIPTION "Exif/IPTC/Xmp C++ metadata library and tools plus ICC Profiles, Previews and more."
LANGUAGES CXX
)
@ -54,9 +56,7 @@ option( BUILD_WITH_CCACHE "Use ccache to speed up compilations"
option( BUILD_WITH_COVERAGE "Add compiler flags to generate coverage stats" OFF )
include(cmake/gcovr.cmake REQUIRED)
set( PACKAGE_BUGREPORT "http://github.com/exiv2/exiv2" )
set( PACKAGE_URL "https://exiv2.org")
set( PROJECT_DESCRIPTION "Exif/IPTC/Xmp C++ metadata library and tools plus ICC Profiles, Previews and more.")
if ( EXIV2_ENABLE_EXTERNAL_XMP )
set(EXIV2_ENABLE_XMP OFF)

View File

@ -18,9 +18,6 @@ if (APPLE)
set(CMAKE_FIND_FRAMEWORK NEVER)
endif()
find_package(Threads REQUIRED)
if( EXIV2_ENABLE_PNG )
find_package( ZLIB REQUIRED )
endif( )

View File

@ -23,7 +23,6 @@ set(EXV_HAVE_ICONV ${ICONV_FOUND})
set(EXV_HAVE_LIBZ ${ZLIB_FOUND})
set(EXV_UNICODE_PATH ${EXIV2_ENABLE_WIN_UNICODE})
check_cxx_symbol_exists(gmtime_r time.h EXV_HAVE_GMTIME_R)
check_cxx_symbol_exists(mmap sys/mman.h EXV_HAVE_MMAP )
check_cxx_symbol_exists(munmap sys/mman.h EXV_HAVE_MUNMAP )
check_cxx_symbol_exists(strerror_r string.h EXV_HAVE_STRERROR_R )

View File

@ -12,9 +12,6 @@
// Define if you require PNG support.
#define EXIV2_ENABLE_PNG
// Define if you have the `gmtime_r' function.
/* #undef EXV_HAVE_GMTIME_R */
// Define if you have the <libintl.h> header file.
/* #undef EXV_HAVE_LIBINTL_H */

View File

@ -997,16 +997,11 @@ namespace Exiv2 {
//@}
protected:
//! @name Creators
//@{
//! Default Constructor
RemoteIo() {p_=NULL;}
//@}
// Pimpl idiom
class Impl;
//! Pointer to implementation
Impl* p_;
Impl* p_ {nullptr};
}; // class RemoteIo
/*!
@ -1043,12 +1038,6 @@ namespace Exiv2 {
HttpIo& operator=(const HttpIo& rhs);
// Pimpl idiom
class HttpImpl;
//! @name Creators
//@{
//! Default Destructor
virtual ~HttpIo(){}
//@}
};
#ifdef EXV_USE_CURL
@ -1098,12 +1087,6 @@ namespace Exiv2 {
CurlIo& operator=(const CurlIo& rhs);
// Pimpl idiom
class CurlImpl;
//! @name Creators
//@{
//! Default Destructor
virtual ~CurlIo(){}
//@}
};
#endif

View File

@ -120,7 +120,7 @@ namespace Exiv2
int pixelHeight() const;
//@}
Exiv2::ByteOrder endian_ ;
Exiv2::ByteOrder endian_{Exiv2::bigEndian};
private:
void openOrThrow();
@ -136,14 +136,14 @@ namespace Exiv2
return std::string(2*i,' ');
}
uint32_t fileType_;
uint32_t fileType_{0};
std::set<uint64_t> visits_;
uint64_t visits_max_;
uint16_t unknownID_; // 0xffff
uint16_t exifID_;
uint16_t xmpID_;
uint64_t visits_max_{0};
uint16_t unknownID_{0xffff};
uint16_t exifID_{0xffff};
uint16_t xmpID_{0};
std::map<uint32_t, Iloc> ilocs_;
bool bReadMetadata_;
bool bReadMetadata_{false};
//@}
/*!

View File

@ -117,8 +117,8 @@ namespace Exiv2 {
// DATA
mutable std::string primaryGroup_; //!< The primary group
mutable std::string mimeType_; //!< The MIME type
mutable int pixelWidth_; //!< Width of the primary image in pixels
mutable int pixelHeight_; //!< Height of the primary image in pixels
mutable int pixelWidthPrimary_; //!< Width of the primary image in pixels
mutable int pixelHeightPrimary_; //!< Height of the primary image in pixels
}; // class TiffImage

View File

@ -65,12 +65,6 @@
*/
#define EXV_CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
// Simple min and max macros
//! Simple common min macro
#define EXV_MIN(a,b) ((a) < (b) ? (a) : (b))
//! Simple common max macro
#define EXV_MAX(a,b) ((a) > (b) ? (a) : (b))
#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__clang__)
#define EXV_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)

View File

@ -289,36 +289,26 @@ time_t Position::deltaMax_ = 60 ;
///////////////////////////////////////////////////////////
// UserData - used by XML Parser
class UserData
struct UserData final
{
public:
explicit UserData(Options& options):
indent(0)
, count(0)
, nTrkpt(0)
, bTime(false)
, bEle(false)
, ele(0.0)
, lat(0.0)
, lon(0.0)
, options_(options)
explicit UserData(Options& options)
: options_(options)
{}
virtual ~UserData() = default;
// public data members
int indent;
size_t count ;
int indent{0};
size_t count{0};
Position now ;
Position prev;
int nTrkpt;
bool bTime ;
bool bEle ;
double ele;
double lat;
double lon;
int nTrkpt{0};
bool bTime{false};
bool bEle{false};
double ele{0.};
double lat{0.};
double lon{0.};
std::string xmlt;
std::string exift;
time_t time;
time_t time{0};
Options& options_;
// static public data memembers
};
@ -669,8 +659,8 @@ int readFile(const char* path, const Options& /* options */)
if ( sina(ext,code) )
nResult = typeCode;
}
fclose(f);
}
if ( f ) fclose(f) ;
return nResult ;
}
@ -809,7 +799,7 @@ int main(int argc,const char* argv[])
shorts["-D"] = "-delta";
shorts["-s"] = "-delta";
shorts["-X"] = "-dryrun";
shorts["-a"] = "-ascii";
shorts["-A"] = "-ascii";
Options options ;
options.help = sina(keywords[kwHELP ],argv) || argc < 2;

View File

@ -215,7 +215,6 @@ if (NOT MSVC)
target_link_libraries( exiv2lib PRIVATE psapi ws2_32 shell32 )
endif()
target_link_libraries( exiv2lib PRIVATE Threads::Threads)
else()
target_link_libraries( exiv2lib PRIVATE psapi ws2_32 shell32 )
endif()

View File

@ -50,6 +50,7 @@
#include <ctime>
#include <cmath>
#include <cassert>
#include <mutex>
#include <stdexcept>
#include <sys/types.h> // for stat()
#include <sys/stat.h> // for stat()
@ -71,6 +72,7 @@
// *****************************************************************************
// local declarations
namespace {
std::mutex cs;
//! Helper class to set the timestamp of a file to that of another file
class Timestamp {
@ -253,7 +255,6 @@ namespace Action {
try {
path_ = path;
int rc = 0;
Exiv2::PrintStructureOption option = Exiv2::kpsNone ;
switch (Params::instance().printMode_) {
case Params::pmSummary: rc = Params::instance().greps_.empty() ? printSummary() : printList(); break;
case Params::pmList: rc = printList(); break;
@ -262,14 +263,10 @@ namespace Action {
case Params::pmStructure: rc = printStructure(std::cout,Exiv2::kpsBasic, path_) ; break;
case Params::pmRecursive: rc = printStructure(std::cout,Exiv2::kpsRecursive, path_) ; break;
case Params::pmXMP:
if (option == Exiv2::kpsNone)
option = Exiv2::kpsXMP;
rc = setModeAndPrintStructure(option, path_,binary());
rc = setModeAndPrintStructure(Exiv2::kpsXMP, path_,binary());
break;
case Params::pmIccProfile:
if (option == Exiv2::kpsNone)
option = Exiv2::kpsIccProfile;
rc = setModeAndPrintStructure(option, path_,binary());
rc = setModeAndPrintStructure(Exiv2::kpsIccProfile, path_,binary());
break;
}
return rc;
@ -540,8 +537,6 @@ namespace Action {
bool first = true;
if (Params::instance().printItems_ & Params::prTag) {
if (!first)
std::cout << " ";
first = false;
std::cout << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << md.tag();
}
@ -1854,34 +1849,12 @@ namespace {
return os.str();
} // tm2Str
// use static CS/MUTEX to make temporaryPath() thread safe
#if defined(_MSC_VER) || defined(__MINGW__)
static CRITICAL_SECTION cs;
#else
/* Unix/Linux/Cygwin/macOS */
#include <pthread.h>
/* This is the critical section object (statically allocated). */
#if defined(__APPLE__)
#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
static pthread_mutex_t cs = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
#else
static pthread_mutex_t cs = PTHREAD_MUTEX_INITIALIZER;
#endif
#else
#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
pthread_mutex_t cs = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
#else
pthread_mutex_t cs = PTHREAD_MUTEX_INITIALIZER;
#endif
#endif
#endif
std::string temporaryPath()
{
static int count = 0;
std::lock_guard<std::mutex> guard(cs);
#if defined(_MSC_VER) || defined(__MINGW__)
EnterCriticalSection(&cs);
char lpTempPathBuffer[MAX_PATH];
GetTempPath(MAX_PATH,lpTempPathBuffer);
std::string tmp(lpTempPathBuffer);
@ -1890,22 +1863,14 @@ namespace {
DWORD pid = ::GetProcessId(process);
#else
pid_t pid = ::getpid();
pthread_mutex_lock( &cs );
std::string tmp = "/tmp/";
#endif
char sCount[13];
sprintf(sCount,"_%d",++count); /// \todo replace by std::snprintf on master
std::string result = tmp + Exiv2::toString(pid) + "_" + std::to_string(count);
if (Exiv2::fileExists(result)) {
std::remove(result.c_str());
}
std::string result = tmp + Exiv2::toString(pid) + sCount ;
if ( Exiv2::fileExists(result) ) std::remove(result.c_str());
#if defined(_MSC_VER) || defined(__MINGW__)
LeaveCriticalSection(&cs);
#else
pthread_mutex_unlock( &cs );
#endif
return result;
return result;
}
int metacopy(const std::string& source,

View File

@ -112,6 +112,10 @@ namespace Action {
this method.
*/
static TaskFactory& instance();
//! Prevent copy construction: not implemented.
TaskFactory(const TaskFactory& rhs) = delete;
//! Destructor
void cleanup();
@ -144,8 +148,6 @@ namespace Action {
private:
//! Prevent construction other than through instance().
TaskFactory();
//! Prevent copy construction: not implemented.
TaskFactory(const TaskFactory& rhs);
//! Pointer to the one and only instance of this class.
static TaskFactory* instance_;

View File

@ -1047,7 +1047,7 @@ namespace Exiv2 {
}
//! Internal Pimpl structure of class MemIo.
class MemIo::Impl {
class MemIo::Impl final{
public:
Impl() = default; //!< Default constructor
Impl(const byte* data, long size); //!< Constructor 2
@ -1088,10 +1088,7 @@ namespace Exiv2 {
//! Destructor. Releases all managed memory.
~BlockMap()
{
if (data_) {
std::free(data_);
data_ = nullptr;
}
delete [] data_;
}
//! @brief Populate the block.
@ -1099,8 +1096,9 @@ namespace Exiv2 {
//! @param num The size of data
void populate (byte* source, size_t num)
{
assert(source != nullptr);
size_ = num;
data_ = static_cast<byte*>(std::malloc(size_));
data_ = new byte [size_];
type_ = bMemory;
std::memcpy(data_, source, size_);
}
@ -1152,7 +1150,7 @@ namespace Exiv2 {
if (!isMalloced_) {
// Minimum size for 1st block
long size = EXV_MAX(blockSize * (1 + need / blockSize), size_);
long size = std::max(blockSize * (1 + need / blockSize), size_);
auto data = static_cast<byte*>(std::malloc(size));
if (data == nullptr) {
throw Error(kerMallocFailed);
@ -1176,7 +1174,6 @@ namespace Exiv2 {
throw Error(kerMallocFailed);
}
sizeAlloced_ = want;
isMalloced_ = true;
}
size_ = need;
}
@ -1358,8 +1355,8 @@ namespace Exiv2 {
long MemIo::read(byte* buf, long rcount)
{
long avail = EXV_MAX(p_->size_ - p_->idx_, 0);
long allow = EXV_MIN(rcount, avail);
long avail = std::max(p_->size_ - p_->idx_, 0L);
long allow = std::min(rcount, avail);
std::memcpy(buf, &p_->data_[p_->idx_], allow);
p_->idx_ += allow;
if (rcount > avail) p_->eof_ = true;
@ -1533,16 +1530,15 @@ namespace Exiv2 {
}
std::string data = orgPath.substr(base64Pos+7);
auto decodeData = new char[data.length()];
long size = base64decode(data.c_str(), decodeData, data.length());
std::vector<char> decodeData (data.length());
long size = base64decode(data.c_str(), decodeData.data(), data.length());
if (size > 0) {
fs.write(decodeData, size);
fs.write(decodeData.data(), size);
fs.close();
} else {
fs.close();
throw Error(kerErrorMessage, "Unable to decode base 64.");
}
delete[] decodeData;
}
return path;
@ -1665,7 +1661,7 @@ namespace Exiv2 {
size_t iBlock = (rcount == size_) ? 0 : lowBlock;
while (remain) {
size_t allow = EXV_MIN(remain, blockSize_);
size_t allow = std::min(remain, blockSize_);
blocksMap_[iBlock].populate(&source[totalRead], allow);
remain -= allow;
totalRead += allow;
@ -1704,7 +1700,7 @@ namespace Exiv2 {
auto source = reinterpret_cast<byte*>(const_cast<char*>(data.c_str()));
size_t remain = p_->size_, iBlock = 0, totalRead = 0;
while (remain) {
size_t allow = EXV_MIN(remain, p_->blockSize_);
size_t allow = std::min(remain, p_->blockSize_);
p_->blocksMap_[iBlock].populate(&source[totalRead], allow);
remain -= allow;
totalRead += allow;
@ -1761,7 +1757,7 @@ namespace Exiv2 {
size_t i = 0;
size_t readCount = 0;
size_t blockSize = 0;
auto buf = static_cast<byte*>(std::malloc(p_->blockSize_));
auto buf = new byte [p_->blockSize_];
size_t nBlocks = (p_->size_ + p_->blockSize_ - 1) / p_->blockSize_;
// find $left
@ -1805,8 +1801,7 @@ namespace Exiv2 {
blockSize = static_cast<long>(p_->blocksMap_[blockIndex].getSize());
}
// free buf
if (buf) std::free(buf);
delete []buf;
// submit to the remote machine.
long dataSize = static_cast<long>(src.size() - left - right);
@ -1840,7 +1835,7 @@ namespace Exiv2 {
if (p_->eof_) return 0;
p_->totalRead_ += rcount;
size_t allow = EXV_MIN(rcount, (long)( p_->size_ - p_->idx_));
size_t allow = std::min(rcount, (long)( p_->size_ - p_->idx_));
size_t lowBlock = p_->idx_ /p_->blockSize_;
size_t highBlock = (p_->idx_ + allow)/p_->blockSize_;
@ -1858,14 +1853,14 @@ namespace Exiv2 {
byte* data = p_->blocksMap_[iBlock++].getData();
if (data == nullptr)
data = fakeData;
size_t blockR = EXV_MIN(allow, p_->blockSize_ - startPos);
size_t blockR = std::min(allow, p_->blockSize_ - startPos);
std::memcpy(&buf[totalRead], &data[startPos], blockR);
totalRead += blockR;
startPos = 0;
allow -= blockR;
} while(allow);
if (fakeData) std::free(fakeData);
std::free(fakeData);
p_->idx_ += static_cast<long>(totalRead);
p_->eof_ = (p_->idx_ == static_cast<long>(p_->size_));

View File

@ -101,12 +101,8 @@ namespace Exiv2
}
BmffImage::BmffImage(BasicIo::UniquePtr io, bool /* create */)
: Image(ImageType::bmff, mdExif | mdIptc | mdXmp, std::move(io)),
endian_(Exiv2::bigEndian),
bReadMetadata_(false)
: Image(ImageType::bmff, mdExif | mdIptc | mdXmp, std::move(io))
{
pixelWidth_ = 0;
pixelHeight_ = 0;
} // BmffImage::BmffImage
std::string BmffImage::toAscii(long n)
@ -292,10 +288,11 @@ namespace Exiv2
const auto maxlen = static_cast<size_t>(data.size_ - skip);
enforce(strnlen(str, maxlen) < maxlen, Exiv2::kerCorruptedMetadata);
std::string name(str);
if ( !name.find("Exif") ) { // "Exif" or "ExifExif"
if (name.find("Exif") != std::string::npos) { // "Exif" or "ExifExif"
exifID_ = ID;
id=" *** Exif ***";
} else if ( !name.find("mime\0xmp") || !name.find("mime\0application/rdf+xml") ) {
} else if (name.find("mime\0xmp") != std::string::npos ||
name.find("mime\0application/rdf+xml") != std::string::npos) {
xmpID_ = ID;
id=" *** XMP ***";
}

View File

@ -1088,7 +1088,7 @@ namespace Exiv2 {
}
if ( in.bad() || !(ref == 'N' || ref == 'S' || ref == 'E' || ref == 'W')
|| sep1 != ',' || sep2 != ',' || !in.eof()) {
|| sep1 != ',' || !in.eof()) {
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
#endif

View File

@ -645,12 +645,14 @@ namespace Exiv2 {
UNUSED(rootDirectory);
assert(rootDirectory == 0x0000);
crwDirs.pop();
if (!pRootDir_) pRootDir_ = new CiffDirectory;
if ( pRootDir_) {
CiffComponent* child = pRootDir_->add(crwDirs, crwTagId);
if ( child ) child->setValue(buf);
if (!pRootDir_) {
pRootDir_ = new CiffDirectory;
}
} // CiffHeader::add
CiffComponent* child = pRootDir_->add(crwDirs, crwTagId);
if (child) {
child->setValue(buf);
}
} // CiffHeader::add
CiffComponent* CiffComponent::add(CrwDirs& crwDirs, uint16_t crwTagId)
{

View File

@ -956,26 +956,24 @@ int Params::nonoption(const std::string& argv)
static int readFileToBuf(FILE* f,Exiv2::DataBuf& buf)
{
const int buff_size = 4*1028;
auto bytes = static_cast<Exiv2::byte*>(::malloc(buff_size));
std::vector<Exiv2::byte> bytes(buff_size);
int nBytes = 0 ;
bool more = bytes != nullptr;
bool more {true};
while ( more ) {
char buff[buff_size];
int n = static_cast<int>(fread(buff, 1, buff_size, f));
more = n > 0 ;
if ( more ) {
bytes = static_cast<Exiv2::byte*>(realloc(bytes, nBytes + n));
memcpy(bytes+nBytes,buff,n);
bytes.resize(nBytes+n);
memcpy(bytes.data()+nBytes,buff,n);
nBytes += n ;
}
}
if ( nBytes ) {
buf.alloc(nBytes);
memcpy(buf.pData_, bytes, nBytes);
memcpy(buf.pData_, bytes.data(), nBytes);
}
if (bytes != nullptr)
::free(bytes);
return nBytes;
}
@ -1386,15 +1384,14 @@ namespace {
// Skip empty lines and comments
std::string::size_type cmdStart = line.find_first_not_of(delim);
if (cmdStart == std::string::npos || line[cmdStart] == '#') return false;
if (cmdStart == std::string::npos || line[cmdStart] == '#')
return false;
// Get command and key
std::string::size_type cmdEnd = line.find_first_of(delim, cmdStart+1);
std::string::size_type keyStart = line.find_first_not_of(delim, cmdEnd+1);
std::string::size_type keyEnd = line.find_first_of(delim, keyStart+1);
if ( cmdStart == std::string::npos
|| cmdEnd == std::string::npos
|| keyStart == std::string::npos) {
if (cmdEnd == std::string::npos || keyStart == std::string::npos) {
std::string cmdLine ;
#if defined(_MSC_VER) || defined(__MINGW__)
for ( int i = 1 ; i < __argc ; i++ ) { cmdLine += std::string(" ") + formatArg(__argv[i]) ; }

View File

@ -158,6 +158,10 @@ public:
@return Reference to the global Params instance.
*/
static Params& instance();
//! Prevent copy-construction: not implemented.
Params(const Params& rhs) = delete;
//! Destructor
static void cleanup();
@ -293,9 +297,6 @@ private:
yodAdjust_[yodDay] = emptyYodAdjust_[yodDay];
}
//! Prevent copy-construction: not implemented.
Params(const Params& rhs);
//! Destructor, frees any allocated regexes in greps_
~Params();

View File

@ -163,7 +163,7 @@ namespace Exiv2 {
const auto data = static_cast<const unsigned char*>(data_buf);
for (size_t i = 0, j = 0 ; i < dataLength;) {
uint32_t octet_a = i < dataLength ? data[i++] : 0 ;
uint32_t octet_a = data[i++];
uint32_t octet_b = i < dataLength ? data[i++] : 0 ;
uint32_t octet_c = i < dataLength ? data[i++] : 0 ;

View File

@ -335,12 +335,11 @@ namespace Exiv2 {
}
uint16_t dirLength = byteSwap2(dir,0,bSwap);
bool tooBig = dirLength > 500;
if ( tooBig ) throw Error(kerTiffDirectoryTooLarge);
if ( dirLength > 500 ) // tooBig
throw Error(kerTiffDirectoryTooLarge);
if ( bFirst && bPrint ) {
out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ",c,c) << io.path() << std::endl;
if ( tooBig ) out << Internal::indent(depth) << "dirLength = " << dirLength << std::endl;
}
// Read the dictionary
@ -498,7 +497,7 @@ namespace Exiv2 {
}
if ( start ) {
io.read(dir.pData_, 4);
start = tooBig ? 0 : byteSwap4(dir,0,bSwap);
start = byteSwap4(dir,0,bSwap);
}
} while (start) ;

View File

@ -332,8 +332,6 @@ namespace Exiv2 {
// Markers can start with any number of 0xff
while ((c=io_->getb()) == 0xff) {
if (c == EOF)
return -2;
}
return c;
}

View File

@ -57,6 +57,8 @@ const unsigned char pngBlank[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,
namespace
{
const auto nullComp = (const Exiv2::byte*)"\0\0";
const auto typeICCP = (const Exiv2::byte*)"iCCP";
inline bool compare(const char* str, const Exiv2::DataBuf& buf, size_t length)
{
assert(strlen(str) <= length);
@ -345,7 +347,7 @@ namespace Exiv2 {
// format is content dependent
if ( bGood ) {
if ( bXMP ) {
while ( !data[start] && start < dataOffset) start++; // skip leading nul bytes
while (start < dataOffset && !data[start]) start++; // skip leading nul bytes
out << data+start; // output the xmp
}
@ -573,7 +575,7 @@ namespace Exiv2 {
memcpy(chunkBuf.pData_, cheaderBuf.pData_, 8); // Copy header.
bufRead = io_->read(chunkBuf.pData_ + 8, dataOffset + 4); // Extract chunk data + CRC
if (io_->error()) throw Error(kerFailedToReadImageData);
if (bufRead != static_cast<long>(dataOffset + 4))
if (bufRead != static_cast<long>(dataOffset) + 4L)
throw Error(kerInputDataReadFailed);
char szChunk[5];
@ -645,8 +647,6 @@ namespace Exiv2 {
if ( iccProfileDefined() ) {
DataBuf compressed;
if ( zlibToCompressed(iccProfile_.pData_,iccProfile_.size_,compressed) ) {
const auto nullComp = reinterpret_cast<const byte*>("\0\0");
const auto type = reinterpret_cast<const byte*>("iCCP");
const auto nameLength = static_cast<uint32_t>(profileName_.size());
const uint32_t chunkLength = nameLength + 2 + compressed.size_ ;
byte length[4];
@ -654,15 +654,15 @@ namespace Exiv2 {
// calculate CRC
uLong tmp = crc32(0L, Z_NULL, 0);
tmp = crc32(tmp, type, 4);
tmp = crc32(tmp, reinterpret_cast<const Bytef*>(profileName_.data()), nameLength);
tmp = crc32(tmp, typeICCP, 4);
tmp = crc32(tmp, (const Bytef*)profileName_.data(), nameLength);
tmp = crc32(tmp, nullComp, 2);
tmp = crc32(tmp, compressed.pData_, compressed.size_);
byte crc[4];
ul2Data(crc, tmp, bigEndian);
if( outIo.write(length, 4) != 4
|| outIo.write(type, 4) != 4
|| outIo.write(typeICCP, 4) != 4
|| outIo.write(reinterpret_cast<const byte*>(profileName_.data()), nameLength) != nameLength
|| outIo.write(nullComp,2) != 2
|| outIo.write (compressed.pData_,compressed.size_) != compressed.size_

View File

@ -1008,7 +1008,7 @@ namespace {
DataBuf makePnm(uint32_t width, uint32_t height, const DataBuf &rgb)
{
const long expectedSize = static_cast<long>(width * height * 3);
const long expectedSize = static_cast<long>(width) * static_cast<long>(height) * 3L;
if (rgb.size_ != expectedSize) {
#ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Invalid size of preview data. Expected " << expectedSize << " bytes, got " << rgb.size_ << " bytes.\n";

View File

@ -2512,8 +2512,8 @@ namespace Exiv2 {
{
const TagInfo* ti = tagList(ifdId);
if (ti == nullptr) return nullptr;
if (tagName.empty()) return nullptr;
const char* tn = tagName.c_str();
if (tn == nullptr) return nullptr;
for (int idx = 0; ti[idx].tag_ != 0xffff; ++idx) {
if (0 == strcmp(ti[idx].name_, tn)) {
return &ti[idx];

View File

@ -583,7 +583,7 @@ namespace Exiv2 {
uint32_t TiffBinaryArray::addElement(uint32_t idx, const ArrayDef& def)
{
auto tag = static_cast<uint16_t>(idx / cfg()->tagStep());
int32_t sz = EXV_MIN(def.size(tag, cfg()->group_), TiffEntryBase::doSize() - idx);
int32_t sz = std::min(def.size(tag, cfg()->group_), TiffEntryBase::doSize() - idx);
TiffComponent::UniquePtr tc = TiffCreator::create(tag, cfg()->group_);
auto tp = dynamic_cast<TiffBinaryElement*>(tc.get());
// The assertion typically fails if a component is not configured in
@ -1698,7 +1698,7 @@ namespace Exiv2 {
if (cfg()->hasFillers_ && def()) {
const ArrayDef* lastDef = def() + defSize() - 1;
auto lastTag = static_cast<uint16_t>(lastDef->idx_ / cfg()->tagStep());
idx = EXV_MAX(idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
idx = std::max(idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
}
return idx;

View File

@ -68,10 +68,11 @@ namespace Exiv2 {
using namespace Internal;
TiffImage::TiffImage(BasicIo::UniquePtr io, bool /*create*/)
: Image(ImageType::tiff, mdExif | mdIptc | mdXmp, std::move(io)),
pixelWidth_(0), pixelHeight_(0)
: Image(ImageType::tiff, mdExif | mdIptc | mdXmp, std::move(io))
, pixelWidthPrimary_(0)
, pixelHeightPrimary_(0)
{
} // TiffImage::TiffImage
} // TiffImage::TiffImage
//! Structure for TIFF compression to MIME type mappings
struct MimeTypeList {
@ -135,26 +136,30 @@ namespace Exiv2 {
int TiffImage::pixelWidth() const
{
if (pixelWidth_ != 0) return pixelWidth_;
if (pixelWidthPrimary_ != 0) {
return pixelWidthPrimary_;
}
ExifKey key(std::string("Exif.") + primaryGroup() + std::string(".ImageWidth"));
auto imageWidth = exifData_.findKey(key);
if (imageWidth != exifData_.end() && imageWidth->count() > 0) {
pixelWidth_ = static_cast<int>(imageWidth->toLong());
pixelWidthPrimary_ = static_cast<int>(imageWidth->toLong());
}
return pixelWidth_;
return pixelWidthPrimary_;
}
int TiffImage::pixelHeight() const
{
if (pixelHeight_ != 0) return pixelHeight_;
if (pixelHeightPrimary_ != 0) {
return pixelHeightPrimary_;
}
ExifKey key(std::string("Exif.") + primaryGroup() + std::string(".ImageLength"));
auto imageHeight = exifData_.findKey(key);
if (imageHeight != exifData_.end() && imageHeight->count() > 0) {
pixelHeight_ = imageHeight->toLong();
pixelHeightPrimary_ = imageHeight->toLong();
}
return pixelHeight_;
return pixelHeightPrimary_;
}
void TiffImage::setComment(const std::string& /*comment*/)

View File

@ -1597,10 +1597,8 @@ namespace Exiv2 {
// #1143 Write a "hollow" buffer for the preview image
// Sadly: we don't know the exact location of the image in the source (it's near offset)
// And neither TiffReader nor TiffEntryBase have access to the BasicIo object being processed
auto buffer = static_cast<byte*>(::malloc(isize));
::memset(buffer,0,isize);
v->read(buffer,isize, byteOrder());
::free(buffer);
std::vector<byte> buffer(isize);
v->read(buffer.data() ,isize, byteOrder());
}
object->setValue(std::move(v));

View File

@ -639,7 +639,6 @@ namespace Exiv2 {
byte exifShortHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
byte exifTiffLEHeader[] = { 0x49, 0x49, 0x2A }; // "MM*"
byte exifTiffBEHeader[] = { 0x4D, 0x4D, 0x00, 0x2A }; // "II\0*"
byte* rawExifData = nullptr;
long offset = 0;
bool s_header = false;
bool le_header = false;
@ -673,7 +672,7 @@ namespace Exiv2 {
}
const long sizePayload = payload.size_ + offset;
rawExifData = static_cast<byte*>(malloc(sizePayload));
byte* rawExifData = new byte[sizePayload];
if (s_header) {
us2Data(size_buff2, static_cast<uint16_t>(sizePayload - 6), bigEndian);
@ -710,7 +709,7 @@ namespace Exiv2 {
exifData_.clear();
}
if (rawExifData) free(rawExifData);
delete [] rawExifData;
} else if (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP)) {
readOrThrow(*io_, payload.pData_, payload.size_, Exiv2::kerCorruptedMetadata);
xmpPacket_.assign(reinterpret_cast<char*>(payload.pData_), payload.size_);