Handle NUL-byte keys in get_multi

Thanks to Ormod for finding, reporting and drilling down the bug.
int
lericson 2010-05-27 14:26:24 +02:00
parent 212a69e09f
commit 02c7681ff2
2 changed files with 30 additions and 14 deletions

View File

@ -1200,28 +1200,37 @@ static PyObject *PylibMC_Client_get_multi(
retval = PyDict_New();
for (i = 0; i < nresults; i++) {
PyObject *val;
PyObject *val, *key_obj;
int rc;
res = results + i;
/* This is safe because libmemcached's max key length
* includes space for a NUL-byte. */
res->key[res->key_len] = '\0';
/* Explicitly construct a key string object so that NUL-bytes and the
* likes can be contained within the keys (this is possible in the
* binary protocol.) */
key_obj = PyString_FromStringAndSize(res->key + prefix_len,
res->key_len - prefix_len);
if (key_obj == NULL)
goto unpack_error;
/* Parse out value */
val = _PylibMC_parse_memcached_value(res->value, res->value_len,
res->flags);
if (val == NULL) {
/* PylibMC_parse_memcached_value raises the exception on its own */
Py_DECREF(retval);
break;
}
if (val == NULL)
goto unpack_error;
PyDict_SetItemString(retval, res->key + prefix_len, val);
rc = PyDict_SetItem(retval, key_obj, val);
Py_DECREF(key_obj);
Py_DECREF(val);
if (PyErr_Occurred()) {
/* only PyDict_SetItemString can incur this one */
if (rc != 0)
goto unpack_error;
continue;
unpack_error:
Py_DECREF(retval);
break;
}
}
earlybird:

View File

@ -1,4 +1,4 @@
"""Tests. They want YOU!!
r"""Tests. They want YOU!!
Basic functionality.
@ -245,6 +245,13 @@ Python-wrapped behaviors dict
'fnv1a_32'
>>> super(pylibmc.Client, pc).get_behaviors()["hash"]
6
Ormod's Zero-byte Adventure Story
>>> bc = _pylibmc.client([test_server], binary=True)
>>> bc.set("\0\0", "ORMOD")
True
>>> bc.get_multi(["\0\0"])
{'\x00\x00': 'ORMOD'}
"""
# Used to test pickling.