mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-22 22:58:33 +00:00
Detect integer overflow/underflow
This commit is contained in:
parent
d7d446e0b8
commit
6d46346eb9
@ -29,8 +29,12 @@ namespace QUtil
|
||||
QPDF_DLL
|
||||
std::string double_to_string(double, int decimal_places = 0);
|
||||
|
||||
// These string to number methods throw std::runtime_error on
|
||||
// underflow/overflow.
|
||||
QPDF_DLL
|
||||
long long string_to_ll(char const* str);
|
||||
QPDF_DLL
|
||||
int string_to_int(char const* str);
|
||||
|
||||
// Pipeline's write method wants unsigned char*, but we often have
|
||||
// some other type of string. These methods do combinations of
|
||||
|
@ -81,11 +81,40 @@ QUtil::double_to_string(double num, int decimal_places)
|
||||
long long
|
||||
QUtil::string_to_ll(char const* str)
|
||||
{
|
||||
errno = 0;
|
||||
#ifdef _MSC_VER
|
||||
return _strtoi64(str, 0, 10);
|
||||
long long result = _strtoi64(str, 0, 10);
|
||||
#else
|
||||
return strtoll(str, 0, 10);
|
||||
long long result = strtoll(str, 0, 10);
|
||||
#endif
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("overflow/underflow converting ") + str
|
||||
+ " to 64-bit integer");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
QUtil::string_to_int(char const* str)
|
||||
{
|
||||
errno = 0;
|
||||
long long_val = strtol(str, 0, 10);
|
||||
if (errno == ERANGE)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("overflow/underflow converting ") + str
|
||||
+ " to long integer");
|
||||
}
|
||||
int result = static_cast<int>(long_val);
|
||||
if (static_cast<long>(result) != long_val)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("overflow/underflow converting ") + str
|
||||
+ " to integer");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char*
|
||||
|
@ -14,6 +14,14 @@
|
||||
one
|
||||
7
|
||||
compare okay
|
||||
-2147483648 to int: PASSED
|
||||
2147483647 to int: PASSED
|
||||
2147483648 to int threw: PASSED
|
||||
-2147483649 to int threw: PASSED
|
||||
9999999999999999999999999 to int threw: PASSED
|
||||
2147483648 to int: PASSED
|
||||
-2147483649 to int: PASSED
|
||||
99999999999999999999999999999999999999999999999999 to int threw: PASSED
|
||||
----
|
||||
before remove
|
||||
exception: remove file: No such file or directory
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/PointerHolder.hh>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h>
|
||||
@ -13,6 +14,57 @@
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
template <class int_T>
|
||||
void test_to_number(char const* str, int_T wanted, bool error,
|
||||
int_T (*fn)(char const*))
|
||||
{
|
||||
bool threw = false;
|
||||
bool worked = false;
|
||||
int_T result = 0;
|
||||
try
|
||||
{
|
||||
result = fn(str);
|
||||
worked = (wanted == result);
|
||||
}
|
||||
catch (std::runtime_error)
|
||||
{
|
||||
threw = true;
|
||||
}
|
||||
if (threw)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
std::cout << str << " to int threw: PASSED" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << str << " to int threw but wanted "
|
||||
<< wanted << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (worked)
|
||||
{
|
||||
std::cout << str << " to int: PASSED" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << str << " to int failed; got " << result << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_to_int(char const* str, int wanted, bool error)
|
||||
{
|
||||
test_to_number(str, wanted, error, QUtil::string_to_int);
|
||||
}
|
||||
|
||||
void test_to_ll(char const* str, long long wanted, bool error)
|
||||
{
|
||||
test_to_number(str, wanted, error, QUtil::string_to_ll);
|
||||
}
|
||||
|
||||
void string_conversion_test()
|
||||
{
|
||||
std::cout << QUtil::int_to_string(16059) << std::endl
|
||||
@ -44,6 +96,21 @@ void string_conversion_test()
|
||||
std::cout << "compare failed" << std::endl;
|
||||
}
|
||||
delete [] tmp;
|
||||
|
||||
std::string int_max_str = QUtil::int_to_string(INT_MAX);
|
||||
std::string int_min_str = QUtil::int_to_string(INT_MIN);
|
||||
long long int_max_plus_1 = static_cast<long long>(INT_MAX) + 1;
|
||||
long long int_min_minus_1 = static_cast<long long>(INT_MIN) - 1;
|
||||
std::string int_max_plus_1_str = QUtil::int_to_string(int_max_plus_1);
|
||||
std::string int_min_minus_1_str = QUtil::int_to_string(int_min_minus_1);
|
||||
test_to_int(int_min_str.c_str(), INT_MIN, false);
|
||||
test_to_int(int_max_str.c_str(), INT_MAX, false);
|
||||
test_to_int(int_max_plus_1_str.c_str(), 0, true);
|
||||
test_to_int(int_min_minus_1_str.c_str(), 0, true);
|
||||
test_to_int("9999999999999999999999999", 0, true);
|
||||
test_to_ll(int_max_plus_1_str.c_str(), int_max_plus_1, false);
|
||||
test_to_ll(int_min_minus_1_str.c_str(), int_min_minus_1, false);
|
||||
test_to_ll("99999999999999999999999999999999999999999999999999", 0, true);
|
||||
}
|
||||
|
||||
void os_wrapper_test()
|
||||
|
Loading…
x
Reference in New Issue
Block a user