Skip to content

Allow negative relative streams in dissect.util.streams.RelativeStream #126

@DissectBot

Description

@DissectBot

Currently only positive relative streams are supported, where the relative stream starts at the given offset of the source file-like object. However, in some cases it might be useful to allow negative relative streams, to act like the stream starts at a given offset.

For example, a normal use case of RelativeStream is this:

  • Source file-like object with some data on offset 0x1000 that we want to use as a normal stream, like it originates from offset 0

  • RelativeStream(source, 0x1000) - the relative stream will start all reading from offset 0x1000

    The negative relative stream example would look like this:

  • Source file-like object with data at offset 0, but we need to make it look like it starts at 0x1000

  • RelativeStream(source, -0x1000) - the relative stream will return garbage if trying to read before 0x1000, and start returning the source stream data at offset 0 from the relative stream offset 0x1000

    The reason this doesn't currently already work is because RelativeStream uses AlignedStream, which aligns all reads on a certain block size. If the RelativeStream must start on virtual offset 0x100, but the block size is 0x200, it will try to seek to 0 - 0x100 (because 0x100 // 0x200 == 0).

    A quick and dirty fix looks like this, but some additional documentation would need to be added, and maybe a bit cleaner implementation with some more safety nets.

    {code:python}
    diff --git a/dissect/util/stream.py b/dissect/util/stream.py
    index b0c66c7..79f6ad7 100644
    — a/dissect/util/stream.py
    +++ b/dissect/util/stream.py
    @@ -203,8 +203,15 @@ class RelativeStream(AlignedStream):
    return super(RelativeStream, self)._seek(pos, whence)

    def _read(self, offset, length):

  •    self._fh.seek(self.offset + offset)
    
  •    return self._fh.read(length)
    
    •    rel_offset = self.offset + offset
      
    •    if rel_offset < 0:
      
    •        buf = b'\x00' \* -rel_offset
      
    •        rel_offset = 0
      
    •        length += rel_offset
      
    •    else:
      
    •        buf = b''
      
    •    self._fh.seek(rel_offset)
      
    •    return buf + self._fh.read(length)
      

    class BufferedStream(AlignedStream):
    {code}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions