Handle NUL-byte keys in get_multi
Thanks to Ormod for finding, reporting and drilling down the bug.
This commit is contained in:
parent
212a69e09f
commit
02c7681ff2
@ -1200,29 +1200,38 @@ static PyObject *PylibMC_Client_get_multi(
|
|||||||
retval = PyDict_New();
|
retval = PyDict_New();
|
||||||
|
|
||||||
for (i = 0; i < nresults; i++) {
|
for (i = 0; i < nresults; i++) {
|
||||||
PyObject *val;
|
PyObject *val, *key_obj;
|
||||||
|
int rc;
|
||||||
|
|
||||||
res = results + i;
|
res = results + i;
|
||||||
|
|
||||||
/* This is safe because libmemcached's max key length
|
/* Explicitly construct a key string object so that NUL-bytes and the
|
||||||
* includes space for a NUL-byte. */
|
* likes can be contained within the keys (this is possible in the
|
||||||
res->key[res->key_len] = '\0';
|
* 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,
|
val = _PylibMC_parse_memcached_value(res->value, res->value_len,
|
||||||
res->flags);
|
res->flags);
|
||||||
if (val == NULL) {
|
if (val == NULL)
|
||||||
/* PylibMC_parse_memcached_value raises the exception on its own */
|
goto unpack_error;
|
||||||
Py_DECREF(retval);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDict_SetItemString(retval, res->key + prefix_len, val);
|
rc = PyDict_SetItem(retval, key_obj, val);
|
||||||
|
Py_DECREF(key_obj);
|
||||||
Py_DECREF(val);
|
Py_DECREF(val);
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (rc != 0)
|
||||||
/* only PyDict_SetItemString can incur this one */
|
goto unpack_error;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unpack_error:
|
||||||
Py_DECREF(retval);
|
Py_DECREF(retval);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
earlybird:
|
earlybird:
|
||||||
PyMem_Free(key_lens);
|
PyMem_Free(key_lens);
|
||||||
|
9
tests.py
9
tests.py
@ -1,4 +1,4 @@
|
|||||||
"""Tests. They want YOU!!
|
r"""Tests. They want YOU!!
|
||||||
|
|
||||||
|
|
||||||
Basic functionality.
|
Basic functionality.
|
||||||
@ -245,6 +245,13 @@ Python-wrapped behaviors dict
|
|||||||
'fnv1a_32'
|
'fnv1a_32'
|
||||||
>>> super(pylibmc.Client, pc).get_behaviors()["hash"]
|
>>> super(pylibmc.Client, pc).get_behaviors()["hash"]
|
||||||
6
|
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.
|
# Used to test pickling.
|
||||||
|
Reference in New Issue
Block a user