mirror of https://github.com/swig/swig
python/cast_mode: Fix integer overflow of LONG_MAX+1.
In SWIG_CanCastAsInteger, we check for double(value) <= double(LONG_MAX). However LONG_MAX cannot be represented as double if sizeof(long)=8, so it is usually rounded to LONG_MAX+1. So SWIG_CanCastAsInteger returned true for LONG_MAX+1 and the next cast ended up in an integer overflow. Worse for unsigned long: It is called by smaller unsigned integers with range checks after the convertion to unsigned long. As the integer overflow yields a 0x0, this is valid for all small unsigned integers. Smaller signed integers will always fail this range check after the integer overflow. This fixes the tests on my machine: as_l(lmaxd + LSB) as_ll(llmaxd + LSB) as_ul(ulmax + LSB) as_ull(ullmax + LSB) Wrong old results before this commit: as_l(float(2**63)) := -0x8000000000000000 as_ll(float(2**63)) := -0x8000000000000000 as_uc(float(2**64)) := 0x0 as_us(float(2**64)) := 0x0 as_ui(float(2**64)) := 0x0 as_ul(float(2**64)) := 0x0 as_ull(float(2**64)) := 0x0 Now all of them throw an exception.
This commit is contained in:
parent
02c45b9145
commit
5c008f0c52
|
@ -7,6 +7,17 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.2.0 (in progress)
|
||||
===========================
|
||||
|
||||
2023-XX-XX: degasus
|
||||
[Python] #2494 Fix integer overflow / undefined behavior in the python cast_mode on
|
||||
sizeof(long)==8 platforms for the implicit conversion of the edge cases:
|
||||
long(double(LONG_MAX + 1))
|
||||
long long(double(LONG_MAX + 1))
|
||||
unsigned char(double(ULONG_MAX + 1))
|
||||
unsigned short(double(ULONG_MAX + 1))
|
||||
unsigned int(double(ULONG_MAX + 1))
|
||||
unsigned long(double(ULONG_MAX + 1))
|
||||
unsigned long long(double(ULONG_MAX + 1))
|
||||
|
||||
2023-12-03: olly
|
||||
[Ocaml] Remove -suffix command line option which has emitted a
|
||||
deprecation warning since SWIG 3.0.4 - if you want to specify
|
||||
|
|
|
@ -104,7 +104,9 @@ SWIG_AsVal_dec(long)(PyObject *obj, long* val)
|
|||
if (!dispatch) {
|
||||
double d;
|
||||
int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
|
||||
if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
|
||||
// largest double not larger than LONG_MAX
|
||||
const double long_max = sizeof(long) == 8 ? 0x7ffffffffffffc00LL : LONG_MAX;
|
||||
if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, long_max)) {
|
||||
if (val) *val = (long)(d);
|
||||
return res;
|
||||
}
|
||||
|
@ -166,7 +168,9 @@ SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val)
|
|||
if (!dispatch) {
|
||||
double d;
|
||||
int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d));
|
||||
if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
|
||||
// largest double not larger than ULONG_MAX
|
||||
const double ulong_max = sizeof(unsigned long) == 8 ? 0xfffffffffffff800uLL : ULONG_MAX;
|
||||
if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ulong_max)) {
|
||||
if (val) *val = (unsigned long)(d);
|
||||
return res;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue