From c45c6706234d5fb6e28f72e27dad7a9a23ad1c98 Mon Sep 17 00:00:00 2001 From: Cervenka Dusan Date: Fri, 20 Dec 2019 08:29:51 +0100 Subject: [PATCH] Fixed VLA/VSA for all types. Null termination removed. --- dissect/cstruct/cstruct.py | 40 ++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/dissect/cstruct/cstruct.py b/dissect/cstruct/cstruct.py index 3314e40..5c24ccd 100644 --- a/dissect/cstruct/cstruct.py +++ b/dissect/cstruct/cstruct.py @@ -985,7 +985,7 @@ class Array(BaseType): When using the default C-style parser, the following syntax is supported: x[3] -> 3 -> static length. - x[] -> None -> null-terminated. + x[] -> None -> length based on data buf length (to the end of buffer) (VLA/VSA). x[expr] -> expr -> dynamic length. """ @@ -1522,14 +1522,30 @@ def gen_struct_class(self, structure): num = 'max(0, Expression(self.cstruct, "{expr}").evaluate(r))'.format( expr=num.expr ) - - struct_read += ( - 'r["{name}"] = []\n' - 'for _ in xrange({num}):\n' - ' r["{name}"].append(self.cstruct.{struct_name}._read(stream))\n'.format( - name=field.name, num=num, struct_name=ft.type.name + if ft.dynamic: #To the end of buffer + struct_read += ( + 'r["{name}"] = []\n' + 'while True:\n' + ' bufSize = stream.getbuffer().nbytes\n' + ' bufPos = stream.tell()\n' + ' try:' + ' a = self.cstruct.{struct_name}._read(stream)\n' + ' except:\n' + ' if bufSize == bufPos:\n' + ' break;\n' + ' raise EOFError()\n' + ' r["{name}"].append(a)\n'.format( + name=field.name, num=num, struct_name=ft.type.name + ) + ) + else: + struct_read += ( + 'r["{name}"] = []\n' + 'for _ in xrange({num}):\n' + ' r["{name}"].append(self.cstruct.{struct_name}._read(stream))\n'.format( + name=field.name, num=num, struct_name=ft.type.name + ) ) - ) else: struct_read += 'r["{name}"] = self.cstruct.{struct_name}._read(stream)\n'.format( name=field.name, struct_name=ft.name @@ -1713,14 +1729,14 @@ def gen_dynamic_block(self, field): t = field.type.type reader = None - if not field.type.count: # Null terminated + if not field.type.count: #To the end of buffer if isinstance(t, PackedType): reader = ( 't = []\nwhile True:\n' ' d = stream.read({size})\n' + ' if len(d) == 0: break\n' ' if len(d) != {size}: raise EOFError()\n' ' v = struct.unpack(self.cstruct.endian + "{packchar}", d)[0]\n' - ' if v == 0: break\n' ' t.append(v)'.format(size=t.size, packchar=t.packchar) ) @@ -1738,14 +1754,14 @@ def gen_dynamic_block(self, field): if isinstance(t, WcharType): reader += ".decode('utf-16-le' if self.cstruct.endian == '<' else 'utf-16-be')" - elif isinstance(t, BytesInteger): + elif isinstance(t, BytesInteger): #To the end of buffer reader = ( 't = []\n' 'while True:\n' ' d = stream.read({size})\n' + ' if len(d) == 0: break\n' ' if len(d) != {size}: raise EOFError()\n' ' v = BytesInteger.parse(d, {size}, 1, {signed}, self.cstruct.endian)\n' - ' if v == 0: break\n' ' t.append(v)'.format(size=t.size, signed=t.signed) )