Mercurial > pub > dyncall > bindings
diff python/pydc/pydc.c @ 63:9b6cdffd30dd
- further fixes of inccorect overflow errors for int (and long on LLP64 systems)
* prev commit had bugs
* added overflow tests for also int, long, long long (for both, lp64 and llp64)
- while at it, fixing a reference leak when not using python with utf8 caching
author | Tassilo Philipp |
---|---|
date | Sun, 19 May 2024 15:33:18 +0200 |
parents | 4a9f6c7c09c1 |
children | 75a4082f0fce |
line wrap: on
line diff
--- a/python/pydc/pydc.c Sat May 18 15:33:54 2024 +0200 +++ b/python/pydc/pydc.c Sun May 19 15:33:18 2024 +0200 @@ -259,17 +259,21 @@ long long ll; if ( !DcPyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos ); +#if ULONG_MAX < ULLONG_MAX ll = (DClonglong) PyLong_AsLongLong(po); - if (u && (ll < 0 || ll > ULONG_MAX)) //@@@ on lp64, this is a bad comparison + if (u && (ll < 0 || ll > ULONG_MAX)) return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting 0 <= arg <= %ld, got %lld", pos, ULONG_MAX, ll ); if (!u && (ll < LONG_MIN || ll > LONG_MAX)) return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting %ld <= arg <= %ld, got %lld", pos, LONG_MIN, LONG_MAX, ll ); +#else + ll = u ? (DClonglong) PyLong_AsUnsignedLongLong(po) : (DClonglong) PyLong_AsLongLong(po); +#endif *l = (DClong)ll; return po; } -static inline PyObject* py2dclonglong(DClonglong* ll, PyObject* po, int pos) +static inline PyObject* py2dclonglong(DClonglong* ll, PyObject* po, int u, int pos) { #if PY_MAJOR_VERSION < 3 if ( PyInt_Check(po) ) { @@ -280,7 +284,8 @@ if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting " EXPECT_LONG_TYPE_STR, pos ); - *ll = (DClonglong) PyLong_AsLongLong(po); + *ll = u ? (DClonglong) PyLong_AsUnsignedLongLong(po) : (DClonglong) PyLong_AsLongLong(po); + return po; } @@ -342,9 +347,6 @@ return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); // get signature -#if !defined(PYUNICODE_CACHES_UTF8) - PyObject* sig_obj = NULL; -#endif PyObject* so = PyTuple_GetItem(args, pos++); if ( PyUnicode_Check(so) ) { @@ -352,8 +354,15 @@ sig_ptr = PyUnicode_AsUTF8(so); #else // w/o PyUnicode_AsUTF8(), which caches the UTF-8 representation, itself, create new ref we'll dec below - if((sig_obj = PyUnicode_AsEncodedString(so, "utf-8", "strict"))) // !new ref! - sig_ptr = PyBytes_AS_STRING(sig_obj); // Borrowed pointer + PyObject* sig_obj = PyUnicode_AsEncodedString(so, "utf-8", "strict"); // !new ref! + if(sig_obj) { + const char *a = PyBytes_AS_STRING(sig_obj); // Borrowed pointer + if(a) { + sig_ptr = alloca(strlen(sig_ptr)+1); + strcpy(sig_ptr, a); + } + Py_DECREF(sig_obj); + } #endif } else if ( DcPyString_Check(so) ) sig_ptr = DcPyString_AsString(so); @@ -426,6 +435,7 @@ return NULL; dcArgInt(gpCall, i); } + break; case DC_SIGCHAR_LONG: case DC_SIGCHAR_ULONG: @@ -435,12 +445,13 @@ return NULL; dcArgLong(gpCall, l); } + break; case DC_SIGCHAR_LONGLONG: case DC_SIGCHAR_ULONGLONG: { DClonglong ll; - if(!py2dclonglong(&ll, po, pos)) + if(!py2dclonglong(&ll, po, ch == DC_SIGCHAR_ULONGLONG, pos)) return NULL; dcArgLongLong(gpCall, ll); } @@ -516,7 +527,6 @@ if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); - ch = *++sig_ptr; switch(ch) { @@ -540,10 +550,6 @@ default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature"); // @@@ this could be handled via array lookups of a 256b array instead of switch/case, then share it with callback code if it makes sense } - -#if !defined(PYUNICODE_CACHES_UTF8) - Py_XDECREF(sig_obj); -#endif } @@ -656,23 +662,16 @@ case DC_SIGCHAR_INT: case DC_SIGCHAR_UINT: - if ( !DcPyInt_Check(po) ) - PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", -1 ); - else - result->i = (DCint) DcPyInt_AS_LONG(po); - break; + py2dcint(&result->i, po, ch == DC_SIGCHAR_UINT, -1); case DC_SIGCHAR_LONG: case DC_SIGCHAR_ULONG: - if ( !DcPyInt_Check(po) ) - PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", -1 ); - else - result->j = (DClong) PyLong_AsLong(po); + py2dclong(&result->j, po, ch == DC_SIGCHAR_ULONG, -1); break; case DC_SIGCHAR_LONGLONG: case DC_SIGCHAR_ULONGLONG: - py2dclonglong(&result->l, po, -1); + py2dclonglong(&result->l, po, ch == DC_SIGCHAR_ULONGLONG, -1); break; case DC_SIGCHAR_FLOAT: