Ah you've got a good catch there, browsing the docs cffi does support variadic function calls https://cffi.readthedocs.org/en/release-0.8/#variadic-function-calls
I'll study this after work tonight, I'm sure we can address the issue. As for the null char in the middle of a received string, I'll have to think about that one. I'm open to suggestions. -Michel On Fri, Jan 17, 2014 at 12:55 PM, Greg Ward <[email protected]> wrote: > On 17 January 2014, Michel Pelletier said: > > zstr however is how you turn messages into strings. It is not an > > implementation of a string type. It is critical to the functionality of > > pyczmq (assuming you want string output from the library). > > I was going to start another thread about this... but what the hell, > as long as it came up, here are the two problems I've spotted with > pyczmq.zstr.send(). > > 1. zstr_send() is printf()-style, pyczmq.zstr.send() is not > ----------------------------------------------------------- > > The C API for zstr_send() is > > zstr_send(void *zocket, const char *format, ...) > > which means calling it like > > char *data = [...get a string from somewhere...] > zstr_send(mysocket, data); > > is wrong, because 'data' might happen to contain a "%s" or "%d" by > chance. Presumably the innards of zstr_send() will look for further > args on the stack, find gibberish, and send gibberish over the wire. > Or crash. The right way to do this in C is > > zstr_send(mysocket, "%s", data); > > But the corresponding Python function is > > def send(sock, string): > return C.zstr_send(sock, string) > > so if 'string' happens to contain "%s" or "%d", bad stuff happens. But > since pyczmq.zstr.send() doesn't expose a format string, there's no > way to do the right thing. > > Here's an example: > > $ cat zstr-bug1.py > from pyczmq import zmq, zctx, zsocket, zstr > > ctx = zctx.new() > rep = zsocket.new(ctx, zmq.REP) > zsocket.bind(rep, "tcp://127.0.0.1:5253") > > req = zsocket.new(ctx, zmq.REQ) > zsocket.connect(req, "tcp://127.0.0.1:5253") > > out_data = "blah blah hey what is %s doing here?" > zstr.send(req, out_data) > > in_data = zstr.recv(rep) > assert in_data == out_data, "expected %r, got %r" % (out_data, in_data) > > $ python zstr-bug1.py > zsh: segmentation fault (core dumped) python zstr-bug1.py > > Here are the innermost stack frames from that segfault: > > """ > #0 0x00007f3c06a4bf90 in _IO_vfprintf_internal (s=s@entry=0x7fffd8435470, > format=<optimized out>, > format@entry=0x7f3c07124fa4 "blah blah hey what is %s doing here?", > ap=ap@entry=0x7fffd84355e8) at vfprintf.c:1655 > #1 0x00007f3c06b0f6c0 in ___vsnprintf_chk ( > s=s@entry=0x1120750 "blah blah hey what is ", maxlen=<optimized out>, > maxlen@entry=256, flags=flags@entry=1, slen=slen@entry=256, > format=format@entry=0x7f3c07124fa4 "blah blah hey what is %s doing > here?", > args=args@entry=0x7fffd84355e8) at vsnprintf_chk.c:63 > #2 0x00007f3c04af0d1b in vsnprintf (__ap=0x7fffd84355e8, > __fmt=0x7f3c07124fa4 "blah blah hey what is %s doing here?", __n=256, > __s=0x1120750 "blah blah hey what is ") > at /usr/include/x86_64-linux-gnu/bits/stdio2.h:77 > #3 zsys_vprintf ( > format=0x7f3c07124fa4 "blah blah hey what is %s doing here?", > argptr=argptr@entry=0x7fffd8435638) at zsys.c:386 > #4 0x00007f3c04af0499 in zstr_send (zocket=0x11c2d30, format=<optimized > out>) > at zstr.c:112 > #5 0x00007f3c05521adc in ffi_call_unix64 () > from /usr/lib/x86_64-linux-gnu/libffi.so.6 > """ > > 2. zstr_send() is not binary safe > --------------------------------- > > The fact that CZMQ's zstr_send() is not binary safe is just fine: it > says right in the docs that it's a convenience for sending C strings > around. So the fact that pyczmq.zstr.send() is not binary safe is not > surprising (although it is annoying -- I'm used to Python strings, not > C strings). But since you say it's "critical to the functionality of > pyczmq", maybe I should worry about it. Anyways, here's an example: > > $ cat zstr-bug2.py > from pyczmq import zmq, zctx, zsocket, zstr > > ctx = zctx.new() > rep = zsocket.new(ctx, zmq.REP) > zsocket.bind(rep, "tcp://127.0.0.1:5253") > > req = zsocket.new(ctx, zmq.REQ) > zsocket.connect(req, "tcp://127.0.0.1:5253") > > out_data = "blah blah hey what is \0 doing here?" > zstr.send(req, out_data) > > in_data = zstr.recv(rep) > assert in_data == out_data, "expected %r, got %r" % (out_data, in_data) > > $ python zstr-bug2.py > Traceback (most recent call last): > File "zstr-bug2.py", line 14, in <module> > assert in_data == out_data, "expected %r, got %r" % (out_data, > in_data) > AssertionError: expected 'blah blah hey what is \x00 doing here?', got > 'blah blah hey what is ' > > So: until I get to the point of needing secure authentication, pyczmq > just gets in my way and makes life harder. Darn. > > Greg > _______________________________________________ > zeromq-dev mailing list > [email protected] > http://lists.zeromq.org/mailman/listinfo/zeromq-dev >
_______________________________________________ zeromq-dev mailing list [email protected] http://lists.zeromq.org/mailman/listinfo/zeromq-dev
