Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/db/unit_tests/dbTransTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -420,4 +420,25 @@ TEST(15)
EXPECT_EQ (db::Trans (t).to_string (), "r0 0,0");
}

TEST(16_issue2362)
{
db::Trans t, tt;
std::string ts;
tl::Extractor ex;

t = db::Trans (0, false, db::Vector (std::numeric_limits<db::Coord>::min (), std::numeric_limits<db::Coord>::min ()));
ts = t.to_string ();

ex = tl::Extractor (ts.c_str ());
ex.read (tt);

EXPECT_EQ (ts, tt.to_string ());

t = db::Trans (0, false, db::Vector (std::numeric_limits<db::Coord>::max (), std::numeric_limits<db::Coord>::max ()));
ts = t.to_string ();

ex = tl::Extractor (ts.c_str ());
ex.read (tt);

EXPECT_EQ (ts, tt.to_string ());
}
26 changes: 22 additions & 4 deletions src/pya/pya/pyaConvert.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@

#include "tlVariant.h"
#include "tlException.h"
#include "tlInternational.h"
#include "tlHeap.h"

#include <string>
#include <limits>
#if defined(HAVE_QT)
# include <QString>
# include <QByteArray>
Expand Down Expand Up @@ -316,12 +318,28 @@ struct python2c_func_cast
}
};

template <class D, class C>
struct python2c_func_cast_check
: public python2c_func<C>
{
D operator() (PyObject *rval)
{
C c = python2c_func<C>::operator() (rval);
if (c < std::numeric_limits<D>::min ()) {
throw tl::TypeError (tl::to_string (tr ("Value out of range: ")) + tl::to_string (c) + tl::to_string (tr (", min value is ")) + tl::to_string ((C) std::numeric_limits<D>::min ()));
} else if (c > std::numeric_limits<D>::max ()) {
throw tl::TypeError (tl::to_string (tr ("Value out of range: ")) + tl::to_string (c) + tl::to_string (tr (", max value is ")) + tl::to_string ((C) std::numeric_limits<D>::max ()));
}
return (D)c;
}
};

template <> struct python2c_func<signed char> : public python2c_func_cast<signed char, char> { };
template <> struct python2c_func<unsigned char> : public python2c_func_cast<unsigned char, char> { };
template <> struct python2c_func<short> : public python2c_func_cast<short, long> { };
template <> struct python2c_func<unsigned short> : public python2c_func_cast<unsigned short, long> { };
template <> struct python2c_func<int> : public python2c_func_cast<int, long> { };
template <> struct python2c_func<unsigned int> : public python2c_func_cast<unsigned int, unsigned long> { };
template <> struct python2c_func<short> : public python2c_func_cast_check<short, long> { };
template <> struct python2c_func<unsigned short> : public python2c_func_cast_check<unsigned short, long> { };
template <> struct python2c_func<int> : public python2c_func_cast_check<int, long> { };
template <> struct python2c_func<unsigned int> : public python2c_func_cast_check<unsigned int, unsigned long> { };

template <> PYA_PUBLIC long long python2c_func<long long>::operator() (PyObject *rval);
template <> PYA_PUBLIC unsigned long long python2c_func<unsigned long long>::operator() (PyObject *rval);
Expand Down
38 changes: 27 additions & 11 deletions src/tl/tl/tlString.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1268,20 +1268,36 @@ Extractor::try_read_signed_int (T &value)
}

