Skip to content

Commit 1f364be

Browse files
Fix seg fault when using iconv_open() (#2403)
* Fix seg fault when using `iconv_open()` - Fix failure condition for `iconv_open()` - Add new exception when failing to change the text encoding of an Exif comment * Add testing for `iconv_open()` seg fault bug * Fix Python test by changing log level
1 parent dc5dc0d commit 1f364be

File tree

7 files changed

+40
-4
lines changed

7 files changed

+40
-4
lines changed

include/exiv2/error.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ enum class ErrorCode {
223223
kerCorruptedMetadata,
224224
kerArithmeticOverflow,
225225
kerMallocFailed,
226+
kerInvalidIconvEncoding,
226227

227228
kerErrorCount,
228229
};

src/convert.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,13 @@ void Converter::cnvExifComment(const char* from, const char* to) {
589589
return;
590590
}
591591
// Todo: Convert to UTF-8 if necessary
592-
(*xmpData_)[to] = cv->comment();
592+
try {
593+
(*xmpData_)[to] = cv->comment();
594+
} catch (const Error&) {
595+
#ifndef SUPPRESS_WARNINGS
596+
EXV_WARNING << "Failed to convert " << from << " to " << to << "\n";
597+
#endif
598+
}
593599
if (erase_)
594600
exifData_->erase(pos);
595601
}
@@ -1567,7 +1573,7 @@ bool convertStringCharsetIconv(std::string& str, const char* from, const char* t
15671573
bool ret = true;
15681574
iconv_t cd;
15691575
cd = iconv_open(to, from);
1570-
if (!cd) {
1576+
if (cd == (iconv_t)(-1)) {
15711577
#ifndef SUPPRESS_WARNINGS
15721578
EXV_WARNING << "iconv_open: " << strError() << "\n";
15731579
#endif

src/error.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ constexpr std::array errList{
8989
N_("corrupted image metadata"), // kerCorruptedMetadata
9090
N_("Arithmetic operation overflow"), // kerArithmeticOverflow
9191
N_("Memory allocation failed"), // kerMallocFailed
92+
N_("Cannot convert text encoding from '%1' to '%2'"), // kerInvalidIconvEncoding
9293
};
9394
static_assert(errList.size() == static_cast<size_t>(Exiv2::ErrorCode::kerErrorCount),
9495
"errList needs to contain a error msg for every ErrorCode defined in error.hpp");

src/value.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,11 @@ size_t CommentValue::copy(byte* buf, ByteOrder byteOrder) const {
370370

371371
std::ostream& CommentValue::write(std::ostream& os) const {
372372
CharsetId csId = charsetId();
373+
std::string text = comment();
373374
if (csId != undefined) {
374375
os << "charset=" << CharsetInfo::name(csId) << " ";
375376
}
376-
return os << comment();
377+
return os << text;
377378
}
378379

379380
std::string CommentValue::comment(const char* encoding) const {
@@ -384,7 +385,8 @@ std::string CommentValue::comment(const char* encoding) const {
384385
c = value_.substr(8);
385386
if (charsetId() == unicode) {
386387
const char* from = !encoding || *encoding == '\0' ? detectCharset(c) : encoding;
387-
convertStringCharset(c, from, "UTF-8");
388+
if (!convertStringCharset(c, from, "UTF-8"))
389+
throw Error(ErrorCode::kerInvalidIconvEncoding, encoding, "UTF-8");
388390
}
389391
bool bAscii = charsetId() == undefined || charsetId() == ascii;
390392
// # 1266 Remove trailing nulls

test/data/issue_2403_poc.exv

79 Bytes
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from system_tests import CaseMeta, CopyTmpFiles, check_no_ASAN_UBSAN_errors
4+
@CopyTmpFiles("$data_path/issue_2403_poc.exv")
5+
6+
class checkIconvSegFault(metaclass=CaseMeta):
7+
url = """"""
8+
description = """Test the fixcom action in the exiv2 app"""
9+
10+
filename = """$tmp_path/issue_2403_poc.exv"""
11+
12+
commands = ["""$exiv2 --verbose --log e --encode made_up_encoding fixcom $filename""",
13+
"""$exiv2 --verbose --keep --encode UCS-2LE fixcom $filename"""]
14+
retval = [1,0]
15+
16+
stdout = ["""File 1/1: $filename
17+
""",
18+
"""File 1/1: $filename
19+
Setting Exif UNICODE user comment to "Test"
20+
"""]
21+
22+
stderr = ["""Exiv2 exception in fixcom action for file $filename:
23+
Cannot convert text encoding from 'made_up_encoding' to 'UTF-8'
24+
""",
25+
""""""]

tests/regression_tests/test_regression_allfiles.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def get_valid_files(data_dir):
147147
# this test file actually contains some eixf info, but windows has
148148
# different output let's try and fix this later
149149
"exiv2-bug1044.tif",
150+
"issue_2403_poc.exv",
150151
]
151152

152153
file_paths = [

0 commit comments

Comments
 (0)