示例#1
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__pack_data(self):
		"""Pack the nested field
		"""
		if self._pfp__pack_type is None:
			return

		tmp_stream = six.BytesIO()
		self._._pfp__build(bitwrap.BitwrappedStream(tmp_stream))
		raw_data = tmp_stream.getvalue()

		unpack_func = self._pfp__packer
		unpack_args = []
		if self._pfp__packer is not None:
			unpack_func = self._pfp__packer
			unpack_args = [true(), raw_data]
		elif self._pfp__pack is not None:
			unpack_func = self._pfp__pack
			unpack_args = [raw_data]

		# does not need to be converted to a char array
		if not isinstance(unpack_func, functions.NativeFunction):
			io_stream = bitwrap.BitwrappedStream(six.BytesIO(raw_data))
			unpack_args[-1] = Array(len(raw_data), Char, io_stream)

		res = unpack_func.call(unpack_args, *self._pfp__pack_func_call_info, no_cast=True)
		if isinstance(res, Array):
			res = res._pfp__build()

		io_stream = six.BytesIO(res)
		tmp_stream = bitwrap.BitwrappedStream(io_stream)

		self._pfp__no_unpack = True
		self._pfp__parse(tmp_stream)
		self._pfp__no_unpack = False
示例#2
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__build(self, stream=None, save_offset=False):
		if stream is None:
			io_stream = six.BytesIO()
			tmp_stream = bitwrap.BitwrappedStream(io_stream)
			tmp_stream.padded = self._pfp__interp.get_bitfield_padded()
			super(Dom, self)._pfp__build(tmp_stream, save_offset=save_offset)

			# flush out any unaligned bitfields, etc
			tmp_stream.flush()
			res = io_stream.getvalue()
			return res
		else:
			if not isinstance(stream, bitwrap.BitwrappedStream):
				stream = bitwrap.BitwrappedStream(stream)
			return super(Dom, self)._pfp__build(stream, save_offset=save_offset)
示例#3
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__build(self, stream=None, save_offset=False):
		"""Build the union and write the result into the stream.

		:stream: None
		:returns: None
		"""
		max_size = -1
		if stream is None:
			core_stream = six.BytesIO()
			new_stream = bitwrap.BitwrappedStream(core_stream)
		else:
			new_stream = stream

		for child in self._pfp__children:
			curr_pos = new_stream.tell()
			child._pfp__build(new_stream, save_offset)
			size = new_stream.tell() - curr_pos
			new_stream.seek(-size, 1)

			if size > max_size:
				max_size = size

		new_stream.seek(max_size, 1)

		if stream is None:
			return core_stream.getvalue()
		else:
			return max_size
示例#4
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__width(self):
		"""Return the width of the field (sizeof)
		"""
		raw_output = six.BytesIO()
		output = bitwrap.BitwrappedStream(raw_output)
		self._pfp__build(output)
		output.flush()
		return len(raw_output.getvalue())
示例#5
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__unpack_data(self, raw_data):
		"""Means that the field has already been parsed normally,
		and that it now needs to be unpacked.

		:raw_data: A string of the data that the field consumed while parsing
		"""
		if self._pfp__pack_type is None:
			return
		if self._pfp__no_unpack:
			return

		unpack_func = self._pfp__packer
		unpack_args = []
		if self._pfp__packer is not None:
			unpack_func = self._pfp__packer
			unpack_args = [false(), raw_data]

		elif self._pfp__unpack is not None:
			unpack_func = self._pfp__unpack
			unpack_args = [raw_data]

		# does not need to be converted to a char array
		if not isinstance(unpack_func, functions.NativeFunction):
			io_stream = bitwrap.BitwrappedStream(six.BytesIO(raw_data))
			unpack_args[-1] = Array(len(raw_data), Char, io_stream)

		res = unpack_func.call(unpack_args, *self._pfp__pack_func_call_info, no_cast=True)
		if isinstance(res, Array):
			res = res._pfp__build()

		io_stream = six.BytesIO(res)
		tmp_stream = bitwrap.BitwrappedStream(io_stream)

		tmp_stream.padded = self._pfp__interp.get_bitfield_padded()

		self._ = self._pfp__parsed_packed = self._pfp__pack_type(tmp_stream)

		self._._pfp__watch(self)
