@@ -386,6 +386,23 @@ test_gc(PyObject *Py_UNUSED(module), PyObject* Py_UNUSED(ignored))
386386}
387387
388388
389+ static int
390+ check_module_attr (PyObject * module , const char * name , PyObject * expected )
391+ {
392+ PyObject * attr = PyObject_GetAttrString (module , name );
393+ if (attr == _Py_NULL ) {
394+ return -1 ;
395+ }
396+ assert (attr == expected );
397+ Py_DECREF (attr );
398+
399+ if (PyObject_DelAttrString (module , name ) < 0 ) {
400+ return -1 ;
401+ }
402+ return 0 ;
403+ }
404+
405+
389406// test PyModule_AddType()
390407static int
391408test_module_add_type (PyObject * module )
@@ -407,14 +424,7 @@ test_module_add_type(PyObject *module)
407424 ASSERT_REFCNT (Py_REFCNT (type ) == refcnt + 1 );
408425#endif
409426
410- PyObject * attr = PyObject_GetAttrString (module , type_name );
411- if (attr == _Py_NULL ) {
412- return -1 ;
413- }
414- assert (attr == _Py_CAST (PyObject * , type ));
415- Py_DECREF (attr );
416-
417- if (PyObject_DelAttrString (module , type_name ) < 0 ) {
427+ if (check_module_attr (module , type_name , _Py_CAST (PyObject * , type )) < 0 ) {
418428 return -1 ;
419429 }
420430 ASSERT_REFCNT (Py_REFCNT (type ) == refcnt );
@@ -426,30 +436,70 @@ test_module_add_type(PyObject *module)
426436static int
427437test_module_addobjectref (PyObject * module )
428438{
429- PyObject * obj = Py_True ;
430439 const char * name = "test_module_addobjectref" ;
440+ PyObject * obj = PyUnicode_FromString (name );
441+ assert (obj != NULL );
431442#ifdef CHECK_REFCNT
432443 Py_ssize_t refcnt = Py_REFCNT (obj );
433444#endif
434445
435446 if (PyModule_AddObjectRef (module , name , obj ) < 0 ) {
436447 ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt );
448+ Py_DECREF (obj );
437449 return -1 ;
438450 }
439- #ifndef IMMORTAL_OBJS
440451 ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt + 1 );
441- #endif
442452
443- if (PyObject_DelAttrString (module , name ) < 0 ) {
453+ if (check_module_attr (module , name , obj ) < 0 ) {
454+ Py_DECREF (obj );
444455 return -1 ;
445456 }
446457 ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt );
447458
448459 // PyModule_AddObjectRef() with value=NULL must not crash
460+ assert (!PyErr_Occurred ());
449461 int res = PyModule_AddObjectRef (module , name , _Py_NULL );
450462 assert (res < 0 );
463+ assert (PyErr_ExceptionMatches (PyExc_SystemError ));
464+ PyErr_Clear ();
465+
466+ Py_DECREF (obj );
467+ return 0 ;
468+ }
469+
470+
471+ // test PyModule_Add()
472+ static int
473+ test_module_add (PyObject * module )
474+ {
475+ const char * name = "test_module_add" ;
476+ PyObject * obj = PyUnicode_FromString (name );
477+ assert (obj != NULL );
478+ #ifdef CHECK_REFCNT
479+ Py_ssize_t refcnt = Py_REFCNT (obj );
480+ #endif
481+
482+ if (PyModule_Add (module , name , Py_NewRef (obj )) < 0 ) {
483+ ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt );
484+ Py_DECREF (obj );
485+ return -1 ;
486+ }
487+ ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt + 1 );
488+
489+ if (check_module_attr (module , name , obj ) < 0 ) {
490+ Py_DECREF (obj );
491+ return -1 ;
492+ }
493+ ASSERT_REFCNT (Py_REFCNT (obj ) == refcnt );
494+
495+ // PyModule_Add() with value=NULL must not crash
496+ assert (!PyErr_Occurred ());
497+ int res = PyModule_Add (module , name , _Py_NULL );
498+ assert (res < 0 );
499+ assert (PyErr_ExceptionMatches (PyExc_SystemError ));
451500 PyErr_Clear ();
452501
502+ Py_DECREF (obj );
453503 return 0 ;
454504}
455505
@@ -458,18 +508,20 @@ static PyObject *
458508test_module (PyObject * Py_UNUSED (module ), PyObject * Py_UNUSED (ignored ))
459509{
460510 PyObject * module = PyImport_ImportModule ("sys" );
461- if (module == _Py_NULL ) {
462- return _Py_NULL ;
511+ if (module == NULL ) {
512+ return NULL ;
463513 }
464514 assert (PyModule_Check (module ));
465515
466516 if (test_module_add_type (module ) < 0 ) {
467517 goto error ;
468518 }
469-
470519 if (test_module_addobjectref (module ) < 0 ) {
471520 goto error ;
472521 }
522+ if (test_module_add (module ) < 0 ) {
523+ goto error ;
524+ }
473525
474526 Py_DECREF (module );
475527 Py_RETURN_NONE ;
0 commit comments