aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-11-04 18:52:41 +0100
committerJay Berkenbilt <ejb@ql.org>2021-11-04 18:53:46 +0100
commitec09b914434b8dbc23bf6043b13ee5d5ecf4c2a6 (patch)
tree02ebea0e8d0b6328cf0c0960f4ff2fd1a1b9c130
parent4a648b9a00d2c4de37bf17165b20a1fc32956eee (diff)
downloadqpdf-ec09b914434b8dbc23bf6043b13ee5d5ecf4c2a6.tar.zst
Add QIntC::range_check_subtract
-rw-r--r--ChangeLog4
-rw-r--r--include/qpdf/QIntC.hh28
-rw-r--r--libtests/qintc.cc32
-rw-r--r--libtests/qtest/qintc/qintc.out9
4 files changed, 73 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index ed435242..56a2be61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2021-11-04 Jay Berkenbilt <ejb@ql.org>
+ * Add QIntC::range_check_substract to do range checking on
+ subtraction, which has different boundary conditions from
+ addition.
+
* Bug fix: fix crash that could occur under certain conditions
when using --pages with files that had form fields. Fixes #548.
diff --git a/include/qpdf/QIntC.hh b/include/qpdf/QIntC.hh
index 2349e775..03da8853 100644
--- a/include/qpdf/QIntC.hh
+++ b/include/qpdf/QIntC.hh
@@ -250,6 +250,34 @@ namespace QIntC // QIntC = qpdf Integer Conversion
throw std::range_error(msg.str());
}
}
+
+ template <typename T>
+ void range_check_substract(T const& cur, T const& delta)
+ {
+ if ((delta >= 0) == (cur >= 0))
+ {
+ return;
+ }
+
+ if ((delta > 0) &&
+ ((std::numeric_limits<T>::min() + delta) > cur))
+ {
+ std::ostringstream msg;
+ msg.imbue(std::locale::classic());
+ msg << "subtracting " << delta << " from " << cur
+ << " would cause an integer underflow";
+ throw std::range_error(msg.str());
+ }
+ else if ((delta < 0) &&
+ ((std::numeric_limits<T>::max() + delta) < cur))
+ {
+ std::ostringstream msg;
+ msg.imbue(std::locale::classic());
+ msg << "subtracting " << delta << " from " << cur
+ << " would cause an integer overflow";
+ throw std::range_error(msg.str());
+ }
+ }
};
#endif // QINTC_HH
diff --git a/libtests/qintc.cc b/libtests/qintc.cc
index 32c3713f..f9ca9558 100644
--- a/libtests/qintc.cc
+++ b/libtests/qintc.cc
@@ -48,6 +48,29 @@ static void try_range_check_real(
std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl;
}
+#define try_range_check_subtract(exp_pass, a, b) \
+ try_range_check_subtract_real(#a " - " #b, exp_pass, a, b)
+
+template <typename T>
+static void try_range_check_subtract_real(
+ char const* description, bool exp_pass,
+ T const& a, T const& b)
+{
+ bool passed = false;
+ try
+ {
+ QIntC::range_check_substract(a, b);
+ std::cout << description << ": okay";
+ passed = true;
+ }
+ catch (std::range_error& e)
+ {
+ std::cout << description << ": " << e.what();
+ passed = false;
+ }
+ std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl;
+}
+
int main()
{
uint32_t u1 = 3141592653U; // Too big for signed type
@@ -96,5 +119,14 @@ int main()
try_range_check(false, min_ll, -1LL);
try_range_check(false, max_sc, max_sc);
try_range_check(true, '!', '#');
+ try_range_check_subtract(true, 1, 2);
+ try_range_check_subtract(true, -1, -2);
+ try_range_check_subtract(true, 1, 10);
+ try_range_check_subtract(true, -1, -10);
+ try_range_check_subtract(false, 0LL, min_ll);
+ try_range_check_subtract(false, 1LL, min_ll);
+ try_range_check_subtract(true, 0LL, max_ll);
+ try_range_check_subtract(true, -1LL, max_ll);
+ try_range_check_subtract(false, -2LL, max_ll);
return 0;
}
diff --git a/libtests/qtest/qintc/qintc.out b/libtests/qtest/qintc/qintc.out
index 5520c635..c78f02ab 100644
--- a/libtests/qtest/qintc/qintc.out
+++ b/libtests/qtest/qintc/qintc.out
@@ -26,3 +26,12 @@ min_ll + 0LL: okay PASSED
min_ll + -1LL: adding -1 to -9223372036854775808 would cause an integer underflow PASSED
max_sc + max_sc: adding  to  would cause an integer overflow PASSED
'!' + '#': okay PASSED
+1 - 2: okay PASSED
+-1 - -2: okay PASSED
+1 - 10: okay PASSED
+-1 - -10: okay PASSED
+0LL - min_ll: subtracting -9223372036854775808 from 0 would cause an integer overflow PASSED
+1LL - min_ll: subtracting -9223372036854775808 from 1 would cause an integer overflow PASSED
+0LL - max_ll: okay PASSED
+-1LL - max_ll: okay PASSED
+-2LL - max_ll: subtracting 9223372036854775807 from -2 would cause an integer underflow PASSED