Repository: matwey/pybeam

Issue:
KeyError: b'CInf' for a BEAM file
The following fails:

```
BeamFile('Elixir.IEx.Introspection.beam').compileinfo['source']

KeyError                                  Traceback (most recent call last)
<ipython-input-3-7cf8d4bc6f05> in <module>
----> 1 _2.compileinfo['source']

/usr/lib/python3.8/site-packages/pybeam/beam_file.py in compileinfo(self)
     56         @property
     57         def compileinfo(self):
---> 58                 cinf = self.selectChunkByName(b"CInf")
     59                 return dict(cinf.payload)
     60 

/usr/lib/python3.8/site-packages/pybeam/beam_file.py in selectChunkByName(self, name)
     33                         if c.chunk_name == name:
     34                                 return c
---> 35                 raise KeyError(name)
     36 
     37         @property

KeyError: b'CInf'
```

[Elixir.IEx.Introspection.beam.txt](https://github.com/matwey/pybeam/files/5477601/Elixir.IEx.Introspection.beam.txt)



Discussion:
lgtm-com[bot]: This pull request **introduces 1 alert** when merging 15b7ade6394c3939b6d13a17ca2d430928ddb634 into 2dec4d87719d500070bf1cf3090d5a2cc62f8d9b - [view on LGTM.com](https://lgtm.com/projects/g/matwey/pybeam/rev/pr-1687e21e88f7060ea78658080a383af5187b037c)

**new alerts:**

* 1 for Unused import

Patch:
diff --git a/pybeam/beam_file.py b/pybeam/beam_file.py
index eb7b126..6a70fef 100644
--- a/pybeam/beam_file.py
+++ b/pybeam/beam_file.py
@@ -26,53 +26,49 @@ class BeamFile(object):
 	def __init__(self, f):
 		if not hasattr(f, 'read'):
 			f = open(f, "rb")
-		self._tree = beam.parse(f.read())
+		self._chunks = beam.parse(f.read())
 
 	def selectChunkByName(self, name):
-		for c in self._tree.chunks:
-			if c.chunk_name == name:
-				return c
-		raise KeyError(name)
+		return self._chunks.get(name)
 
 	@property
 	def atoms(self):
-		try:
-			return self.selectChunkByName(b"AtU8").payload
-		except KeyError:
-			pass
-		return self.selectChunkByName(b"Atom").payload
+		atom = self.selectChunkByName(b"AtU8")
+		atom = atom if atom is not None else self.selectChunkByName(b"Atom")
+		return atom
 
 	@property
 	def attributes(self):
 		attr = self.selectChunkByName(b"Attr")
 		# convert from proplist to dict
-		return dict(attr.payload)
+		return dict(attr) if attr is not None else None
 
 	@property
 	def code(self):
-		code = self.selectChunkByName(b"Code").payload
+		code = self.selectChunkByName(b"Code")
 		return (code.set, code.opcode_max, code.labels, code.functions, code.code)
 
 	@property
 	def compileinfo(self):
 		cinf = self.selectChunkByName(b"CInf")
-		return dict(cinf.payload)
+		return dict(cinf) if cinf is not None else None
 
 	@property
 	def exports(self):
 		expt = self.selectChunkByName(b"ExpT")
 		atoms = self.atoms
-		return [(atoms[e.function-1], e.arity, e.label) for e in expt.payload.entry]
+		return [(atoms[e.function-1], e.arity, e.label) for e in expt.entry] if expt is not None else None
 
 	@property
 	def literals(self):
-		return [e.term for e in self.selectChunkByName(b"LitT").payload.data.entry]
+		litt = self.selectChunkByName(b"LitT")
+		return litt.entry if litt is not None else None
 
 	@property
 	def imports(self):
 		impt = self.selectChunkByName(b"ImpT")
 		atoms = self.atoms
-		return [(atoms[e.module-1], atoms[e.function-1], e.arity) for e in impt.payload.entry]
+		return [(atoms[e.module-1], atoms[e.function-1], e.arity) for e in impt.entry] if impt is not None else None
 
 	@property
 	def modulename(self):
diff --git a/pybeam/erlang_types.py b/pybeam/erlang_types.py
index 582ce50..299bc0e 100644
--- a/pybeam/erlang_types.py
+++ b/pybeam/erlang_types.py
@@ -20,86 +20,31 @@
 # THE SOFTWARE.
 #
 
-from six import iterbytes
+from collections import namedtuple
+from six import PY2
 
-class AtomCacheReference(object):
-	def __init__(self, index):
-		self.index = index
-	def __eq__(self,other):
-		return self.index == other.index
+class AtomCacheReference(int):
+	pass
 
-class Reference(object):
-	def __init__(self, node, id_, creation):
-		self.node = node
-		self.id = id_
-		self.creation = creation
-	def __eq__(self,other):
-		return self.node == other.node and self.id == other.id and self.creation == other.creation
+Reference = namedtuple("Reference", ["node", "id", "creation"])
 
-class Port(object):
-	def __init__(self, node, id_, creation):
-		self.node = node
-		self.id = id_
-		self.creation = creation
-	def __eq__(self,other):
-		return self.node == other.node and self.id == other.id and self.creation == other.creation
+Port = namedtuple("Port", ["node", "id", "creation"])
 
-class Pid(object):
-	def __init__(self, node, id_, serial, creation):
-		self.node = node
-		self.id = id_
-		self.serial = serial
-		self.creation = creation
-	def __eq__(self,other):
-		return self.node == other.node and self.id == other.id and self.creation == other.creation and self.serial == other.serial
+Pid = namedtuple("Pid", ["node", "id", "serial", "creation"])
 
-class String(object):
-	def __init__(self, value):
-		self.value = value
-	def __eq__(self, other):
-		return self.value == other.value
-	def __iter__(self):
-		return iterbytes(self.value)
-	def __len__(self):
-		return len(self.value)
+if PY2:
+	class String(bytes):
+		def __getitem__(self, index):
+			return ord(super(String, self).__getitem__(index))
+else:
+	class String(bytes):
+		pass
 
-class Binary(object):
-	def __init__(self, value):
-		self.value = value
-	def __eq__(self, other):
-		return self.value == other.value
+class Binary(bytes):
+	pass
 
-class Fun(object):
-	def __init__(self, arity, uniq, index, module, oldindex, olduniq, pid, free):
-		self.arity = arity
-		self.uniq = uniq
-		self.index = index
-		self.module = module
-		self.oldindex = oldindex
-		self.olduniq = olduniq
-		self.pid = pid
-		self.free = free
-	def __eq__(self, other):
-		return (self.arity == other.arity
-			and self.uniq == other.uniq
-			and self.index == other.index
-			and self.module == other.module
-			and self.oldindex == other.oldindex
-			and self.olduniq == other.olduniq
-			and self.pid == other.pid
-			and self.free == other.free)
+Fun = namedtuple("Fun", ["arity", "uniq", "index", "module", "oldindex", "olduniq", "pid", "free"])
 
-class MFA(object):
-	def __init__(self, module, function, arity):
-		self.module = module
-		self.function = function
-		self.arity = arity
-	def __eq__(self, other):
-		return self.module == other.module and self.function == other.function and self.arity == other.arity
+MFA = namedtuple("MFA", ["module", "function", "arity"])
 
-class BitBinary(object):
-	def __init__(self, value, bits):
-		self.value = value
-		self.bits = bits
-	def __eq__(self, other):
-		return self.value == other.value and self.bits == other.bits
+BitBinary = namedtuple("BitBinary", ["value", "bits"])
diff --git a/pybeam/schema/beam/__init__.py b/pybeam/schema/beam/__init__.py
index 107b7dc..1652253 100644
--- a/pybeam/schema/beam/__init__.py
+++ b/pybeam/schema/beam/__init__.py
@@ -20,20 +20,23 @@
 # THE SOFTWARE.
 #
 
-from construct import this
-from construct import (
-	Const,
-	FixedSized,
-	GreedyRange,
-	Int32ub,
-	Struct,)
+from construct import Adapter, Const, FocusedSeq, GreedyRange, Int32ub, Prefixed, Terminated
 
 from pybeam.schema.beam.chunks import chunk
 
-beam = Struct(
-	"for1" / Const(b'FOR1'),
-	"size" / Int32ub,
-	"beam" / Const(b'BEAM'),
-	"chunks" / FixedSized(this.size-4, GreedyRange(chunk)))
+
+class DictAdapter(Adapter):
+	def _decode(self, obj, context, path):
+		return dict(obj)
+
+	def _encode(self, obj, context, path):
+		return obj.items()
+
+beam = FocusedSeq("chunks",
+	Const(b'FOR1'),
+	"chunks" / Prefixed(Int32ub, FocusedSeq("chunks",
+		Const(b'BEAM'),
+		"chunks" / DictAdapter(GreedyRange(chunk)),
+		Terminated)))
 
 __all__ = ["beam"]
diff --git a/pybeam/schema/beam/chunks.py b/pybeam/schema/beam/chunks.py
index 26696b3..3d0a373 100644
--- a/pybeam/schema/beam/chunks.py
+++ b/pybeam/schema/beam/chunks.py
@@ -26,14 +26,13 @@ from construct import (
 	Aligned,
 	Bytes,
 	Compressed,
-	Computed,
-	FixedSized,
 	GreedyBytes,
 	Int32ub,
 	Int8ub,
 	PascalString,
 	Prefixed,
 	PrefixedArray,
+	Sequence,
 	Struct,
 	Switch,)
 
@@ -53,8 +52,7 @@ Code = Struct("headerlen" / Int32ub,
 	"labels" / Int32ub,
 	"functions" / Int32ub,
 	Bytes(lambda ctx: ctx.headerlen-16),
-	Bytes(lambda ctx: ctx._.size-ctx.headerlen-4),
-	)
+	GreedyBytes)
 
 ExpT = Struct("entry" / PrefixedArray(Int32ub, Struct("function" / Int32ub,
 	"arity" / Int32ub,
@@ -64,21 +62,17 @@ ImpT = Struct("entry" / PrefixedArray(Int32ub, Struct("module" / Int32ub,
 	"function" / Int32ub,
 	"arity" / Int32ub)))
 
-uncomp_chunk_litt = Struct("entry" / PrefixedArray(Int32ub, Prefixed(Int32ub, Struct("term" / external_term))))
+uncomp_chunk_litt = PrefixedArray(Int32ub, Prefixed(Int32ub, external_term))
 LitT = Struct(Int32ub,
-	"data" / Prefixed(Computed(lambda ctx: ctx._.size-4),
-		Compressed(uncomp_chunk_litt, "zlib")
-	)
-)
+	"entry" / Compressed(uncomp_chunk_litt, "zlib"))
 
 LocT = PrefixedArray(Int32ub, Struct("function" / Int32ub,
 	"arity" / Int32ub,
 	"label" / Int32ub))
 
-chunk = Struct(
+chunk = Sequence(
 	"chunk_name" / Bytes(4),
-	"size" / Int32ub,
-	"payload" / Aligned(4, FixedSized(this.size, Switch(this.chunk_name, {
+	Aligned(4, Prefixed(Int32ub, Switch(this.chunk_name, {
 #		"Abst" : chunk_abst,
 		b"Atom" : Atom,
 		b"AtU8" : AtU8,
@@ -93,7 +87,6 @@ chunk = Struct(
 		b"LocT" : LocT,
 #		"StrT" : chunk_strt,
 #		"Trac" : chunk_trac,
-	}, default=GreedyBytes))),
-	)
+	}, default=GreedyBytes))))
 
 __all__ = ["chunk"]
diff --git a/pybeam/schema/eetf.py b/pybeam/schema/eetf.py
index 2685110..b2e0846 100644
--- a/pybeam/schema/eetf.py
+++ b/pybeam/schema/eetf.py
@@ -133,7 +133,7 @@ def tag(obj):
 term_ = LazyBound(lambda: term)
 
 atom_cache_ref = ExprAdapter(Int8ub,
-		encoder=lambda obj, ctx: obj.index,
+		encoder=lambda obj, ctx: obj,
 		decoder=lambda obj, ctx: AtomCacheReference(obj))
 small_integer = Int8ub
 integer = Int32sb
@@ -163,13 +163,13 @@ nil = ExprAdapter(Sequence(),
 		encoder=lambda obj, ctx: (),
 		decoder=lambda obj, ctx: [])
 string = ExprAdapter(Prefixed(Int16ub, GreedyBytes),
-		encoder=lambda obj, ctx: obj.value,
+		encoder=lambda obj, ctx: obj,
 		decoder=lambda obj, ctx: etString(obj))
 list_ = ListAdapter(Sequence("len" / Int32ub,
 		Array(this.len, term_),
 		term_))
 binary = ExprAdapter(Prefixed(Int32ub, GreedyBytes),
-		encoder=lambda obj, ctx: obj.value,
+		encoder=lambda obj, ctx: obj,
 		decoder=lambda obj, ctx: Binary(obj))
 small_big = BigInteger(Int8ub)
 large_big = BigInteger(Int32ub)


Test patch:
diff --git a/test/beam_file.py b/test/beam_file.py
index 66a02c9..5b53273 100644
--- a/test/beam_file.py
+++ b/test/beam_file.py
@@ -27,7 +27,7 @@ import io
 
 class BEAMFileTest(unittest.TestCase):
 	def setUp(self):
-		self.raw = b'FOR1\x00\x00\x02\xb4BEAMAtom\x00\x00\x00U\x00\x00\x00\x08\x08ssh_math\x04ipow\x06crypto\x07mod_pow\x10bytes_to_integer\x0bmodule_info\x06erlang\x0fget_module_info\x00\x00\x00Code\x00\x00\x00\\\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x99\x00\x00\x00\x07\x00\x00\x00\x03\x01\x10\x99\x10\x02\x12"0\x01 \'\x15\x01#(\x15\x13\x01\x0c\x000\x99 \x070\x00\x99 \x08\x10\x10\x00\x010\x99\x00\x02\x12b\x00\x01@@\x12\x03\x99\x00N\x10 \x01P\x99\x00\x02\x12b\x10\x01`@\x03\x13@\x12\x03\x99\x00N 0\x03StrT\x00\x00\x00\x00ImpT\x00\x00\x004\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x02ExpT\x00\x00\x00(\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02Attr\x00\x00\x00(\x83l\x00\x00\x00\x01h\x02d\x00\x03vsnl\x00\x00\x00\x01n\x10\x00\x8f\xde\xf9V}\xf3wr\x8a\x93\xc1p\xedDK\x9ajjCInf\x00\x00\x01@\x83l\x00\x00\x00\x04h\x02d\x00\x07optionsl\x00\x00\x00\x04h\x02d\x00\x06outdirk\x00</home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/ssh/src/../ebinh\x02d\x00\x01ik\x007/home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/kernel/srcd\x00\x10warn_unused_varsd\x00\ndebug_infojh\x02d\x00\x07versionk\x00\x055.0.1h\x02d\x00\x04timeh\x06b\x00\x00\x07\xe0a\x02a\x0fa\x0ba\x08a\x12h\x02d\x00\x06sourcek\x00A/home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/ssh/src/ssh_math.erlj'
+		self.raw = b'FOR1\x00\x00\x02\xd4BEAMAtom\x00\x00\x00U\x00\x00\x00\x08\x08ssh_math\x04ipow\x06crypto\x07mod_pow\x10bytes_to_integer\x0bmodule_info\x06erlang\x0fget_module_info\x00\x00\x00Code\x00\x00\x00\\\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x99\x00\x00\x00\x07\x00\x00\x00\x03\x01\x10\x99\x10\x02\x12"0\x01 \'\x15\x01#(\x15\x13\x01\x0c\x000\x99 \x070\x00\x99 \x08\x10\x10\x00\x010\x99\x00\x02\x12b\x00\x01@@\x12\x03\x99\x00N\x10 \x01P\x99\x00\x02\x12b\x10\x01`@\x03\x13@\x12\x03\x99\x00N 0\x03StrT\x00\x00\x00\x00ImpT\x00\x00\x004\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x02ExpT\x00\x00\x00(\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02Attr\x00\x00\x00(\x83l\x00\x00\x00\x01h\x02d\x00\x03vsnl\x00\x00\x00\x01n\x10\x00\x8f\xde\xf9V}\xf3wr\x8a\x93\xc1p\xedDK\x9ajjCInf\x00\x00\x01@\x83l\x00\x00\x00\x04h\x02d\x00\x07optionsl\x00\x00\x00\x04h\x02d\x00\x06outdirk\x00</home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/ssh/src/../ebinh\x02d\x00\x01ik\x007/home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/kernel/srcd\x00\x10warn_unused_varsd\x00\ndebug_infojh\x02d\x00\x07versionk\x00\x055.0.1h\x02d\x00\x04timeh\x06b\x00\x00\x07\xe0a\x02a\x0fa\x0ba\x08a\x12h\x02d\x00\x06sourcek\x00A/home/abuild/rpmbuild/BUILD/otp_src_17.1/lib/ssh/src/ssh_math.erljLitT\x00\x00\x00\x18\x00\x00\x00\x0ax\x9cc```d```j\xce\x02\x00\x01\x87\x00\xf1\x00\x00'
 		self.io = io.BytesIO(self.raw)
 		self.beam = beam_file.BeamFile(self.io)
 	def test_attr(self):
@@ -51,3 +51,5 @@ class BEAMFileTest(unittest.TestCase):
 		self.assertListEqual([('crypto', 'mod_pow', 3), ('crypto', 'bytes_to_integer', 1), ('erlang', 'get_module_info', 1), ('erlang', 'get_module_info', 2)], self.beam.imports)
 	def test_modulename(self):
 		self.assertEqual('ssh_math', self.beam.modulename)
+	def test_literals(self):
+		self.assertListEqual([[]], self.beam.literals)
diff --git a/test/schema_beam.py b/test/schema_beam.py
index 9b9ee5f..c38fb8c 100644
--- a/test/schema_beam.py
+++ b/test/schema_beam.py
@@ -21,8 +21,9 @@
 #
 
 from pybeam.schema import beam
-from pybeam.schema.beam.chunks import Atom, AtU8, Attr, CInf, chunk
+from pybeam.schema.beam.chunks import Atom, AtU8, Attr, CInf, LitT
 from construct import Container, StreamError
+from construct.core import TerminatedError
 import unittest
 
 class BEAMConstructTest(unittest.TestCase):
@@ -30,15 +31,15 @@ class BEAMConstructTest(unittest.TestCase):
 		pass
 	def test_beam1(self):
 		c = beam
-		self.assertEqual(c.parse(b'FOR1\x00\x00\x00\x04BEAM'), Container(for1=b"FOR1", beam=b"BEAM", chunks=[], size=4))
+		self.assertEqual(c.parse(b'FOR1\x00\x00\x00\x04BEAM'), {})
 	def test_beam2(self):
 		c = beam
 		raw = b'FOR1\x00\x00\x02TBEAMAtU8\x00\x00\x002\x00\x00\x00\x07\x01m\x04fact\x06erlang\x01-\x01*\x0bmodule_info\x0fget_module_info\x00\x00Code\x00\x00\x00w\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x99\x00\x00\x00\x08\x00\x00\x00\x03\x01\x10\x99\x10\x02\x12"\x10\x01 \'5\x01\x03\x0e\x10\x10\x99\x10}\x05\x10\x00\x03\x11\x13@\x03\x04@\x13\x03\x99\x10\x04\x10%\x99\x10}\x05\x10\x10\x04\x03\x03\x12\x10\x13\x010+\x15\x03\x01@\x11\x03\x13\x01@\x99\x00\x02\x12b\x00\x01P@\x12\x03\x99\x00N\x10 \x01`\x99\x00\x02\x12b\x10\x01p@\x03\x13@\x12\x03\x99\x00N 0\x03\x00StrT\x00\x00\x00\x00ImpT\x00\x00\x004\x00\x00\x00\x04\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x02ExpT\x00\x00\x00(\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02LocT\x00\x00\x00\x04\x00\x00\x00\x00Attr\x00\x00\x00(\x83l\x00\x00\x00\x01h\x02d\x00\x03vsnl\x00\x00\x00\x01n\x10\x007\xfc\x18\xc42\x03\xc0\xfa\xe0\x91w.a\xb8\xebqjjCInf\x00\x00\x00l\x83l\x00\x00\x00\x03h\x02d\x00\x07optionsl\x00\x00\x00\x01d\x00\rno_debug_infojh\x02d\x00\x07versionk\x00\x057.1.5h\x02d\x00\x06sourcek\x00!/home/matwey/rpmbuild/BUILD/m.erljDbgi\x00\x00\x00F\x83h\x03d\x00\rdebug_info_v1d\x00\x11erl_abstract_codeh\x02d\x00\x04nonel\x00\x00\x00\x01d\x00\rno_debug_infoj\x00\x00Line\x00\x00\x00\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00A\x00\x00\x00'
-		parsed = c.parse(raw)
-		self.assertEqual(len(raw), 604)
-		self.assertEqual(parsed.for1, b'FOR1')
-		self.assertEqual(parsed.size, 596)
-		self.assertEqual(parsed.beam, b'BEAM')
+		chunks = c.parse(raw)
+		self.assertSetEqual(set(chunks.keys()), set([b'AtU8', b'Code', b'StrT', b'ImpT', b'ExpT', b'LocT', b'Attr', b'CInf', b'Dbgi', b'Line']))
+	def test_beam3(self):
+		c = beam
+		self.assertRaises(TerminatedError, lambda: c.parse(b'FOR1\x00\x00\x00\x0cBEAMAtU8\x00\x00\x002'))
 	def test_chunk_atom(self):
 		c = Atom
 		self.assertEqual(c.parse(b'\x00\x00\x00\x00'), [])
@@ -63,9 +64,12 @@ class BEAMConstructTest(unittest.TestCase):
 		self.assertEqual(c.parse(b'\x83\x64\x00\x08burtovoy'), u"burtovoy")
 		self.assertEqual(c.parse(c.build(u"burtovoy")), u"burtovoy")
 		self.assertEqual(c.parse(b'\x83\x6a'), [])
-	def test_chunk_litt(self):
-		c = chunk
+	def test_chunk_litt1(self):
+		c = LitT
 		littc = b'x\x9cc```d```j\xce\x02\x00\x01\x87\x00\xf1'
-		litt = b'LitT\x00\x00\x00\x16\x00\x00\x00\x0a' + littc + b'\x00\x00'
-		self.assertEqual(c.parse(litt).payload.data.entry[0].term, [])
-
+		litt = b'\x00\x00\x00\x0a' + littc + b'\x00\x00'
+		self.assertEqual(c.parse(litt).entry[0], [])
+	def test_chunk_litt2(self):
+		c = LitT
+		litt = b'\x00\x00\x03?x\x9cuR\xc1n\xd40\x10M\xb2mi\xab]T@THP4\xea\r\x84\x96\x13|\x01\x0b\x8a\xb4\x80T8\xf4f9\xce,\xf1\xaecG\xb6S\xef\nqZ\x89/\xe0\x02\'>\x80\x8f\xe1\x17\xf8\x0e.\xd8\xde\x84\x94\x03\x97\xf1\xf8yf\xde\x9b\x19\'Ir?I\x92\xcb\xad\xf0\xf6\xa0\xca\\Z\xd0\xd4\x1fG%2U7\xca \xcd\x02ZEtO5(\xa3\x97\xdax\x9cYM\xa5\x11\xd4"aT\x88\x82\xb2\x15\x91\xb4FB5\xb7\x1b\x9a.}\xd5\xd3m\xed\xed\xc9\xdd\xdf\xe3[_\xcf\x9e\x7f~\x9c\x8d\'\xbf\xbe\xff\xfc\xe1\xb1;\xf1ebqm\x9f\xd6T\xafJ\xe5d\x90\x11\xe1$z\xb6\xf3nD,\x05o\x1em\xab\x91\xcb>~Z\x06\xc9#7\x99\t\xbe\xe6z\xfaZ\x95\xad@wH\x08\x97\x0bE\xc8\x8e\xfca\x08\xfe\x7f\xc8 \xa2T\xac\xadQZj\xb9\n"\x1e\xc4\x89d\xee\xa4\xcf\xa5L\xab\xe9L^\xf9\xd6Ca\xe8\xde\x0f\xfb\xbe\xdd\xa4\x0e!\xfd5\xc4\xdc\x0e\xe4#\xc9\xc5`<\xba\xbf]%\xe9\xb1w\xee\xf5%\x16\xadd\x81\xd6\xed\xc7\x12!\xf5[T\xf5%_\x00\x97\xc6"-A-\x802\x86\xc6p\xf9\x01\xfeQ\x0b\x1b\xd5\x82S\xad(A\xf0\x15B\xad4B\xe8P\xd7\xbbwZ\xa8\xd6\x02\x85+*Z\x04\xa5;\xc0V\x08\x1aM+l,.\x01\xd7\x8d\x0e\x04J>\x81\xd6`\x0c8\xe7\xe7P\xa1hP\xf7J\xbc\xaeWq/i\x90\x98\xa1\x0c\xc7\xb3\xddl\xc1Q\x03\xe1\xe3p\x81%8n\xab@\xe4\xd5\x9a)\xbc\xab\x94\x0b\xda\x95\x14\x1b0\rz,\x0c>\x0e!u{v\xd3\xe0r\xd8\xf4\xf1\xb0\x9a\xd9<\xbf\xcc/\xc8\xecE\xfe\xfe\xed\x85\x07\xc6\x11>\xf8{\xbf\x19\xef~\xab/\xf3\xf9\x8c\x90\xeb\xc8<\x7f\xb3CN;\x9a\t-\x8c\xff\xb3\xcc\x12\xa6\xca\xc8w\x14cG\x82\x17!e\xdb\xf54\xfc\xdb\xa0\xeb\xfa4\x87\x14\xa3\xd9\x1f2\xc5\xe6\n\x00\x00\x00'
+		self.assertEqual(len(c.parse(litt).entry), 27)