Mercurial > pub > dyncall > bindings
comparison 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 |
comparison
equal
deleted
inserted
replaced
62:4a9f6c7c09c1 | 63:9b6cdffd30dd |
---|---|
257 static inline PyObject* py2dclong(DClong* l, PyObject* po, int u, int pos) | 257 static inline PyObject* py2dclong(DClong* l, PyObject* po, int u, int pos) |
258 { | 258 { |
259 long long ll; | 259 long long ll; |
260 if ( !DcPyInt_Check(po) ) | 260 if ( !DcPyInt_Check(po) ) |
261 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos ); | 261 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", pos ); |
262 #if ULONG_MAX < ULLONG_MAX | |
262 ll = (DClonglong) PyLong_AsLongLong(po); | 263 ll = (DClonglong) PyLong_AsLongLong(po); |
263 if (u && (ll < 0 || ll > ULONG_MAX)) //@@@ on lp64, this is a bad comparison | 264 if (u && (ll < 0 || ll > ULONG_MAX)) |
264 return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting 0 <= arg <= %ld, got %lld", pos, ULONG_MAX, ll ); | 265 return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting 0 <= arg <= %ld, got %lld", pos, ULONG_MAX, ll ); |
265 if (!u && (ll < LONG_MIN || ll > LONG_MAX)) | 266 if (!u && (ll < LONG_MIN || ll > LONG_MAX)) |
266 return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting %ld <= arg <= %ld, got %lld", pos, LONG_MIN, LONG_MAX, ll ); | 267 return PyErr_Format( PyExc_RuntimeError, "arg %lld out of range - expecting %ld <= arg <= %ld, got %lld", pos, LONG_MIN, LONG_MAX, ll ); |
268 #else | |
269 ll = u ? (DClonglong) PyLong_AsUnsignedLongLong(po) : (DClonglong) PyLong_AsLongLong(po); | |
270 #endif | |
267 | 271 |
268 *l = (DClong)ll; | 272 *l = (DClong)ll; |
269 return po; | 273 return po; |
270 } | 274 } |
271 | 275 |
272 static inline PyObject* py2dclonglong(DClonglong* ll, PyObject* po, int pos) | 276 static inline PyObject* py2dclonglong(DClonglong* ll, PyObject* po, int u, int pos) |
273 { | 277 { |
274 #if PY_MAJOR_VERSION < 3 | 278 #if PY_MAJOR_VERSION < 3 |
275 if ( PyInt_Check(po) ) { | 279 if ( PyInt_Check(po) ) { |
276 *ll = (DClonglong) PyInt_AS_LONG(po); | 280 *ll = (DClonglong) PyInt_AS_LONG(po); |
277 return po; | 281 return po; |
278 } | 282 } |
279 #endif | 283 #endif |
280 if ( !PyLong_Check(po) ) | 284 if ( !PyLong_Check(po) ) |
281 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting " EXPECT_LONG_TYPE_STR, pos ); | 285 return PyErr_Format( PyExc_RuntimeError, "arg %d - expecting " EXPECT_LONG_TYPE_STR, pos ); |
282 | 286 |
283 *ll = (DClonglong) PyLong_AsLongLong(po); | 287 *ll = u ? (DClonglong) PyLong_AsUnsignedLongLong(po) : (DClonglong) PyLong_AsLongLong(po); |
288 | |
284 return po; | 289 return po; |
285 } | 290 } |
286 | 291 |
287 static inline PyObject* py2dcpointer(DCpointer* p, PyObject* po, int pos) | 292 static inline PyObject* py2dcpointer(DCpointer* p, PyObject* po, int pos) |
288 { | 293 { |
340 pfunc = DcPyCObject_AsVoidPtr(PyTuple_GetItem(args, pos++)); | 345 pfunc = DcPyCObject_AsVoidPtr(PyTuple_GetItem(args, pos++)); |
341 if (!pfunc) | 346 if (!pfunc) |
342 return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); | 347 return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); |
343 | 348 |
344 // get signature | 349 // get signature |
345 #if !defined(PYUNICODE_CACHES_UTF8) | |
346 PyObject* sig_obj = NULL; | |
347 #endif | |
348 PyObject* so = PyTuple_GetItem(args, pos++); | 350 PyObject* so = PyTuple_GetItem(args, pos++); |
349 if ( PyUnicode_Check(so) ) | 351 if ( PyUnicode_Check(so) ) |
350 { | 352 { |
351 #if defined(PYUNICODE_CACHES_UTF8) | 353 #if defined(PYUNICODE_CACHES_UTF8) |
352 sig_ptr = PyUnicode_AsUTF8(so); | 354 sig_ptr = PyUnicode_AsUTF8(so); |
353 #else | 355 #else |
354 // w/o PyUnicode_AsUTF8(), which caches the UTF-8 representation, itself, create new ref we'll dec below | 356 // w/o PyUnicode_AsUTF8(), which caches the UTF-8 representation, itself, create new ref we'll dec below |
355 if((sig_obj = PyUnicode_AsEncodedString(so, "utf-8", "strict"))) // !new ref! | 357 PyObject* sig_obj = PyUnicode_AsEncodedString(so, "utf-8", "strict"); // !new ref! |
356 sig_ptr = PyBytes_AS_STRING(sig_obj); // Borrowed pointer | 358 if(sig_obj) { |
359 const char *a = PyBytes_AS_STRING(sig_obj); // Borrowed pointer | |
360 if(a) { | |
361 sig_ptr = alloca(strlen(sig_ptr)+1); | |
362 strcpy(sig_ptr, a); | |
363 } | |
364 Py_DECREF(sig_obj); | |
365 } | |
357 #endif | 366 #endif |
358 } else if ( DcPyString_Check(so) ) | 367 } else if ( DcPyString_Check(so) ) |
359 sig_ptr = DcPyString_AsString(so); | 368 sig_ptr = DcPyString_AsString(so); |
360 | 369 |
361 | 370 |
424 DCint i; | 433 DCint i; |
425 if(!py2dcint(&i, po, ch == DC_SIGCHAR_UINT, pos)) | 434 if(!py2dcint(&i, po, ch == DC_SIGCHAR_UINT, pos)) |
426 return NULL; | 435 return NULL; |
427 dcArgInt(gpCall, i); | 436 dcArgInt(gpCall, i); |
428 } | 437 } |
438 break; | |
429 | 439 |
430 case DC_SIGCHAR_LONG: | 440 case DC_SIGCHAR_LONG: |
431 case DC_SIGCHAR_ULONG: | 441 case DC_SIGCHAR_ULONG: |
432 { | 442 { |
433 DClong l; | 443 DClong l; |
434 if(!py2dclong(&l, po, ch == DC_SIGCHAR_ULONG, pos)) | 444 if(!py2dclong(&l, po, ch == DC_SIGCHAR_ULONG, pos)) |
435 return NULL; | 445 return NULL; |
436 dcArgLong(gpCall, l); | 446 dcArgLong(gpCall, l); |
437 } | 447 } |
448 break; | |
438 | 449 |
439 case DC_SIGCHAR_LONGLONG: | 450 case DC_SIGCHAR_LONGLONG: |
440 case DC_SIGCHAR_ULONGLONG: | 451 case DC_SIGCHAR_ULONGLONG: |
441 { | 452 { |
442 DClonglong ll; | 453 DClonglong ll; |
443 if(!py2dclonglong(&ll, po, pos)) | 454 if(!py2dclonglong(&ll, po, ch == DC_SIGCHAR_ULONGLONG, pos)) |
444 return NULL; | 455 return NULL; |
445 dcArgLongLong(gpCall, ll); | 456 dcArgLongLong(gpCall, ll); |
446 } | 457 } |
447 break; | 458 break; |
448 | 459 |
513 if (pos != ts) | 524 if (pos != ts) |
514 return PyErr_Format( PyExc_RuntimeError, "too many arguments"); | 525 return PyErr_Format( PyExc_RuntimeError, "too many arguments"); |
515 | 526 |
516 if (ch == '\0') | 527 if (ch == '\0') |
517 return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); | 528 return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); |
518 | |
519 | 529 |
520 ch = *++sig_ptr; | 530 ch = *++sig_ptr; |
521 switch(ch) | 531 switch(ch) |
522 { | 532 { |
523 // every line creates a new reference passed back to python | 533 // every line creates a new reference passed back to python |
538 case DC_SIGCHAR_STRING: return Py_BuildValue("s", dcCallPointer (gpCall, pfunc)); // !new ref! | 548 case DC_SIGCHAR_STRING: return Py_BuildValue("s", dcCallPointer (gpCall, pfunc)); // !new ref! |
539 case DC_SIGCHAR_POINTER: return Py_BuildValue("n", dcCallPointer (gpCall, pfunc)); // !new ref! | 549 case DC_SIGCHAR_POINTER: return Py_BuildValue("n", dcCallPointer (gpCall, pfunc)); // !new ref! |
540 default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature"); | 550 default: return PyErr_Format(PyExc_RuntimeError, "invalid return type signature"); |
541 // @@@ 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 | 551 // @@@ 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 |
542 } | 552 } |
543 | |
544 #if !defined(PYUNICODE_CACHES_UTF8) | |
545 Py_XDECREF(sig_obj); | |
546 #endif | |
547 } | 553 } |
548 | 554 |
549 | 555 |
550 static PyObject* | 556 static PyObject* |
551 pydc_call(PyObject* self, PyObject* args) | 557 pydc_call(PyObject* self, PyObject* args) |
654 py2dcshort(&result->s, po, ch == DC_SIGCHAR_USHORT, -1); | 660 py2dcshort(&result->s, po, ch == DC_SIGCHAR_USHORT, -1); |
655 break; | 661 break; |
656 | 662 |
657 case DC_SIGCHAR_INT: | 663 case DC_SIGCHAR_INT: |
658 case DC_SIGCHAR_UINT: | 664 case DC_SIGCHAR_UINT: |
659 if ( !DcPyInt_Check(po) ) | 665 py2dcint(&result->i, po, ch == DC_SIGCHAR_UINT, -1); |
660 PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", -1 ); | |
661 else | |
662 result->i = (DCint) DcPyInt_AS_LONG(po); | |
663 break; | |
664 | 666 |
665 case DC_SIGCHAR_LONG: | 667 case DC_SIGCHAR_LONG: |
666 case DC_SIGCHAR_ULONG: | 668 case DC_SIGCHAR_ULONG: |
667 if ( !DcPyInt_Check(po) ) | 669 py2dclong(&result->j, po, ch == DC_SIGCHAR_ULONG, -1); |
668 PyErr_Format( PyExc_RuntimeError, "arg %d - expecting an int", -1 ); | |
669 else | |
670 result->j = (DClong) PyLong_AsLong(po); | |
671 break; | 670 break; |
672 | 671 |
673 case DC_SIGCHAR_LONGLONG: | 672 case DC_SIGCHAR_LONGLONG: |
674 case DC_SIGCHAR_ULONGLONG: | 673 case DC_SIGCHAR_ULONGLONG: |
675 py2dclonglong(&result->l, po, -1); | 674 py2dclonglong(&result->l, po, ch == DC_SIGCHAR_ULONGLONG, -1); |
676 break; | 675 break; |
677 | 676 |
678 case DC_SIGCHAR_FLOAT: | 677 case DC_SIGCHAR_FLOAT: |
679 if (!PyFloat_Check(po)) | 678 if (!PyFloat_Check(po)) |
680 PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a float", -1 ); | 679 PyErr_Format( PyExc_RuntimeError, "arg %d - expecting a float", -1 ); |