示例#6
0
def FSeek(params, ctxt, scope, stream, coord):
    """Returns 0 if successful or -1 if the address is out of range
    """
    if len(params) != 1:
        raise errors.InvalidArguments(
            coord,
            "{} args".format(len(params)),
            "FSeek accepts only one argument",
        )

    if params[0] is None:
        return 0
    pos = PYVAL(params[0])
    curr_pos = stream.tell()

    fsize = stream.size()

    if pos > fsize:
        stream.seek(fsize)
        return -1
    elif pos < 0:
        stream.seek(0)
        return -1

    diff = pos - curr_pos
    if diff < 0:
        stream.seek(pos)
        return 0

    data = stream.read(diff)

    # let the ctxt automatically append numbers, as needed, unless the previous
    # child was also a skipped field
    skipped_name = "_skipped"

    if len(ctxt._pfp__children
           ) > 0 and ctxt._pfp__children[-1]._pfp__name.startswith("_skipped"):
        old_name = ctxt._pfp__children[-1]._pfp__name
        data = ctxt._pfp__children[-1].raw_data + data
        skipped_name = old_name
        ctxt._pfp__children = ctxt._pfp__children[:-1]
        del ctxt._pfp__children_map[old_name]

    tmp_stream = bitwrap.BitwrappedStream(six.BytesIO(data))
    new_field = pfp.fields.Array(len(data), pfp.fields.Char, tmp_stream)
    ctxt._pfp__add_child(skipped_name, new_field, stream)
    scope.add_var(skipped_name, new_field)

    return 0
示例#7
0
    def call(self, args, ctxt, scope, stream, interp, coord, no_cast=False):
        if self.send_interp:
            res = self.func(args, ctxt, scope, stream, coord, interp)
        else:
            res = self.func(args, ctxt, scope, stream, coord)

        if no_cast:
            res_field = res
        elif utils.is_str(res) and self.ret == pfp.fields.Array:
            tmp_stream = bitwrap.BitwrappedStream(six.BytesIO(res))
            res_field = pfp.fields.Array(len(res), pfp.fields.Char, tmp_stream)
        else:
            res_field = self.ret()
            res_field._pfp__set_value(res)

        return res_field
示例#8
0
文件: fields.py 项目: strazzere/pfp
	def __getitem__(self, idx):
		if self.raw_data is None:
			return self.items[idx]
		else:
			if self.width < 0 or idx+1 > self.width:
				raise IndexError(idx)
			width = self.field_cls.width
			offset = width * idx
			data = self.raw_data[offset:offset+width]

			stream = bitwrap.BitwrappedStream(six.BytesIO(data))
			res = self.field_cls(stream)
			res._pfp__watch(self)
			res._pfp__parent = self
			res._pfp__array_idx = idx
			res._pfp__name = "{}[{}]".format(
				self._pfp__name, idx
			)
			return res
示例#9
0
    def call(self, args, ctxt, scope, stream, interp, coord, no_cast=False):
        if self.send_interp:
            res = self.func(args, ctxt, scope, stream, coord, interp)
        else:
            res = self.func(args, ctxt, scope, stream, coord)

        if no_cast:
            res_field = res
        elif utils.is_str(res) and self.ret == pfp.fields.Array:
            tmp_stream = bitwrap.BitwrappedStream(six.BytesIO(res))
            res_field = pfp.fields.Array(len(res), pfp.fields.Char, tmp_stream)
        elif utils.is_str(self.ret) and scope.get_type(self.ret) is not None:
            # TODO should we do any type-checking here to make sure that the
            # return value matches what is declared as the return type?
            res_field = res
        else:
            res_field = self.ret()
            res_field._pfp__set_value(res)

        return res_field
示例#10
0
文件: fields.py 项目: strazzere/pfp
	def _pfp__notify_update(self, child=None):
		"""Handle a child with an updated value
		"""
		if getattr(self, "_pfp__union_update_other_children", True):
			self._pfp__union_update_other_children = False

			new_data = child._pfp__build()
			new_stream =  bitwrap.BitwrappedStream(six.BytesIO(new_data))
			for other_child in self._pfp__children:
				if other_child is child:
					continue

				if isinstance(other_child, Array) and other_child.is_stringable():
					other_child._pfp__set_value(new_data)
				else:
					other_child._pfp__parse(new_stream)
				new_stream.seek(0)

			self._pfp__no_update_other_children = True
		
		super(Union, self)._pfp__notify_update(child=child)