Counter-intuitive behavior when using string_at with a c_char_p type.
JT Olds <[email protected]> Wed, 1 Aug 2012 23:07:39 -0600
| Newsgroups | gmane.comp.python.ctypes |
|---|---|
| Message-ID | <CAPTS6cV0LSgq-isptgnkE87Js2XiF3UaJNmz+2b2Qey7H+Y+yg@mail.gmail.com> |
Hey all,
I can't decide if this is a bug or what, but this is very definitely
surprising behavior to me. Basically, if the restype of a C method is
c_char_p instead of c_void_p, even if you don't want null-terminated
strings you get it. Yay!
Given the following program:
import ctypes
import ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library('c'))
libc.memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
libc.memcpy.restype = ctypes.c_char_p
value = "\x01\x00\x01\x02\x03"
out = ctypes.create_string_buffer(len(value))
out = libc.memcpy(out, value, len(value))
out = ctypes.string_at(out, len(value))
assert len(out) == len(value)
assert out == value
Note that only the second assertion fails. Both assertions will
succeed if you change libc.memcpy.restype to ctypes.c_void_p.
So what's going on here? I'm not completely sure, but everything after
the null byte gets replaced with garbage if libc.memcpy.restype is
ctypes.c_char_p.
Is this intentional? Is this a bug? It made me tear my hair out for a
few hours today. Note that both of these work:
assert value == ctypes.string_at(ctypes.cast(value,
ctypes.c_char_p), len(value))
assert value == ctypes.string_at(ctypes.cast(value,
ctypes.c_void_p), len(value))
-JT
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/