Repository: androguard/androguard
Issue: KeyError in bytecodes/dvm 

### Describe what you wanted to do

I'm analyzing dex files extracted from Android ROMs.
I'm sure that they are valid dex files, I'm able to disassemble them with dexdump and jadx.
I often find files that trigger this exception:

```
File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7326, in get_type_list
    i = self.__typelists_off[off]
```

- is this error specific to a single file? no

- a [minimal working example](https://www.dropbox.com/s/xh2wscwhhw22ojc/test.dex?dl=0) where the error happens.


### Further Log Files and Output
```
Traceback (most recent call last):
  File "/home/simo/gitProj/Test/cmp_class.py", line 27, in __init__
    self.digest = self.session.add(dex_file, fd.read())
  File "/usr/local/lib/python3.6/dist-packages/androguard/session.py", line 310, in add
    digest, _, _ = self.addDEX(filename, raw_data, dx)
  File "/usr/local/lib/python3.6/dist-packages/androguard/session.py", line 221, in addDEX
    d = DalvikVMFormat(data)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7643, in __init__
    self._load(buff)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7654, in _load
    self.map_list = MapList(self.CM, self.__header.map_off, self)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7540, in __init__
    mi.parse()
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7053, in parse
    self.item = [AnnotationItem(buff, cm) for i in range(0, self.size)]
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7053, in <listcomp>
    self.item = [AnnotationItem(buff, cm) for i in range(0, self.size)]
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 1696, in __init__
    self.annotation = EncodedAnnotation(buff, cm)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 1630, in __init__
    self.elements.append(AnnotationElement(buff, cm))
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 1578, in __init__
    self.value = EncodedValue(buff, cm)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 1493, in __init__
    self.value = cm.get_method(id)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7363, in get_method
    return method.get_list()
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 2506, in get_list
    return [self.get_class_name(), self.get_name(), self.get_proto()]
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 2472, in get_proto
    self.proto_idx_value = self.CM.get_proto(self.proto_idx)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7351, in get_proto
    return [proto.get_parameters_off_value(),
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 2146, in get_parameters_off_value
    params = self.CM.get_type_list(self.parameters_off)
  File "/usr/local/lib/python3.6/dist-packages/androguard/core/bytecodes/dvm.py", line 7326, in get_type_list
    i = self.__typelists_off[off]
KeyError: 6958908
```

### System Information

- Androguard Version: 3.3.5
- Python Version: 3.6
- Operating System: Ubuntu 18.04 x64

### My code
I'm not using Androguard in the "standard" way, because I'm not analyzing APK files and I'm just interested in methods' opcodes.
This is my code (it always work with toys example, but often fails with big dex):
```
class AndroguardDexAnalysis:

    def __init__(self, dex_file: str):
        assert os.path.isfile(dex_file)
        self.clsname_to_class = {}
        self.session = session.Session()
        with open(dex_file, "rb") as fd:
            self.digest = self.session.add(dex_file, fd.read())  # EXCEPTION!
           
```


Changed files:
androguard/misc.py, androguard/core/bytecodes/dvm.py

diff --git a/androguard/core/bytecodes/dvm.py b/androguard/core/bytecodes/dvm.py
index 31cf1a38..e2392aef 100644
--- a/androguard/core/bytecodes/dvm.py
+++ b/androguard/core/bytecodes/dvm.py
@@ -687,7 +687,7 @@ class AnnotationSetItem:
     This class can parse an annotation_set_item of a dex file
 
     :param buff: a string which represents a Buff object of the annotation_set_item
-    :type buff: Buff object
+    :type androguard.core.bytecode.BuffHandle buff: Buff object
     :param cm: a ClassManager object
     :type cm: :class:`ClassManager`
     """
@@ -6978,67 +6978,108 @@ class MapItem:
         log.debug("Starting parsing map_item '{}'".format(self.type.name))
         started_at = time.time()
 
+        # Not all items are aligned in the same way. Most are aligned by four bytes,
+        # but there are a few which are not!
+        # Hence, we need to check the alignment for each item.
+
         buff = self.buff
-        buff.set_idx(self.offset)
         cm = self.CM
 
         if TypeMapItem.STRING_ID_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = [StringIdItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.CODE_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = CodeItem(self.size, buff, cm)
 
         elif TypeMapItem.TYPE_ID_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = TypeHIdItem(self.size, buff, cm)
 
         elif TypeMapItem.PROTO_ID_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = ProtoHIdItem(self.size, buff, cm)
 
         elif TypeMapItem.FIELD_ID_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = FieldHIdItem(self.size, buff, cm)
 
         elif TypeMapItem.METHOD_ID_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = MethodHIdItem(self.size, buff, cm)
 
         elif TypeMapItem.CLASS_DEF_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = ClassHDefItem(self.size, buff, cm)
 
         elif TypeMapItem.HEADER_ITEM == self.type:
             # FIXME probably not necessary to parse again here...
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = HeaderItem(self.size, buff, cm)
 
         elif TypeMapItem.ANNOTATION_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = [AnnotationItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.ANNOTATION_SET_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = [AnnotationSetItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.ANNOTATIONS_DIRECTORY_ITEM == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = [AnnotationsDirectoryItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.ANNOTATION_SET_REF_LIST == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = [AnnotationSetRefList(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.TYPE_LIST == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             self.item = [TypeList(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.STRING_DATA_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = [StringDataItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.DEBUG_INFO_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = DebugInfoItemEmpty(buff, cm)
 
         elif TypeMapItem.ENCODED_ARRAY_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = [EncodedArrayItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.CLASS_DATA_ITEM == self.type:
+            # Byte aligned
+            buff.set_idx(self.offset)
             self.item = [ClassDataItem(buff, cm) for _ in range(self.size)]
 
         elif TypeMapItem.MAP_LIST == self.type:
+            # 4-byte aligned
+            buff.set_idx(self.offset + (self.offset % 4))
             pass  # It's me I think !!! No need to parse again
 
         else:
-            log.warning("Map item '{}' @ 0x{:x}({}) is unknown".format(self.type, buff.get_idx(), buff.get_idx()))
+            log.warning("Map item with id '{type}' offset: 0x{off:x} ({off}) "
+                        "size: {size} is unknown. "
+                        "Is this a newer DEX format?".format(type=self.type, off=buff.get_idx(), size=self.size))
 
         diff = time.time() - started_at
         minutes, seconds = diff // 60, diff % 60
diff --git a/androguard/misc.py b/androguard/misc.py
index 528e0161..67b36f61 100644
--- a/androguard/misc.py
+++ b/androguard/misc.py
@@ -22,6 +22,8 @@ def get_default_session():
     """
     Return the default Session from the configuration
     or create a new one, if the session in the configuration is None.
+
+    :rtype: androguard.session.Session
     """
     if androconf.CONF["SESSION"] is None:
         androconf.CONF["SESSION"] = Session()