* fix: use vector::at() rather than operator[] (#1735) * Regression test for https://github.com/Exiv2/exiv2/issues/1706 * Use vector::at() rather than operator[]. * Print to stderr when exception is caught and EXIV2_DEBUG_MESSAGES is enabled. * Check that it prints "Bad value" for the date. (cherry picked from commit f4d3adbf91e6dc4e34aee5bac7b7fd9e127a5c00) # Conflicts: # src/value.cpp * fix merge conflicts from mergify backport Co-authored-by: Kevin Backhouse <kevinbackhouse@github.com> Co-authored-by: Christoph Hasse <hassec@users.noreply.github.com>
This commit is contained in:
parent
2b84f4bd64
commit
1d64f482ff
@ -1616,7 +1616,7 @@ namespace Exiv2 {
|
||||
std::string ValueType<T>::toString(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return Exiv2::toString<T>(value_[n]);
|
||||
return Exiv2::toString<T>(value_.at(n));
|
||||
}
|
||||
|
||||
// Default implementation
|
||||
@ -1624,69 +1624,69 @@ namespace Exiv2 {
|
||||
long ValueType<T>::toLong(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return static_cast<long>(value_[n]);
|
||||
return static_cast<long>(value_.at(n));
|
||||
}
|
||||
// #55 crash when value_[n].first == LONG_MIN
|
||||
// #55 crash when value_.at(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 && INT_MIN < value_[n].first && value_[n].first < INT_MAX );
|
||||
ok_ = (value_.at(n).second != 0 && INT_MIN < value_.at(n).first && value_.at(n).first < INT_MAX );
|
||||
if (!ok_) return 0;
|
||||
return value_[n].first / value_[n].second;
|
||||
return value_.at(n).first / value_.at(n).second;
|
||||
}
|
||||
// Specialization for unsigned rational
|
||||
template<>
|
||||
inline long ValueType<URational>::toLong(long n) const
|
||||
{
|
||||
ok_ = (value_[n].second != 0 && value_[n].first < LARGE_INT);
|
||||
ok_ = (value_.at(n).second != 0 && value_.at(n).first < LARGE_INT);
|
||||
if (!ok_) return 0;
|
||||
return value_[n].first / value_[n].second;
|
||||
return value_.at(n).first / value_.at(n).second;
|
||||
}
|
||||
// Default implementation
|
||||
template<typename T>
|
||||
float ValueType<T>::toFloat(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return static_cast<float>(value_[n]);
|
||||
return static_cast<float>(value_.at(n));
|
||||
}
|
||||
// Specialization for rational
|
||||
template<>
|
||||
inline float ValueType<Rational>::toFloat(long n) const
|
||||
{
|
||||
ok_ = (value_[n].second != 0);
|
||||
ok_ = (value_.at(n).second != 0);
|
||||
if (!ok_) return 0.0f;
|
||||
return static_cast<float>(value_[n].first) / value_[n].second;
|
||||
return static_cast<float>(value_.at(n).first) / value_.at(n).second;
|
||||
}
|
||||
// Specialization for unsigned rational
|
||||
template<>
|
||||
inline float ValueType<URational>::toFloat(long n) const
|
||||
{
|
||||
ok_ = (value_[n].second != 0);
|
||||
ok_ = (value_.at(n).second != 0);
|
||||
if (!ok_) return 0.0f;
|
||||
return static_cast<float>(value_[n].first) / value_[n].second;
|
||||
return static_cast<float>(value_.at(n).first) / value_.at(n).second;
|
||||
}
|
||||
// Default implementation
|
||||
template<typename T>
|
||||
Rational ValueType<T>::toRational(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return Rational(value_[n], 1);
|
||||
return Rational(value_.at(n), 1);
|
||||
}
|
||||
// Specialization for rational
|
||||
template<>
|
||||
inline Rational ValueType<Rational>::toRational(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return Rational(value_[n].first, value_[n].second);
|
||||
return Rational(value_.at(n).first, value_.at(n).second);
|
||||
}
|
||||
// Specialization for unsigned rational
|
||||
template<>
|
||||
inline Rational ValueType<URational>::toRational(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return Rational(value_[n].first, value_[n].second);
|
||||
return Rational(value_.at(n).first, value_.at(n).second);
|
||||
}
|
||||
// Specialization for float.
|
||||
template<>
|
||||
@ -1694,7 +1694,7 @@ namespace Exiv2 {
|
||||
{
|
||||
ok_ = true;
|
||||
// Warning: This is a very simple conversion, see floatToRationalCast()
|
||||
return floatToRationalCast(value_[n]);
|
||||
return floatToRationalCast(value_.at(n));
|
||||
}
|
||||
// Specialization for double.
|
||||
template<>
|
||||
@ -1702,7 +1702,7 @@ namespace Exiv2 {
|
||||
{
|
||||
ok_ = true;
|
||||
// Warning: This is a very simple conversion, see floatToRationalCast()
|
||||
return floatToRationalCast(static_cast<float>(value_[n]));
|
||||
return floatToRationalCast(static_cast<float>(value_.at(n)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
||||
@ -908,7 +908,7 @@ namespace Exiv2 {
|
||||
assert(pCrwMapping != 0);
|
||||
ULongValue v;
|
||||
v.read(ciffComponent.pData(), 8, byteOrder);
|
||||
time_t t = v.value_[0];
|
||||
time_t t = v.value_.at(0);
|
||||
struct tm* tm = std::localtime(&t);
|
||||
if (tm) {
|
||||
const size_t m = 20;
|
||||
|
||||
17
src/exif.cpp
17
src/exif.cpp
@ -229,7 +229,22 @@ namespace Exiv2 {
|
||||
fct = nullptr;
|
||||
}
|
||||
}
|
||||
if ( fct ) fct(os, value(), pMetadata);
|
||||
if ( fct ) {
|
||||
// https://github.com/Exiv2/exiv2/issues/1706
|
||||
// Sometimes the type of the value doesn't match what the
|
||||
// print function expects. (The expected types are stored
|
||||
// in the TagInfo tables, but they are not enforced when the
|
||||
// metadata is parsed.) These type mismatches can sometimes
|
||||
// cause a std::out_of_range exception to be thrown.
|
||||
try {
|
||||
fct(os, value(), pMetadata);
|
||||
} catch (std::out_of_range&) {
|
||||
os << "Bad value";
|
||||
#ifdef EXIV2_DEBUG_MESSAGES
|
||||
std::cerr << "Caught std::out_of_range exception in Exifdatum::write().\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
@ -203,7 +203,7 @@ namespace Exiv2 {
|
||||
{
|
||||
std::vector<byte>::size_type end = value_.size();
|
||||
for (std::vector<byte>::size_type i = 0; i != end; ++i) {
|
||||
os << static_cast<int>(value_[i]);
|
||||
os << static_cast<int>(value_.at(i));
|
||||
if (i < end - 1) os << " ";
|
||||
}
|
||||
return os;
|
||||
@ -212,7 +212,7 @@ namespace Exiv2 {
|
||||
std::string DataValue::toString(long n) const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << static_cast<int>(value_[n]);
|
||||
os << static_cast<int>(value_.at(n));
|
||||
ok_ = !os.fail();
|
||||
return os.str();
|
||||
}
|
||||
@ -220,19 +220,19 @@ namespace Exiv2 {
|
||||
long DataValue::toLong(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return value_[n];
|
||||
return value_.at(n);
|
||||
}
|
||||
|
||||
float DataValue::toFloat(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return value_[n];
|
||||
return value_.at(n);
|
||||
}
|
||||
|
||||
Rational DataValue::toRational(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return {value_[n], 1};
|
||||
return {value_.at(n), 1};
|
||||
}
|
||||
|
||||
StringValueBase::StringValueBase(TypeId typeId)
|
||||
@ -296,19 +296,19 @@ namespace Exiv2 {
|
||||
long StringValueBase::toLong(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return value_[n];
|
||||
return value_.at(n);
|
||||
}
|
||||
|
||||
float StringValueBase::toFloat(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return value_[n];
|
||||
return value_.at(n);
|
||||
}
|
||||
|
||||
Rational StringValueBase::toRational(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return {value_[n], 1};
|
||||
return {value_.at(n), 1};
|
||||
}
|
||||
|
||||
StringValue::StringValue()
|
||||
@ -340,8 +340,9 @@ namespace Exiv2 {
|
||||
{
|
||||
value_ = buf;
|
||||
// ensure count>0 and nul terminated # https://github.com/Exiv2/exiv2/issues/1484
|
||||
if (value_.empty() || value_[value_.size() - 1] != '\0')
|
||||
if (value_.empty() || value_.at(value_.size() - 1) != '\0') {
|
||||
value_ += '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -740,22 +741,22 @@ namespace Exiv2 {
|
||||
std::string XmpArrayValue::toString(long n) const
|
||||
{
|
||||
ok_ = true;
|
||||
return value_[n];
|
||||
return value_.at(n);
|
||||
}
|
||||
|
||||
long XmpArrayValue::toLong(long n) const
|
||||
{
|
||||
return parseLong(value_[n], ok_);
|
||||
return parseLong(value_.at(n), ok_);
|
||||
}
|
||||
|
||||
float XmpArrayValue::toFloat(long n) const
|
||||
{
|
||||
return parseFloat(value_[n], ok_);
|
||||
return parseFloat(value_.at(n), ok_);
|
||||
}
|
||||
|
||||
Rational XmpArrayValue::toRational(long n) const
|
||||
{
|
||||
return parseRational(value_[n], ok_);
|
||||
return parseRational(value_.at(n), ok_);
|
||||
}
|
||||
|
||||
XmpArrayValue* XmpArrayValue::clone_() const
|
||||
@ -1193,4 +1194,4 @@ namespace Exiv2 {
|
||||
return {toLong(n), 1};
|
||||
}
|
||||
|
||||
} // namespace Exiv2
|
||||
} // namespace Exiv2
|
||||
|
||||
BIN
test/data/issue_1706_poc.exv
Normal file
BIN
test/data/issue_1706_poc.exv
Normal file
Binary file not shown.
24
tests/bugfixes/github/test_issue_1706.py
Normal file
24
tests/bugfixes/github/test_issue_1706.py
Normal file
@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from system_tests import CaseMeta, path
|
||||
|
||||
|
||||
class InvalidDateXMP(metaclass=CaseMeta):
|
||||
"""
|
||||
Regression test for the bug described in:
|
||||
https://github.com/Exiv2/exiv2/issues/1706
|
||||
"""
|
||||
url = "https://github.com/Exiv2/exiv2/issues/1706"
|
||||
|
||||
filename = path("$data_path/issue_1706_poc.exv")
|
||||
commands = ["$exiv2 -PE $filename"]
|
||||
|
||||
stderr = [
|
||||
"""Error: Directory Photo with 65280 entries considered invalid; not read.
|
||||
"""
|
||||
]
|
||||
retval = [0]
|
||||
|
||||
def compare_stdout(self, i, command, got_stdout, expected_stdout):
|
||||
# Check that it printed "Bad value" for the date.
|
||||
self.assertRegex(got_stdout, "Exif.PentaxDng.Date\\s+Long\\s+1\\s+Bad value")
|
||||
Loading…
Reference in New Issue
Block a user