about summary refs log tree commit diff stats
path: root/miasm2/core/bin_stream.py
diff options
context:
space:
mode:
authorFabrice Desclaux <fabrice.desclaux@cea.fr>2015-02-11 10:44:24 +0100
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2015-02-11 13:27:14 +0100
commit74cc70d786c73dcf7369349976761276f6940a58 (patch)
tree32ff9a521480739dc83a511e8398a92850226b0f /miasm2/core/bin_stream.py
parentdc916d52815feee22cc81a29fe1272278d4caefc (diff)
downloadmiasm-74cc70d786c73dcf7369349976761276f6940a58.tar.gz
miasm-74cc70d786c73dcf7369349976761276f6940a58.zip
bin_stream: clean code and update API
The __len__ cannot be used any more in bin_stream: Python returns an int object,
which will cap values to 0x7FFFFFFF on 32 bit systems. A binary can have a base
address higher than this, making it impossible to handle such programs.

The __len__ is replaced by a call to getlen.

Elfesteem needs an update to support 'max_addr' API in order to retrieve the
elf/pe max virtual address.
Diffstat (limited to 'miasm2/core/bin_stream.py')
-rw-r--r--miasm2/core/bin_stream.py80
1 files changed, 32 insertions, 48 deletions
diff --git a/miasm2/core/bin_stream.py b/miasm2/core/bin_stream.py
index 48471b2f..9907c103 100644
--- a/miasm2/core/bin_stream.py
+++ b/miasm2/core/bin_stream.py
@@ -32,17 +32,21 @@ class bin_stream(object):
         return self.bin[start:start + l]
 
     def getbits(self, start, n):
+        """Return the bits from the bit stream
+        @start: the offset in bits
+        @n: number of bits to read
+        """
         if not n:
             return 0
         o = 0
         if n > self.getlen() * 8:
-            raise ValueError('not enought bits %r %r' % (n, len(self.bin) * 8))
+            raise IOError('not enough bits %r %r' % (n, len(self.bin) * 8))
         while n:
             # print 'xxx', n, start
             i = start / 8
             c = self.getbytes(i)
             if not c:
-                raise IOError
+                raise IOError('cannot get bytes')
             c = ord(c)
             # print 'o', hex(c)
             r = 8 - start % 8
@@ -60,30 +64,25 @@ class bin_stream(object):
 
 class bin_stream_str(bin_stream):
 
-    def __init__(self, bin="", offset=0L, shift=0):
+    def __init__(self, input_str="", offset=0L, shift=0):
         bin_stream.__init__(self)
-        if offset > len(bin):
-            raise IOError
-        self.bin = bin
+        self.bin = input_str
         self.offset = offset
         self.shift = shift
-        self.l = len(bin)
+        self.l = len(input_str)
 
     def getbytes(self, start, l=1):
         if start + l + self.shift > self.l:
-            raise IOError
+            raise IOError("not enough bytes in str")
 
         return super(bin_stream_str, self).getbytes(start + self.shift, l)
 
     def readbs(self, l=1):
         if self.offset + l + self.shift > self.l:
-            raise IOError
+            raise IOError("not enough bytes in str")
         self.offset += l
         return self.bin[self.offset - l + self.shift:self.offset + self.shift]
 
-    def writebs(self, l=1):
-        raise ValueError('writebs unsupported')
-
     def __str__(self):
         out = self.bin[self.offset + self.shift:]
         return out
@@ -91,85 +90,73 @@ class bin_stream_str(bin_stream):
     def setoffset(self, val):
         self.offset = val
 
-    def __len__(self):
-        return len(self.bin) - (self.offset + self.shift)
-
     def getlen(self):
-        return len(self.bin) - (self.offset + self.shift)
+        return self.l - (self.offset + self.shift)
 
 
 class bin_stream_file(bin_stream):
 
-    def __init__(self, bin, offset=0L):
+    def __init__(self, bin, offset=0L, shift=0):
         bin_stream.__init__(self)
         self.bin = bin
         self.bin.seek(0, 2)
+        self.shift = shift
         self.l = self.bin.tell()
         self.offset = offset
 
     def getoffset(self):
-        return self.bin.tell()
+        return self.bin.tell() - self.shift
 
     def setoffset(self, val):
-        self.bin.seek(val)
+        self.bin.seek(val +  self.shift)
     offset = property(getoffset, setoffset)
 
     def readbs(self, l=1):
-        if self.offset + l > self.l:
-            raise IOError
+        if self.offset + l + self.shift > self.l:
+            raise IOError("not enough bytes in file")
         return self.bin.read(l)
 
-    def writebs(self, l=1):
-        if self.offset + l > self.l:
-            raise IOError
-        return self.bin.write(l)
-
     def __str__(self):
         return str(self.bin)
 
+    def getlen(self):
+        return self.l - (self.offset + self.shift)
+
 
-class bin_stream_pe(bin_stream):
 
-    def __init__(self, bin="", offset=0L):
+class bin_stream_container(bin_stream):
+
+    def __init__(self, virt_view="", offset=0L):
         bin_stream.__init__(self)
-        # print 'ELF/PE'
-        self.mylen = len(bin)
-        if offset > bin.__len__():
-            raise IOError
-        self.bin = bin
+        self.bin = virt_view
+        self.l = virt_view.max_addr()
         self.offset = offset
-        self.l = bin.__len__()
 
     def is_addr_in(self, ad):
         return self.bin.is_addr_in(ad)
 
     def getlen(self):
-        return self.mylen
-        # s = self.bin.parent.SHList[-1]
-        # l = self.bin.parent.rva2virt(s.addr+s.size)
-        # return l
+        return self.l
 
     def readbs(self, l=1):
         if self.offset + l > self.l:
-            raise IOError
+            raise IOError("not enough bytes")
         self.offset += l
         return self.bin(self.offset - l, self.offset)
 
-    def writebs(self, l=1):
-        raise ValueError('writebs unsupported')
-
     def getbytes(self, start, l=1):
         return self.bin(start, start + l)
 
     def __str__(self):
-        out = self.bin[self.offset:]
+        out = self.bin(self.offset, self.l)
         return out
 
     def setoffset(self, val):
         self.offset = val
 
-
-class bin_stream_elf(bin_stream_pe):
+class bin_stream_pe(bin_stream_container):
+    pass
+class bin_stream_elf(bin_stream_container):
     pass
 
 
@@ -198,8 +185,5 @@ class bin_stream_vm(bin_stream):
         self.offset += l
         return s
 
-    def writebs(self, l=1):
-        raise ValueError('writebs unsupported')
-
     def setoffset(self, val):
         self.offset = val