Beispiel #1
0
 def __init__(self, reader: StructReader):
     with StreamDetour(reader):
         self.code = opc(reader.read_byte())
         self.table: Optional[Dict[int, int]] = None
         try:
             fmt = self.OPC_ARGMAP[self.code]
         except KeyError:
             self.arguments = []
         else:
             self.arguments = list(reader.read_struct(fmt))
         if self.code == opc.newarray:
             self.arguments = [JvBaseType(reader.read_byte())]
         elif self.code in self.OPC_CONSTPOOL:
             try:
                 self.arguments[0] = self.pool[self.arguments[0] - 1]
             except (AttributeError, IndexError):
                 pass
         elif self.code == opc.lookupswitch:
             reader.byte_align(blocksize=4)
             default, npairs = reader.read_struct('LL')
             pairs = reader.read_struct(F'{npairs*2}L')
             self.table = dict(zip(*([iter(pairs)] * 2)))
             self.table[None] = default
         elif self.code == opc.tableswitch:
             reader.byte_align(blocksize=4)
             default, low, high = reader.read_struct('LLL')
             assert low <= high
             offsets = reader.read_struct(F'{high-low+1}L')
             self.table = {k + low: offset for k, offset in enumerate(offsets)}
             self.table[None] = default
         elif self.code == opc.wide:
             argop = opc(reader.get_byte())
             self.arguments = (argop, reader.u16())
             if argop == opc.iinc:
                 self.arguments += reader.i16(),
             else:
                 assert argop in (
                     opc.iload, opc.istore,
                     opc.fload, opc.fstore,
                     opc.aload, opc.astore,
                     opc.lload, opc.lstore,
                     opc.dload, opc.dstore,
                     opc.ret)
         offset = reader.tell()
     self.raw = bytes(reader.read(offset - reader.tell()))
Beispiel #2
0
    def __init__(self, reader: StructReader):
        def readint(length: int):
            return int(bytes(reader.read(length * 2)), 16)

        self.signature = reader.read(6)
        if self.signature != b'070701':
            raise ValueError('invalid CPIO header signature')
        self.inode = readint(4)
        self.mode = readint(4)
        self.uid = readint(4)
        self.gid = readint(4)
        self.nlinks = readint(4)
        mtime = readint(4)
        self.mtime = datetime.utcfromtimestamp(mtime)
        self.size = readint(4)
        self.dev = readint(4), readint(4)
        self.rdev = readint(4), readint(4)
        namesize = readint(4)
        self.checksum = readint(4)
        self.name = bytes(reader.read(namesize)).decode('ascii').rstrip('\0')
        reader.byte_align(4)
        self.data = reader.read(self.size)
        reader.byte_align(4)
Beispiel #3
0
    def process(self, data: bytearray):
        formatter = string.Formatter()
        until = self.args.until
        until = until and PythonExpression(until, all_variables_allowed=True)
        reader = StructReader(memoryview(data))
        mainspec = self.args.spec
        byteorder = mainspec[:1]
        if byteorder in '<!=@>':
            mainspec = mainspec[1:]
        else:
            byteorder = '='

        def fixorder(spec):
            if spec[0] not in '<!=@>':
                spec = byteorder + spec
            return spec

        it = itertools.count() if self.args.multi else (0, )
        for index in it:

            if reader.eof:
                break
            if index >= self.args.count:
                break

            meta = metavars(data, ghost=True)
            meta['index'] = index
            args = []
            last = None
            checkpoint = reader.tell()

            try:
                for prefix, name, spec, conversion in formatter.parse(
                        mainspec):
                    if prefix:
                        args.extend(reader.read_struct(fixorder(prefix)))
                    if name is None:
                        continue
                    if conversion:
                        reader.byte_align(
                            PythonExpression.evaluate(conversion, meta))
                    if spec:
                        spec = meta.format_str(spec, self.codec, args)
                    if spec != '':
                        try:
                            spec = PythonExpression.evaluate(spec, meta)
                        except ParserError:
                            pass
                    if spec == '':
                        last = value = reader.read()
                    elif isinstance(spec, int):
                        last = value = reader.read_bytes(spec)
                    else:
                        value = reader.read_struct(fixorder(spec))
                        if not value:
                            self.log_warn(F'field {name} was empty, ignoring.')
                            continue
                        if len(value) > 1:
                            self.log_info(
                                F'parsing field {name} produced {len(value)} items reading a tuple'
                            )
                        else:
                            value = value[0]

                    args.append(value)

                    if name == _SHARP:
                        raise ValueError(
                            'Extracting a field with name # is forbidden.')
                    elif name.isdecimal():
                        index = int(name)
                        limit = len(args) - 1
                        if index > limit:
                            self.log_warn(
                                F'cannot assign index field {name}, the highest index is {limit}'
                            )
                        else:
                            args[index] = value
                        continue
                    elif name:
                        meta[name] = value

                if until and not until(meta):
                    self.log_info(
                        F'the expression ({until}) evaluated to zero; aborting.'
                    )
                    break

                with StreamDetour(reader, checkpoint) as detour:
                    full = reader.read(detour.cursor - checkpoint)
                if last is None:
                    last = full

                outputs = []

                for template in self.args.outputs:
                    used = set()
                    outputs.append(
                        meta.format(template,
                                    self.codec, [full, *args], {_SHARP: last},
                                    True,
                                    used=used))
                    for key in used:
                        meta.pop(key, None)

                for output in outputs:
                    chunk = self.labelled(output, **meta)
                    chunk.set_next_batch(index)
                    yield chunk

            except EOF:
                leftover = repr(SizeInt(len(reader) - checkpoint)).strip()
                self.log_info(F'discarding {leftover} left in buffer')
                break