Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
3.4.6, 3.5.0
-
None
-
FreeBSD
Description
In python if we ask zookeeper.get (which translates into pyzoo_get) for empty node we can get trash in result on Python level. Issue is pretty tricky. It goes like this:
- python C extension allocates buffer with malloc buffer = malloc(sizeof(char)*buffer_len); and calls zoo_wget providing both buffer and buffer_len.
- deserialize_GetDataResponse deserializes empty buffer and sets buffer_len to -1 and zoo_wget returns.
- python C extension calls Py_BuildValue( "(s#,N)", buffer,buffer_len ... with buffer_len set to -1.
- Py_BuildValue calls do_mkvalue to build python string which falls back to strlen(str) in case string length (buffer_len < 0) - that's our case.
- usually strlen returns 0, because e.g. linux uses magic zero filled page as result of mmap (which is being copied upon page fault, i.e. when you want to write to it)
- everything works!
But on FreeBSD (not always) we can get random data in malloc result and this trash will be exposed to the user.
Not sure about the right way to fix this, but something like
Index: src/contrib/zkpython/src/c/zookeeper.c =================================================================== --- src/contrib/zkpython/src/c/zookeeper.c (revision 1583238) +++ src/contrib/zkpython/src/c/zookeeper.c (working copy) @@ -1223,7 +1223,7 @@ } PyObject *stat_dict = build_stat( &stat ); - PyObject *ret = Py_BuildValue( "(s#,N)", buffer,buffer_len, stat_dict ); + PyObject *ret = Py_BuildValue( "(s#,N)", buffer,buffer_len < 0 ? 0 : buffer_len, stat_dict ); free(buffer); return ret;
should do the trick