Skip to content

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

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions