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:
parent
024830a72c
commit
f30022d73d
6
.github/workflows/on_push_BasicWinLinMac.yml
vendored
6
.github/workflows/on_push_BasicWinLinMac.yml
vendored
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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( )
|
||||
|
||||
@ -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 )
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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};
|
||||
//@}
|
||||
|
||||
/*!
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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_));
|
||||
|
||||
@ -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 ***";
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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]) ; }
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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 ;
|
||||
|
||||
|
||||
@ -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) ;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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_
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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*/)
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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_);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user