value = 0;
while (safe_isdigit (*m_cp)) {
if (value > std::numeric_limits<T>::max () / 10) {
throw tl::Exception (overflow_msg_func<T> () ());

if (minus) {

// NOTE: that's a separate path as there are more numbers in the negative case
while (safe_isdigit (*m_cp)) {
if (value < std::numeric_limits<T>::min () / 10) {
throw tl::Exception (overflow_msg_func<T> () ());
}
value *= 10;
if (value < std::numeric_limits<T>::min () + (*m_cp - '0')) {
throw tl::Exception (overflow_msg_func<T> () ());
}
value -= (*m_cp - '0');
++m_cp;
}
value *= 10;
if (value > std::numeric_limits<T>::max () - (*m_cp - '0')) {
throw tl::Exception (overflow_msg_func<T> () ());

} else {

while (safe_isdigit (*m_cp)) {
if (value > std::numeric_limits<T>::max () / 10) {
throw tl::Exception (overflow_msg_func<T> () ());
}
value *= 10;
if (value > std::numeric_limits<T>::max () - (*m_cp - '0')) {
throw tl::Exception (overflow_msg_func<T> () ());
}
value += (*m_cp - '0');
++m_cp;
}
value += (*m_cp - '0');
++m_cp;
}

if (minus) {
value = -value;
}

return true;
Expand Down
61 changes: 61 additions & 0 deletions src/tl/unit_tests/tlStringTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ TEST(1a)
ex.expect ("x");
}

template<class T>
void
ex_from_string (const std::string &s, T &v)
{
tl::Extractor ex (s.c_str ());
ex.read (v);
}

TEST(2)
{
long l;
Expand Down Expand Up @@ -663,3 +671,56 @@ TEST(16)
EXPECT_EQ (ex.try_read (x), true);
EXPECT_EQ (tl::to_string (x), "-inf");
}

// border cases of int values: round trip value->string->value
TEST(17)
{
int n, nn;
n = std::numeric_limits<int>::max ();
ex_from_string (to_string (n), nn);
EXPECT_EQ (n, nn);
n = std::numeric_limits<int>::min ();
ex_from_string (to_string (n), nn);
EXPECT_EQ (n, nn);

unsigned int un, unn;
un = std::numeric_limits<unsigned int>::max ();
ex_from_string (to_string (un), unn);
EXPECT_EQ (un, unn);
un = std::numeric_limits<unsigned int>::min ();
ex_from_string (to_string (un), unn);
EXPECT_EQ (un, unn);

long ln, lnn;
ln = std::numeric_limits<long>::max ();
ex_from_string (to_string (ln), lnn);
EXPECT_EQ (ln, lnn);
ln = std::numeric_limits<long>::min ();
ex_from_string (to_string (ln), lnn);
EXPECT_EQ (ln, lnn);

unsigned long uln, ulnn;
uln = std::numeric_limits<unsigned long>::max ();
ex_from_string (to_string (uln), ulnn);
EXPECT_EQ (uln, ulnn);
uln = std::numeric_limits<unsigned long>::min ();
ex_from_string (to_string (uln), ulnn);
EXPECT_EQ (uln, ulnn);

long long lln, llnn;
lln = std::numeric_limits<long long>::max ();
ex_from_string (to_string (lln), llnn);
EXPECT_EQ (lln, llnn);
lln = std::numeric_limits<long long>::min ();
ex_from_string (to_string (lln), llnn);
EXPECT_EQ (lln, llnn);

unsigned long long ulln, ullnn;
ulln = std::numeric_limits<unsigned long long>::max ();
ex_from_string (to_string (ulln), ullnn);
EXPECT_EQ (ulln, ullnn);
ulln = std::numeric_limits<unsigned long long>::min ();
ex_from_string (to_string (ulln), ullnn);
EXPECT_EQ (ulln, ullnn);
}

44 changes: 36 additions & 8 deletions testdata/python/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,20 +537,20 @@ def test_12(self):
self.assertEqual( a3.get_n(), -11 )

self.assertEqual( a1.a10_d(5.2), "5.2" )
self.assertEqual( a1.a10_s(0x70000000), "0" )
self.assertEqual( a1.a10_s(0x7fffffff), "-1" )
self.assertEqual( a1.a10_us(0x70000000), "0" )
self.assertEqual( a1.a10_us(0x7fffffff), "65535" )
self.assertEqual( a1.a10_s(0x7fff), "32767" )
self.assertEqual( a1.a10_s(-32768), "-32768" )
self.assertEqual( a1.a10_us(0), "0" )
self.assertEqual( a1.a10_us(0xffff), "65535" )
self.assertEqual( a1.a10_i(-0x80000000), "-2147483648" )
self.assertEqual( a1.a10_l(-0x80000000), "-2147483648" )
self.assertEqual( a1.a10_ll(-0x80000000), "-2147483648" )
self.assertEqual( a1.a10_ui(0xffffffff), "4294967295" )
self.assertEqual( a1.a10_ul(0xffffffff), "4294967295" )
self.assertEqual( a1.a10_ull(0xffffffff), "4294967295" )
self.assertEqual( a1.a11_s(0x70000000), 0 )
self.assertEqual( a1.a11_s(0x7fffffff), -1 )
self.assertEqual( a1.a11_us(0x70000000), 0 )
self.assertEqual( a1.a11_us(0x7fffffff), 65535 )
self.assertEqual( a1.a11_s(0x7fff), 32767 )
self.assertEqual( a1.a11_s(-32768), -32768 )
self.assertEqual( a1.a11_us(0), 0 )
self.assertEqual( a1.a11_us(0xffff), 65535 )
self.assertEqual( a1.a11_i(-0x80000000), -2147483648 )
self.assertEqual( a1.a11_l(-0x80000000), -2147483648 )
self.assertEqual( a1.a11_ll(-0x80000000), -2147483648 )
Expand Down Expand Up @@ -3384,6 +3384,34 @@ def test_94(self):
b = None
self.assertEqual(r() is None, True)

# range checks
def test_95(self):

# uses the A single-argument constructor to verify that int ranges
# are tested
a = pya.A.new_a(100)
self.assertEqual(a.a1(), 100)
a = pya.A.new_a(2147483647)
self.assertEqual(a.a1(), 2147483647)
a = pya.A.new_a(-2147483648)
self.assertEqual(a.a1(), -2147483648)

m = ""
try:
a = pya.A.new_a(2147483648)
self.assertEqual(a.a1(), 2147483648)
except Exception as ex:
m = str(ex)
self.assertEqual(m, "Value out of range: 2147483648, max value is 2147483647 for argument #1 in A.new_a")

m = ""
try:
a = pya.A.new_a(-2147483649)
self.assertEqual(a.a1(), -2147483649)
except Exception as ex:
m = str(ex)
self.assertEqual(m, "Value out of range: -2147483649, min value is -2147483648 for argument #1 in A.new_a")


# run unit tests
if __name__ == '__main__':
Expand Down
Loading