-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
ctypes.Structure does not set value of fields #102844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
According to
I don't think you are using it correctly. |
As the documentation very clearly states for bit fields
I have adhered to this. Also referring to your point:
I have ensured to follow the guidelines laid out in the documentation. There is also a SO thread regarding this same issue by me. And according to this answer, it seems to be an issue with how the interpreter is working with the structure definition, and not an ill-formed program. |
Sorry I was wrong about the bitfield support :( I took a look at the bitfield code, and it's never gonna work. The code is fundamentally wrong. For a quick example: static PyObject *
b_get(void *ptr, Py_ssize_t size)
{
signed char val = *(signed char *)ptr;
GET_BITFIELD(val, size);
return PyLong_FromLong(val);
} This is the code trying to get a "byte" from a buffer with an offset. The way the current code does it is to cast the pointer to the value container first(which will truncate the actual data needed if It seems like in #97588 @matthiasgoergens is trying on some new implementation? If it solves the issue, then let's just wait for it. |
It took me some effort to come across these issues, initially first scouring https://bugs.python.org, which gave me the same revelation as it did you. I hope @matthiasgoergens PR is accepted soon, but considering that the last version it will be backported to is 3.11, this is another area I would need some help. Is there any way to compile a portable Python binary with it's dependencies (RHEL8)? Otherwise I don't think this can be utilised by me, and I will need to see how to serialize my various network protocol structs in C. Thanks for guiding me towards the solution, and thank you @matthiasgoergens for your work on this. |
I could probably backport it further. The main problem is that it breaks bug-for-but compatibility, and might thus break software that relies on the old broken behaviour. However I guess we can sidestep this problem by hiding the backports behind a feature flag? How early a version do you need? |
Our systems are offline, and I know they work with 3.8.10. Due to the remote nature, we cannot access the internet. I tried building 3.11 for these systems, but the issue was I could not package the dependencies along with, and every build listed out further dependencies to install. If there is a method to package the dependencies with Python while building, then there would not be a need for backporting, and I could just build this and try installing it. Hence my question. Otherwise if the backported 3.8 is utilised, can I just replace the binary, without adding any further files? |
You could backport to 3.10, but the releases before that (3.7-3.9) are in security-fix-only mode and so the backports won't be accepted past that. You could ask whomever packages and distributes your Python to backport the fix to their version (as, e.g., Linux distro maintainers sometimes do)—or if that's you, you could endevour to apply the patch to the 3.8 source and build that (at your own risk, of course). |
@DakshKK Can you run docker containers or VM images or so? If yes, you could build one of those with a modern Python while the internet is available, then seal it and ship it off to your offline system? If you can't do docker, you might be able to rig something manually via chroot etc. That's how docker works internally anyway. I can work with you in backporting the fixes to 3.8, but that wouldn't be an official release, of course. I don't know whether it's just one binary, or whether you'd need to replace some shared libraries or so. We'd need to investigate. |
Almost certainly not, because the ctypes code isn't in the Python interpreter binary to begin with. On Linux, the ctypes module's C code is compiled to a loadable extension module named $ ls /usr/lib64/python3.11/lib-dynload/*ctypes*
/usr/lib64/python3.11/lib-dynload/_ctypes.cpython-311d-x86_64-linux-gnu.so
/usr/lib64/python3.11/lib-dynload/_ctypes.cpython-311-x86_64-linux-gnu.so
/usr/lib64/python3.11/lib-dynload/_ctypes_test.cpython-311d-x86_64-linux-gnu.so
/usr/lib64/python3.11/lib-dynload/_ctypes_test.cpython-311-x86_64-linux-gnu.so (That's one shared object each for the debug and non-debug Python ABIs, for both Since the fix may involve both C code changes and (possibly) Python module code changes, you'd likely need some combination of a new If you're lucky, only the C code changes and you only have to worry about |
For what it's worth, I ran your test against my branch in #97702 and it seems to pass: from ctypes import Structure, c_byte, c_int, memmove, pointer, sizeof
class Demo (Structure):
_fields_ = [
('f1', c_byte, 8),
('f2', c_int, 21),
('f3', c_byte, 2),
('f4', c_byte, 1)
]
def show(d):
for (name, _, _) in d._fields_:
print(f"{name}: {getattr(d, name)}")
if __name__=='__main__':
s = Demo.from_buffer_copy(b'\x01\x0f\x00\xe0')
show(s) Result: $ ./python demo.py
f1: 1
f2: 15
f3: -1
f4: -1 |
I have been traveling and missed out on these updates, but I did build @matthiasgoergens PR on my home system and it helped me achieve what I require. I can not run VM images but maybe And I thank everyone for their patience, and help in trying to get me a solution for this. |
Bug report
I have been using bit-fields with
ctypes.Structure
.My issue is that no matter what I do, I am unable to set the values for my bitfield fields.
The structure has the following definition:
I have set the above struct using
from_buffer_copy
with a value ofb'\x01\x0f\x00\xe0'
(Binary representation of C struct, with the underneath values).This should set the following values
f1
: 1f2
: 15f3
: -1 (3, overflow makes it -1)f4
: -1 (1, overflow makes it -1)Manual setting, or
from_buffer_copy
, achieve nothing;f3
, andf4
remain 0.f3
, andf4
are both supposed to be -1.Please let me understand if there is supposed to be some special configuration or what the issue is.
Your environment
The text was updated successfully, but these errors were encountered: