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 );