Skip to content

Commit 6acd682

Browse files
committed
Fix: c_parser ignored scopes with nameless inline struct
The `parse_type` would continue looking for tokens even when the c_type ended with a `{`. This would mean that the following resulted in an exception: ``` __struct__ = """ struct { int i; } s; """ ``` `parse_type` now ignores any following tokens if `c_type` ends with an `{` - meaning the tokens afterwards are not element of the current type scope. Signed-off-by: Sophie Tyalie <dev@flowerpot.me>
1 parent ecc321b commit 6acd682

File tree

2 files changed

+42
-35
lines changed

2 files changed

+42
-35
lines changed

cstruct/c_parser.py

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -78,43 +78,47 @@ def parse_type(tokens: Tokens, __cls__: Type['AbstractCStruct'], byte_order: Opt
7878
# signed/unsigned/struct
7979
if c_type in ['signed', 'unsigned', 'struct', 'union'] and len(tokens) > 1:
8080
c_type = c_type + " " + tokens.pop()
81-
next_token = tokens.pop()
82-
# short int, long int, or long long
83-
if next_token in ['int', 'long']:
84-
c_type = c_type + " " + next_token
85-
next_token = tokens.pop()
86-
# void *
87-
if next_token.startswith("*"):
88-
next_token = next_token[1:]
89-
c_type = 'void *'
90-
# parse length
81+
9182
vlen = 1
9283
flexible_array = False
93-
if "[" in next_token:
94-
t = next_token.split("[")
95-
if len(t) != 2:
96-
raise ParserError("Error parsing: " + next_token)
97-
next_token = t[0].strip()
98-
vlen_part = t[1]
99-
vlen_expr = []
100-
while not vlen_part.endswith("]"):
84+
85+
if not c_type.endswith("{"):
86+
next_token = tokens.pop()
87+
# short int, long int, or long long
88+
if next_token in ['int', 'long']:
89+
c_type = c_type + " " + next_token
90+
next_token = tokens.pop()
91+
# void *
92+
if next_token.startswith("*"):
93+
next_token = next_token[1:]
94+
c_type = 'void *'
95+
# parse length
96+
if "[" in next_token:
97+
t = next_token.split("[")
98+
if len(t) != 2:
99+
raise ParserError("Error parsing: " + next_token)
100+
next_token = t[0].strip()
101+
vlen_part = t[1]
102+
vlen_expr = []
103+
while not vlen_part.endswith("]"):
104+
vlen_expr.append(vlen_part.split("]")[0].strip())
105+
vlen_part = tokens.pop()
106+
t_vlen = vlen_part.split("]")[0].strip()
101107
vlen_expr.append(vlen_part.split("]")[0].strip())
102-
vlen_part = tokens.pop()
103-
t_vlen = vlen_part.split("]")[0].strip()
104-
vlen_expr.append(vlen_part.split("]")[0].strip())
105-
t_vlen = " ".join(vlen_expr)
106-
if not t_vlen:
107-
flexible_array = True
108-
vlen = 0
109-
else:
110-
try:
111-
vlen = c_eval(t_vlen)
112-
except (ValueError, TypeError):
113-
vlen = int(t_vlen)
114-
tokens.push(next_token)
115-
# resolve typedefs
116-
while c_type in TYPEDEFS:
117-
c_type = TYPEDEFS[c_type]
108+
t_vlen = " ".join(vlen_expr)
109+
if not t_vlen:
110+
flexible_array = True
111+
vlen = 0
112+
else:
113+
try:
114+
vlen = c_eval(t_vlen)
115+
except (ValueError, TypeError):
116+
vlen = int(t_vlen)
117+
tokens.push(next_token)
118+
# resolve typedefs
119+
while c_type in TYPEDEFS:
120+
c_type = TYPEDEFS[c_type]
121+
118122
# calculate fmt
119123
if c_type.startswith('struct ') or c_type.startswith('union '): # struct/union
120124
c_type, tail = c_type.split(' ', 1)

tests/test_cstruct.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ class MBR(cstruct.CStruct):
7575
class Dummy(cstruct.CStruct):
7676
__byte_order__ = cstruct.LITTLE_ENDIAN
7777
__def__ = """
78+
struct {
7879
struct {
80+
int i;
81+
} s;
7982
char c;
8083
char vc[10];
81-
int i;
8284
int vi[10];
8385
long long l;
8486
long vl[10];
@@ -210,6 +212,7 @@ def test_inline():
210212

211213
def test_dummy():
212214
dummy = Dummy()
215+
213216
dummy.c = b'A'
214217
dummy.vc = b'ABCDEFGHIJ'
215218
dummy.i = 123456

0 commit comments

Comments
 (0)