Skip to content

Commit 8d3edd7

Browse files
author
vbuell
committed
References are fully supported (except of enums). Refactoring of typecodes.
1 parent 853fea2 commit 8d3edd7

File tree

1 file changed

+97
-46
lines changed

1 file changed

+97
-46
lines changed

javaobj.py

Lines changed: 97 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ def __init__(self):
3838
self.superclass = None
3939

4040
def __str__(self):
41+
return self.__repr__()
42+
43+
def __repr__(self):
4144
return "[%s:0x%X]" % (self.name, self.serialVersionUID)
4245

4346

@@ -77,6 +80,35 @@ class JavaObjectMarshaller:
7780
SC_EXTERNALIZABLE = 0x04
7881
SC_ENUM = 0x10
7982

83+
# type definition chars (typecode)
84+
TYPE_BYTE = 'B' # 0x42
85+
TYPE_CHAR = 'C'
86+
TYPE_DOUBLE = 'D' # 0x44
87+
TYPE_FLOAT = 'F' # 0x46
88+
TYPE_INTEGER = 'I' # 0x49
89+
TYPE_LONG = 'J' # 0x4A
90+
TYPE_SHORT = 'S' # 0x53
91+
TYPE_BOOLEAN = 'Z' # 0x5A
92+
TYPE_OBJECT = 'L' # 0x4C
93+
TYPE_ARRAY = '[' # 0x5B
94+
95+
# list of supported typecodes listed above
96+
TYPECODES_LIST = [
97+
# primitive types
98+
TYPE_BYTE,
99+
TYPE_CHAR,
100+
TYPE_DOUBLE,
101+
TYPE_FLOAT,
102+
TYPE_INTEGER,
103+
TYPE_LONG,
104+
TYPE_SHORT,
105+
TYPE_BOOLEAN,
106+
# object types
107+
TYPE_OBJECT,
108+
TYPE_ARRAY ]
109+
110+
BASE_REFERENCE_IDX = 0x7E0000
111+
80112
def __init__(self):
81113
self.opmap = {
82114
self.TC_NULL: self.do_null,
@@ -89,11 +121,17 @@ def __init__(self):
89121
self.TC_REFERENCE: self.do_reference
90122
}
91123
self.current_object = None
124+
self.reference_counter = 0
125+
self.references = []
92126

93127
def load_stream(self, stream):
94-
self.object_stream = stream
95-
self._readStreamHeader()
96-
return self.readObject()
128+
try:
129+
self.object_stream = stream
130+
self._readStreamHeader()
131+
return self.readObject()
132+
except Exception, e:
133+
self.dump_state()
134+
raise
97135

98136
def _readStreamHeader(self):
99137
(magic, version) = self._readStruct(">HH")
@@ -153,7 +191,10 @@ def do_classdesc(self, parent=None, ident=0):
153191
(serialVersionUID, newHandle, classDescFlags) = self._readStruct(">LLB")
154192
clazz.serialVersionUID = serialVersionUID
155193
clazz.flags = classDescFlags
156-
self.print_ident("Serial: 0x%X newHanle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID, newHandle, classDescFlags), ident)
194+
195+
self.add_reference(clazz)
196+
197+
self.print_ident("Serial: 0x%X newHandle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID, newHandle, classDescFlags), ident)
157198
(length, ) = self._readStruct(">H")
158199
self.print_ident("Fields num: 0x%X" % length, ident)
159200

@@ -165,16 +206,19 @@ def do_classdesc(self, parent=None, ident=0):
165206
field_type = None
166207
field_type = self.convert_char_to_type(type)
167208

168-
if field_type == "array":
209+
if field_type == self.TYPE_ARRAY:
169210
field_type = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_STRING, self.TC_REFERENCE])
170211
if field_type is not None:
171212
field_type = "array of " + field_type
172213
else:
173214
field_type = "array of None"
174-
elif field_type == "object":
215+
elif field_type == self.TYPE_OBJECT:
175216
field_type = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_STRING, self.TC_REFERENCE])
176217

177218
self.print_ident("FieldName: 0x%X" % type + " " + str(field_name) + " " + str(field_type), ident)
219+
assert field_name is not None
220+
assert field_type is not None
221+
178222
clazz.fields_names.append(field_name)
179223
clazz.fields_types.append(field_type)
180224
if parent:
@@ -206,6 +250,7 @@ def do_class(self, parent=None, ident=0):
206250
# TODO: what to do with "(ClassDesc)prevObject". (see 3rd line for classDesc:)
207251
classdesc = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL])
208252
self.print_ident("Classdesc: %s" % classdesc, ident)
253+
self.add_reference(classdesc)
209254
return classdesc
210255

211256
def do_object(self, parent=None, ident=0):
@@ -214,7 +259,10 @@ def do_object(self, parent=None, ident=0):
214259
self.print_ident("[object]", ident)
215260

216261
# TODO: what to do with "(ClassDesc)prevObject". (see 3rd line for classDesc:)
217-
classdesc = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL])
262+
classdesc = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL, self.TC_REFERENCE])
263+
# self.TC_REFERENCE hasn't shown in spec, but actually is here
264+
265+
self.add_reference(java_object)
218266

219267
# classdata[]
220268

