@@ -554,33 +554,40 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
554554 unsigned char check_keys ,
555555 unsigned char uuid_subtype ) {
556556 struct module_state * state = GETSTATE (self );
557+ PyObject * type_marker = NULL ;
557558
558559 /*
559560 * Don't use PyObject_IsInstance for our custom types. It causes
560561 * problems with python sub interpreters. Our custom types should
561562 * have a _type_marker attribute, which we can switch on instead.
562563 */
563564 if (PyObject_HasAttrString (value , "_type_marker" )) {
564- long type ;
565- PyObject * type_marker = PyObject_GetAttrString (value , "_type_marker" );
566- if (type_marker == NULL )
565+ type_marker = PyObject_GetAttrString (value , "_type_marker" );
566+ if (type_marker == NULL ) {
567567 return 0 ;
568+ }
569+ }
570+ /*
571+ * Python objects with broken __getattr__ implementations could return
572+ * arbitrary types for a call to PyObject_GetAttrString. For example
573+ * pymongo.database.Database returns a new Collection instance for
574+ * __getattr__ calls with names that don't match an existing attribute
575+ * or method. In some cases "value" could be a subtype of something
576+ * we know how to serialize. Make a best effort to encode these types.
577+ */
568578#if PY_MAJOR_VERSION >= 3
569- type = PyLong_AsLong (type_marker );
579+ if (type_marker && PyLong_CheckExact (type_marker )) {
580+ long type = PyLong_AsLong (type_marker );
570581#else
571- type = PyInt_AsLong (type_marker );
582+ if (type_marker && PyInt_CheckExact (type_marker )) {
583+ long type = PyInt_AsLong (type_marker );
572584#endif
573585 Py_DECREF (type_marker );
574586 /*
575587 * Py(Long|Int)_AsLong returns -1 for error but -1 is a valid value
576588 * so we call PyErr_Occurred to differentiate.
577- *
578- * One potential reason for an error is the user passing an invalid
579- * type that overrides __getattr__ (e.g. pymongo.collection.Collection)
580589 */
581590 if (type == -1 && PyErr_Occurred ()) {
582- PyErr_Clear ();
583- _set_cannot_encode (value );
584591 return 0 ;
585592 }
586593 switch (type ) {
@@ -792,6 +799,8 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
792799 return 1 ;
793800 }
794801 }
802+ } else {
803+ Py_XDECREF (type_marker );
795804 }
796805
797806 /* No _type_marker attibute or not one of our types. */
0 commit comments