Skip to content

Commit 364a13f

Browse files
committed
fix nested anonymous union offset
1 parent bd3ff53 commit 364a13f

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

cstruct/c_parser.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,10 @@ def parse_struct(
426426
for nested_field_name, nested_field_type in field_type.ref.__fields_types__.items():
427427
if nested_field_name in fields_types:
428428
raise ParserError(f"Duplicate member `{nested_field_name}`")
429+
# set the corret offset
430+
nested_field_type = nested_field_type.copy()
431+
nested_field_type.base_offset = offset + nested_field_type.base_offset
432+
nested_field_type.offset = offset + nested_field_type.offset
429433
fields_types[nested_field_name] = nested_field_type
430434
vname = f"__anonymous{anonymous}"
431435
anonymous += 1

tests/test_nested.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,69 @@ def test_nested_struct_offset():
259259
assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333'
260260
assert o.u1.pack() == b'\xe6\x07\x00\x00'
261261
assert o.aaa.pack() == b'3333'
262+
263+
264+
def test_nested_anonymous_struct_offset():
265+
cstruct.parse(
266+
"""
267+
struct op_a1 {
268+
int a;
269+
};
270+
271+
struct op_b1 {
272+
char a;
273+
char b;
274+
char c;
275+
};
276+
""",
277+
__byte_order__=cstruct.LITTLE_ENDIAN,
278+
)
279+
280+
Opu = cstruct.parse(
281+
"""
282+
struct opu {
283+
char preamble[10];
284+
uint64_t magic;
285+
union {
286+
struct op_a1 a_op;
287+
struct op_b1 b_op;
288+
};
289+
struct op_a aaa;
290+
};
291+
""",
292+
__byte_order__=cstruct.LITTLE_ENDIAN,
293+
)
294+
295+
o = Opu()
296+
o.preamble = b'ciao_ciao'
297+
o.magic = 3771778641802345472
298+
o.__anonymous0.a_op.a = 2022
299+
o.aaa.a = 0x33333333
300+
assert o.__anonymous0.b_op.a == b'\xe6'
301+
assert o.__anonymous0.b_op.b == b'\x07'
302+
assert o.__anonymous0.b_op.c == b'\x00'
303+
assert o.__base__ == 0
304+
assert o.__anonymous0.__base__ >= 10
305+
assert o.__anonymous0.__base__ == o.__anonymous0.a_op.__base__
306+
assert o.__anonymous0.__base__ == o.__anonymous0.b_op.__base__
307+
assert o.aaa.__base__ > o.__anonymous0.__base__
308+
assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333'
309+
assert o.__anonymous0.pack() == b'\xe6\x07\x00\x00'
310+
assert o.aaa.pack() == b'3333'
311+
312+
o = Opu()
313+
o.preamble = b'ciao_ciao'
314+
o.magic = 3771778641802345472
315+
o.a_op.a = 2022
316+
o.aaa.a = 0x33333333
317+
assert o.b_op.a == b'\xe6'
318+
assert o.b_op.b == b'\x07'
319+
assert o.b_op.c == b'\x00'
320+
assert o.__base__ == 0
321+
assert o.__anonymous0.__base__ >= 10
322+
assert o.__anonymous0.__base__ == o.a_op.__base__
323+
assert o.__anonymous0.__base__ == o.b_op.__base__
324+
assert o.aaa.__base__ > o.__base__
325+
assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333'
326+
assert o.a_op.pack() == b'\xe6\x07\x00\x00'
327+
assert o.aaa.pack() == b'3333'

0 commit comments

Comments
 (0)