@@ -533,16 +533,19 @@ inline PyObject *parse_class(PyObject *kwargs, TypeTreeNodeObject *node, TypeTre
533533 {
534534 continue ;
535535 }
536+ if (PyObject_HasAttrString (clz, " __slots__" ))
537+ {
538+ // if __slots__ is defined, setattr for non-slots attributes will fail
539+ goto PARSE_CLASS_UNKNOWN;
540+ }
536541 PyObject *extra_value = PyDict_GetItem (kwargs, child->_clean_name ); // - borrowed ref +/- 0
537542 PyDict_SetItem (extras, child->_clean_name , extra_value); // +1
538543 PyDict_DelItem (kwargs, child->_clean_name ); // -1
539544 }
540545
541546 if (PyDict_Size (extras) == 0 )
542547 {
543- Py_DECREF (clz); // 1->0
544- clz = PyObject_GetAttrString (config->classes , " UnknownObject" ); // 0->1
545- PyDict_SetItemString (kwargs, " __node__" , (PyObject *)node);
548+ goto PARSE_CLASS_UNKNOWN;
546549 }
547550
548551 instance = PyObject_Call (clz, args, kwargs);
@@ -551,23 +554,29 @@ inline PyObject *parse_class(PyObject *kwargs, TypeTreeNodeObject *node, TypeTre
551554 pos = 0 ;
552555 while (PyDict_Next (extras, &pos, &key, &value))
553556 {
554- PyObject_GenericSetAttr (instance, key, value);
557+ if (PyObject_GenericSetAttr (instance, key, value) != 0 )
558+ {
559+ Py_DECREF (instance);
560+ goto PARSE_CLASS_UNKNOWN;
561+ }
555562 }
556- goto PARSE_CLASS_CLEANUP;
557563 }
558- PyErr_Clear ();
559-
560- // if we still failed to create an instance, fallback to UnknownObject
561- Py_DECREF (clz);
562- clz = PyObject_GetAttrString (config->classes , " UnknownObject" );
563- PyDict_SetItemString (kwargs, " __node__" , (PyObject *)node);
564- // merge extras back into kwargs
565- pos = 0 ;
566- while (PyDict_Next (extras, &pos, &key, &value))
564+ else
567565 {
568- PyDict_SetItem (kwargs, key, value);
566+ PARSE_CLASS_UNKNOWN:
567+ PyErr_Clear ();
568+ // if we still failed to create an instance, fallback to UnknownObject
569+ Py_DECREF (clz);
570+ clz = PyObject_GetAttrString (config->classes , " UnknownObject" );
571+ PyDict_SetItemString (kwargs, " __node__" , (PyObject *)node);
572+ // merge extras back into kwargs
573+ pos = 0 ;
574+ while (PyDict_Next (extras, &pos, &key, &value))
575+ {
576+ PyDict_SetItem (kwargs, key, value);
577+ }
578+ instance = PyObject_Call (clz, args, kwargs);
569579 }
570- instance = PyObject_Call (clz, args, kwargs);
571580
572581PARSE_CLASS_CLEANUP:
573582 Py_DECREF (args);
@@ -852,7 +861,7 @@ PyObject *read_typetree_value(ReaderT *reader, TypeTreeNodeObject *node, TypeTre
852861 {
853862 value = read_class<swap, true >(reader, node, config);
854863 }
855- if (!config-> as_dict )
864+ else
856865 {
857866 value = read_class<swap, false >(reader, node, config);
858867 value = parse_class (value, node, config);
0 commit comments