about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorCamille Mougey <commial@gmail.com>2015-02-11 13:37:19 +0100
committerCamille Mougey <commial@gmail.com>2015-02-11 13:37:19 +0100
commit5d0d3e5675005d38bfc926a3fe025182ade50720 (patch)
treef5bdc465d5d31a1013e88061dd3f0145f123b987
parentdc916d52815feee22cc81a29fe1272278d4caefc (diff)
parentf68d21f7d8ec32d1378a403c4ccb0345f1d5ef56 (diff)
downloadmiasm-5d0d3e5675005d38bfc926a3fe025182ade50720.tar.gz
miasm-5d0d3e5675005d38bfc926a3fe025182ade50720.zip
Merge pull request #64 from serpilliere/bin_stream_no_len
Bin stream no len
-rw-r--r--miasm2/core/bin_stream.py81
-rw-r--r--miasm2/core/bin_stream_ida.py14
-rw-r--r--miasm2/core/cpu.py8
3 files changed, 42 insertions, 61 deletions
diff --git a/miasm2/core/bin_stream.py b/miasm2/core/bin_stream.py
index 48471b2f..19614661 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,76 @@ 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 +188,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
diff --git a/miasm2/core/bin_stream_ida.py b/miasm2/core/bin_stream_ida.py
index ff88f03e..62c06c9e 100644
--- a/miasm2/core/bin_stream_ida.py
+++ b/miasm2/core/bin_stream_ida.py
@@ -1,4 +1,4 @@
-from idc import Byte
+from idc import Byte, SegEnd
 
 from miasm2.core.bin_stream import bin_stream_str
 
@@ -7,8 +7,6 @@ class bin_stream_ida(bin_stream_str):
     """
     bin_stream implementation for IDA
 
-    IDA should provide Byte function
-
     Don't generate xrange using address computation:
     It can raise error on overflow 7FFFFFFF with 32 bit python
     """
@@ -20,22 +18,16 @@ class bin_stream_ida(bin_stream_str):
 
     def readbs(self, l=1):
         if self.offset + l > self.l:
-            raise IOError
+            raise IOError("not enough bytes")
         o = self.getbytes(self.offset)
         self.offset += l
         return p
 
-    def writebs(self, l=1):
-        raise ValueError('writebs unsupported')
-
     def __str__(self):
         raise NotImplementedError('Not fully functional')
 
     def setoffset(self, val):
         self.offset = val
 
-    def __len__(self):
-        return 0x7FFFFFFF
-
     def getlen(self):
-        return 0x7FFFFFFF - self.offset - self.shift
+        return SegEnd(0) - (self.offset + self.shift)
diff --git a/miasm2/core/cpu.py b/miasm2/core/cpu.py
index d5464305..3fbe1e22 100644
--- a/miasm2/core/cpu.py
+++ b/miasm2/core/cpu.py
@@ -1044,10 +1044,12 @@ class cls_mn(object):
             # print 'len', fname, l
             if l is not None:
                 # print fname, hex(bs_l), l
-                if bs_l * 8 - offset_b < l:
-                    continue
                 # print hex(offset_b)
-                v = cls.getbits(bs, attrib, offset_b, l)
+                try:
+                    v = cls.getbits(bs, attrib, offset_b, l)
+                except IOError:
+                    # Raised if offset is out of bound
+                    continue
                 # print 'TEST', bval, fname, offset_b, cpt, (l, fmask, fbits),
                 # hex(v), hex(v & fmask), hex(fbits), v & fmask == fbits
                 offset_b += l