aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QUtil.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2019-06-21 05:35:23 +0200
committerJay Berkenbilt <ejb@ql.org>2019-06-21 19:17:21 +0200
commitd71f05ca07eb5c7cfa4d6d23e5c1f2a800f52e8e (patch)
tree60f4a13cbadee1a02a49f35f325460f2ad507c95 /libqpdf/QUtil.cc
parentf40ffc9d6392edf9b6fe74d288d6d578e6d1a240 (diff)
downloadqpdf-d71f05ca07eb5c7cfa4d6d23e5c1f2a800f52e8e.tar.zst
Fix sign and conversion warnings (major)
This makes all integer type conversions that have potential data loss explicit with calls that do range checks and raise an exception. After this commit, qpdf builds with no warnings when -Wsign-conversion -Wconversion is used with gcc or clang or when -W3 -Wd4800 is used with MSVC. This significantly reduces the likelihood of potential crashes from bogus integer values. There are some parts of the code that take int when they should take size_t or an offset. Such places would make qpdf not support files with more than 2^31 of something that usually wouldn't be so large. In the event that such a file shows up and is valid, at least qpdf would raise an error in the right spot so the issue could be legitimately addressed rather than failing in some weird way because of a silent overflow condition.
Diffstat (limited to 'libqpdf/QUtil.cc')
-rw-r--r--libqpdf/QUtil.cc78
1 files changed, 39 insertions, 39 deletions
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
index dee3a636..c8c23f6a 100644
--- a/libqpdf/QUtil.cc
+++ b/libqpdf/QUtil.cc
@@ -251,15 +251,15 @@ int_to_string_base_internal(T num, int base, int length)
std::ostringstream buf;
buf << std::setbase(base) << std::nouppercase << num;
std::string result;
- if ((length > 0) &&
- (buf.str().length() < QIntC::to_size(length)))
+ int str_length = QIntC::to_int(buf.str().length());
+ if ((length > 0) && (str_length < length))
{
- result.append(length - buf.str().length(), '0');
+ result.append(QIntC::to_size(length - str_length), '0');
}
result += buf.str();
- if ((length < 0) && (buf.str().length() < QIntC::to_size(-length)))
+ if ((length < 0) && (str_length < -length))
{
- result.append(-length - buf.str().length(), ' ');
+ result.append(QIntC::to_size(-length - str_length), ' ');
}
return result;
}
@@ -273,7 +273,7 @@ QUtil::int_to_string(long long num, int length)
std::string
QUtil::uint_to_string(unsigned long long num, int length)
{
- return int_to_string_base(num, 10, length);
+ return uint_to_string_base(num, 10, length);
}
std::string
@@ -420,7 +420,7 @@ QUtil::safe_fopen(char const* filename, char const* mode)
wmode[strlen(mode)] = 0;
for (size_t i = 0; i < strlen(mode); ++i)
{
- wmode[i] = mode[i];
+ wmode[i] = static_cast<wchar_t>(mode[i]);
}
#ifdef _MSC_VER
@@ -465,9 +465,7 @@ QUtil::seek(FILE* stream, qpdf_offset_t offset, int whence)
# if defined _MSC_VER || defined __BORLANDC__
return _fseeki64(stream, offset, whence);
# else
- return fseek(stream,
- QIntC::IntConverter<qpdf_offset_t, long>(offset),
- whence);
+ return fseek(stream, QIntC::to_long(offset), whence);
# endif
#endif
}
@@ -572,17 +570,15 @@ QUtil::hex_decode(std::string const& input)
bool skip = false;
if ((*p >= 'A') && (*p <= 'F'))
{
- ch -= 'A';
- ch += 10;
+ ch = QIntC::to_char(ch - 'A' + 10);
}
else if ((*p >= 'a') && (*p <= 'f'))
{
- ch -= 'a';
- ch += 10;
+ ch = QIntC::to_char(ch - 'a' + 10);
}
else if ((*p >= '0') && (*p <= '9'))
{
- ch -= '0';
+ ch = QIntC::to_char(ch - '0');
}
else
{
@@ -592,12 +588,12 @@ QUtil::hex_decode(std::string const& input)
{
if (pos == 0)
{
- result.push_back(ch << 4);
+ result.push_back(static_cast<char>(ch << 4));
pos = 1;
}
else
{
- result[result.length()-1] += ch;
+ result[result.length()-1] |= ch;
pos = 0;
}
}
@@ -717,7 +713,7 @@ QUtil::get_current_time()
uinow.LowPart = filenow.dwLowDateTime;
uinow.HighPart = filenow.dwHighDateTime;
ULONGLONG now = uinow.QuadPart;
- return ((now / 10000000LL) - 11644473600LL);
+ return static_cast<time_t>((now / 10000000ULL) - 11644473600ULL);
#else
return time(0);
#endif
@@ -762,7 +758,7 @@ QUtil::toUTF8(unsigned long uval)
*cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f));
uval >>= 6;
// Maximum that will fit in high byte now shrinks by one bit
- maxval >>= 1;
+ maxval = static_cast<unsigned char>(maxval >> 1);
// Slide to the left one byte
if (cur_byte <= bytes)
{
@@ -773,7 +769,7 @@ QUtil::toUTF8(unsigned long uval)
// If maxval is k bits long, the high (7 - k) bits of the
// resulting byte must be high.
*cur_byte = static_cast<unsigned char>(
- (0xff - (1 + (maxval << 1))) + uval);
+ QIntC::to_ulong(0xff - (1 + (maxval << 1))) + uval);
result += reinterpret_cast<char*>(cur_byte);
}
@@ -792,20 +788,22 @@ QUtil::toUTF16(unsigned long uval)
else if (uval <= 0xffff)
{
char out[2];
- out[0] = (uval & 0xff00) >> 8;
- out[1] = (uval & 0xff);
+ out[0] = static_cast<char>((uval & 0xff00) >> 8);
+ out[1] = static_cast<char>(uval & 0xff);
result = std::string(out, 2);
}
else if (uval <= 0x10ffff)
{
char out[4];
uval -= 0x10000;
- unsigned short high = ((uval & 0xffc00) >> 10) + 0xd800;
- unsigned short low = (uval & 0x3ff) + 0xdc00;
- out[0] = (high & 0xff00) >> 8;
- out[1] = (high & 0xff);
- out[2] = (low & 0xff00) >> 8;
- out[3] = (low & 0xff);
+ unsigned short high =
+ static_cast<unsigned short>(((uval & 0xffc00) >> 10) + 0xd800);
+ unsigned short low =
+ static_cast<unsigned short>((uval & 0x3ff) + 0xdc00);
+ out[0] = static_cast<char>((high & 0xff00) >> 8);
+ out[1] = static_cast<char>(high & 0xff);
+ out[2] = static_cast<char>((low & 0xff00) >> 8);
+ out[3] = static_cast<char>(low & 0xff);
result = std::string(out, 4);
}
else
@@ -1172,7 +1170,8 @@ QUtil::parse_numrange(char const* range, int max)
if (p)
{
message = "error at * in numeric range " +
- std::string(range, p - range) + "*" + p + ": " + e.what();
+ std::string(range, QIntC::to_size(p - range)) +
+ "*" + p + ": " + e.what();
}
else
{
@@ -1764,7 +1763,7 @@ unsigned long get_next_utf8_codepoint(
while (ch & bit_check)
{
++bytes_needed;
- to_clear |= bit_check;
+ to_clear = static_cast<unsigned char>(to_clear | bit_check);
bit_check >>= 1;
}
if (((bytes_needed > 5) || (bytes_needed < 1)) ||
@@ -1774,11 +1773,11 @@ unsigned long get_next_utf8_codepoint(
return 0xfffd;
}
- unsigned long codepoint = (ch & ~to_clear);
+ unsigned long codepoint = static_cast<unsigned long>(ch & ~to_clear);
while (bytes_needed > 0)
{
--bytes_needed;
- ch = utf8_val.at(++pos);
+ ch = static_cast<unsigned char>(utf8_val.at(++pos));
if ((ch & 0xc0) != 0x80)
{
--pos;
@@ -1823,7 +1822,7 @@ transcode_utf8(std::string const& utf8_val, std::string& result,
char ch = static_cast<char>(codepoint);
if (encoding == e_utf16)
{
- result += QUtil::toUTF16(ch);
+ result += QUtil::toUTF16(QIntC::to_ulong(ch));
}
else
{
@@ -1837,7 +1836,7 @@ transcode_utf8(std::string const& utf8_val, std::string& result,
else if ((codepoint > 160) && (codepoint < 256) &&
((encoding == e_winansi) || (encoding == e_pdfdoc)))
{
- result.append(1, static_cast<unsigned char>(codepoint & 0xff));
+ result.append(1, static_cast<char>(codepoint & 0xff));
}
else
{
@@ -1859,7 +1858,7 @@ transcode_utf8(std::string const& utf8_val, std::string& result,
okay = false;
ch = static_cast<unsigned char>(unknown);
}
- result.append(1, ch);
+ result.append(1, static_cast<char>(ch));
}
}
return okay;
@@ -1956,7 +1955,7 @@ QUtil::utf16_to_utf8(std::string const& val)
}
// If the string has an odd number of bytes, the last byte is
// ignored.
- for (unsigned int i = start; i < len; i += 2)
+ for (size_t i = start; i < len; i += 2)
{
// Convert from UTF16-BE. If we get a malformed
// codepoint, this code will generate incorrect output
@@ -1965,11 +1964,12 @@ QUtil::utf16_to_utf8(std::string const& val)
// discarded, and a low codepoint not preceded by a high
// codepoint will just get its low 10 bits output.
unsigned short bits =
- (static_cast<unsigned char>(val.at(i)) << 8) +
- static_cast<unsigned char>(val.at(i+1));
+ QIntC::to_ushort(
+ (static_cast<unsigned char>(val.at(i)) << 8) +
+ static_cast<unsigned char>(val.at(i+1)));
if ((bits & 0xFC00) == 0xD800)
{
- codepoint = 0x10000 + ((bits & 0x3FF) << 10);
+ codepoint = 0x10000U + ((bits & 0x3FFU) << 10U);
continue;
}
else if ((bits & 0xFC00) == 0xDC00)