@@ -254,23 +302,27 @@ def do_object(self, parent=None, ident=0):
254302
def do_string(self, parent=None, ident=0):
255303
self.print_ident("[string]", ident)
256304
ba = self._readString()
305+
self.add_reference(str(ba))
257306
return str(ba)
258307

259308
def do_array(self, parent=None, ident=0):
260309
# TC_ARRAY classDesc newHandle (int)<size> values[size]
261310
self.print_ident("[array]", ident)
262311
classdesc = self.read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL])
263-
(size, ) = self._readStruct(">i")
264-
self.print_ident("size: " + str(size), ident)
265312

266313
array = []
267314

315+
self.add_reference(array)
316+
317+
(size, ) = self._readStruct(">i")
318+
self.print_ident("size: " + str(size), ident)
319+
268320
# for char in classdesc.name:
269-
typestr = self.convert_char_to_type(classdesc.name[0])
270-
assert typestr == "array"
271-
typestr = self.convert_char_to_type(classdesc.name[1])
321+
type_char = classdesc.name[0]
322+
assert type_char == self.TYPE_ARRAY
323+
type_char = classdesc.name[1]
272324

273-
if typestr == "object" or typestr == "array":
325+
if type_char == self.TYPE_OBJECT or type_char == self.TYPE_ARRAY:
274326
for i in range(size):
275327
res = self.read_and_exec_opcode(ident=ident+1)
276328
print res
@@ -285,9 +337,10 @@ def do_array(self, parent=None, ident=0):
285337
return None
286338

287339
def do_reference(self, parent=None, ident=0):
288-
# TODO: Reference isn't supported yed
289-
(handle, reference) = self._readStruct(">HH")
290-
print "## Reference:", handle, reference
340+
# TODO: Reference isn't supported yet
341+
(handle, ) = self._readStruct(">L")
342+
print "## Reference handle: 0x%x" % (handle)
343+
return self.references[handle - self.BASE_REFERENCE_IDX]
291344
# raise NotImplementedError("Reference isn't supported yed.")
292345

293346
def do_null(self, parent=None, ident=0):
@@ -310,50 +363,48 @@ def hexdump(self, src, length=16):
310363
return ''.join(result)
311364

312365
def read_native(self, field_type, ident):
313-
if field_type == "boolean":
366+
if len(field_type) > 1:
367+
field_type = field_type[0] # We don't need details for arrays and objects
368+
369+
if field_type == self.TYPE_BOOLEAN:
314370
(val, ) = self._readStruct(">B")
315371
res = bool(val)
316-
elif field_type == "byte":
372+
elif field_type == self.TYPE_BYTE:
317373
(res, ) = self._readStruct(">b")
318-
elif field_type == "short":
374+
elif field_type == self.TYPE_SHORT:
319375
(res, ) = self._readStruct(">h")
320-
elif field_type == "integer":
376+
elif field_type == self.TYPE_INTEGER:
321377
(res, ) = self._readStruct(">i")
322-
elif field_type == "long":
378+
elif field_type == self.TYPE_LONG:
323379
(res, ) = self._readStruct(">q")
324-
elif field_type == "float":
380+
elif field_type == self.TYPE_FLOAT:
325381
(res, ) = self._readStruct(">f")
326-
elif field_type == "double":
382+
elif field_type == self.TYPE_DOUBLE:
327383
(res, ) = self._readStruct(">d")
328-
else:
384+
elif field_type == self.TYPE_OBJECT or field_type == self.TYPE_ARRAY:
329385
res = self.read_and_exec_opcode(ident=ident+1)
386+
else:
387+
raise RuntimeError("Unknown typecode: %s" % field_type)
330388
return res
331389

332390
def convert_char_to_type(self, type_char):
333-
if type(type_char) is str:
334-
type_char = ord(type_char)
335-
336-
if type_char == 0x44: # 'D': Double
337-
return "double"
338-
elif type_char == 0x49: # 'I': Integer
339-
return "integer"
340-
elif type_char == 0x4A: # 'J': Long
341-
return "long"
342-
elif type_char == 0x53: # 'S': Short
343-
return "short"
344-
elif type_char == 0x5A: # 'Z': Boolean
345-
return "boolean"
346-
elif type_char == 0x5B: # '[': Array
347-
return "array"
348-
elif type_char == 0x42: # 'B': Byte
349-
return "byte"
350-
elif type_char == 0x46: # 'F': Float
351-
return "float"
352-
elif type_char == 0x4C: # 'L': Object
353-
return "object"
391+
typecode = type_char
392+
print ">>>> type:", type(type_char)
393+
if type(type_char) is int:
394+
typecode = chr(type_char)
395+
396+
if typecode in self.TYPECODES_LIST:
397+
return typecode
354398
else:
355-
raise NotImplementedError("type 0x%X (%s) isn't implemented yet" % (0, type_char))
399+
raise RuntimeError("Typecode %s (%s) isn't supported." % (type_char, typecode))
400+
401+
def add_reference(self, obj):
402+
self.references.append(obj)
356403

404+
def dump_state(self):
405+
print "==Oops state dump" + "=" * (30 - 17)
406+
print "Referenes:", self.references
407+
print "=" * 30
357408
# =====================================================================================
358409

359410
def dump(self, obj):

0 commit comments

Comments
 (0)