Compare commits

...

4 Commits
master ... v2.5

Author SHA1 Message Date
behackett
1c0596b86e BUMP 2.5.2 2013-06-01 10:07:33 -07:00
behackett
94520a7197 Changelog for 2.5.2. 2013-06-01 08:48:46 -07:00
Bernie Hackett
7395ce72bf Fix import when _cbson unavailable PYTHON-532
This ensures that we don't import _cmessage in
an incomplete state or segfault if _cbson isn't
available. If _cbson.so has been removed we fall
back to pure python.
2013-05-31 14:12:45 -07:00
A. Jesse Jiryu Davis
a060c15ef8 Fix null pointer when decoding invalid DBRef PYTHON-532 2013-05-31 10:17:46 -04:00
7 changed files with 72 additions and 25 deletions

View File

@ -150,7 +150,7 @@ def _get_object(data, position, as_class, tz_aware, uuid_subtype):
object = _elements_to_dict(encoded, as_class, tz_aware, uuid_subtype) object = _elements_to_dict(encoded, as_class, tz_aware, uuid_subtype)
position += obj_size position += obj_size
if "$ref" in object: if "$ref" in object:
return (DBRef(object.pop("$ref"), object.pop("$id"), return (DBRef(object.pop("$ref"), object.pop("$id", None),
object.pop("$db", None), object), position) object.pop("$db", None), object), position)
return object, position return object, position

View File

@ -1202,8 +1202,14 @@ static PyObject* get_value(PyObject* self, const char* buffer, int* position,
Py_INCREF(collection); Py_INCREF(collection);
PyDict_DelItemString(value, "$ref"); PyDict_DelItemString(value, "$ref");
Py_INCREF(id);
PyDict_DelItemString(value, "$id"); if (id == NULL) {
id = Py_None;
Py_INCREF(id);
} else {
Py_INCREF(id);
PyDict_DelItemString(value, "$id");
}
if (database == NULL) { if (database == NULL) {
database = Py_None; database = Py_None;

View File

@ -1,6 +1,20 @@
Changelog Changelog
========= =========
Changes in Version 2.5.2
------------------------
Version 2.5.2 fixes a NULL pointer dereference issue when decoding
an invalid :class:`~bson.dbref.DBRef`.
Issues Resolved
...............
See the `PyMongo 2.5.2 release notes in JIRA`_ for the list of resolved issues
in this release.
.. _PyMongo 2.5.2 release notes in JIRA: https://jira.mongodb.org/browse/PYTHON/fixforversion/12581
Changes in Version 2.5.1 Changes in Version 2.5.1
------------------------ ------------------------

View File

@ -67,7 +67,7 @@ SLOW_ONLY = 1
ALL = 2 ALL = 2
"""Profile all operations.""" """Profile all operations."""
version_tuple = (2, 5, 1) version_tuple = (2, 5, 2)
def get_version_string(): def get_version_string():
if isinstance(version_tuple[-1], basestring): if isinstance(version_tuple[-1], basestring):

View File

@ -551,37 +551,25 @@ PyMODINIT_FUNC
init_cmessage(void) init_cmessage(void)
#endif #endif
{ {
PyObject *m; PyObject *_cbson;
PyObject *c_api_object; PyObject *c_api_object;
PyObject *m;
struct module_state *state; struct module_state *state;
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule("_cmessage", _CMessageMethods);
#endif
if (m == NULL) {
INITERROR;
}
state = GETSTATE(m);
/* Store a reference to the _cbson module since it's needed to call some /* Store a reference to the _cbson module since it's needed to call some
* of its functions * of its functions
*/ */
state->_cbson = PyImport_ImportModule("bson._cbson"); _cbson = PyImport_ImportModule("bson._cbson");
if (state->_cbson == NULL) { if (_cbson == NULL) {
Py_DECREF(m);
INITERROR; INITERROR;
} }
/* Import C API of _cbson /* Import C API of _cbson
* The header file accesses _cbson_API to call the functions * The header file accesses _cbson_API to call the functions
*/ */
c_api_object = PyObject_GetAttrString(state->_cbson, "_C_API"); c_api_object = PyObject_GetAttrString(_cbson, "_C_API");
if (c_api_object == NULL) { if (c_api_object == NULL) {
Py_DECREF(m); Py_DECREF(_cbson);
Py_DECREF(state->_cbson);
INITERROR; INITERROR;
} }
#if PY_VERSION_HEX >= 0x03010000 #if PY_VERSION_HEX >= 0x03010000
@ -592,12 +580,25 @@ init_cmessage(void)
_cbson_API = (void **)PyCObject_AsVoidPtr(c_api_object); _cbson_API = (void **)PyCObject_AsVoidPtr(c_api_object);
#endif #endif
if (_cbson_API == NULL) { if (_cbson_API == NULL) {
Py_DECREF(m);
Py_DECREF(c_api_object); Py_DECREF(c_api_object);
Py_DECREF(state->_cbson); Py_DECREF(_cbson);
INITERROR; INITERROR;
} }
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule("_cmessage", _CMessageMethods);
#endif
if (m == NULL) {
Py_DECREF(c_api_object);
Py_DECREF(_cbson);
INITERROR;
}
state = GETSTATE(m);
state->_cbson = _cbson;
Py_DECREF(c_api_object); Py_DECREF(c_api_object);
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3

View File

@ -31,7 +31,7 @@ from distutils.errors import CCompilerError
from distutils.errors import DistutilsPlatformError, DistutilsExecError from distutils.errors import DistutilsPlatformError, DistutilsExecError
from distutils.core import Extension from distutils.core import Extension
version = "2.5.1" version = "2.5.2"
f = open("README.rst") f = open("README.rst")
try: try:

View File

@ -30,6 +30,7 @@ sys.path[0:0] = [""]
from bson.binary import Binary, UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE from bson.binary import Binary, UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE
from bson.code import Code from bson.code import Code
from bson.dbref import DBRef
from bson.objectid import ObjectId from bson.objectid import ObjectId
from bson.py3compat import b from bson.py3compat import b
from bson.son import SON from bson.son import SON
@ -1675,6 +1676,31 @@ class TestCollection(unittest.TestCase):
self.assertRaises(InvalidDocument, c.save, {"x": c}) self.assertRaises(InvalidDocument, c.save, {"x": c})
warnings.simplefilter("default") warnings.simplefilter("default")
def test_bad_dbref(self):
c = self.db.test
c.drop()
# Incomplete DBRefs.
self.assertRaises(
InvalidDocument,
c.insert, {'ref': {'$ref': 'collection'}})
self.assertRaises(
InvalidDocument,
c.insert, {'ref': {'$id': ObjectId()}})
ref_only = {'ref': {'$ref': 'collection'}}
id_only = {'ref': {'$id': ObjectId()}}
# Force insert of ref without $id.
c.insert(ref_only, check_keys=False)
self.assertEqual(DBRef('collection', id=None), c.find_one()['ref'])
c.drop()
# DBRef without $ref is decoded as normal subdocument.
c.insert(id_only, check_keys=False)
self.assertEqual(id_only, c.find_one())
def test_as_class(self): def test_as_class(self):
c = self.db.test c = self.db.test
c.drop() c.drop()