Skip to content

Commit bdd7b9b

Browse files
author
Timo Schmid
committed
better unmarshalling with new types
1 parent f4a2c7f commit bdd7b9b

File tree

1 file changed

+51
-20
lines changed

1 file changed

+51
-20
lines changed

javaobj.py

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,11 @@ def __init__(self, stream=None):
221221
self.TC_CLASSDESC: self.do_classdesc,
222222
self.TC_OBJECT: self.do_object,
223223
self.TC_STRING: self.do_string,
224+
self.TC_LONGSTRING: self.do_string_long,
224225
self.TC_ARRAY: self.do_array,
225226
self.TC_CLASS: self.do_class,
226227
self.TC_BLOCKDATA: self.do_blockdata,
228+
self.TC_BLOCKDATALONG: self.do_blockdata_long,
227229
self.TC_REFERENCE: self.do_reference,
228230
self.TC_ENUM: self.do_enum,
229231
self.TC_ENDBLOCKDATA: self.do_null, # note that we are reusing of do_null
@@ -234,6 +236,7 @@ def __init__(self, stream=None):
234236
self.object_stream = stream
235237
self._readStreamHeader()
236238
self.object_transformers = []
239+
self.data_left = True
237240

238241
def readObject(self):
239242
try:
@@ -244,8 +247,10 @@ def readObject(self):
244247
if len(the_rest):
245248
log_error("Warning!!!!: Stream still has %s bytes left. Enable debug mode of logging to see the hexdump." % len(the_rest))
246249
log_debug(self._create_hexdump(the_rest))
250+
self.data_left = True
247251
else:
248252
log_debug("Java Object unmarshalled succesfully!")
253+
self.data_left = False
249254
self.object_stream.seek(position_bak)
250255

251256
return res
@@ -275,11 +280,11 @@ def _readStruct(self, unpack):
275280
length = struct.calcsize(unpack)
276281
ba = self.object_stream.read(length)
277282
if len(ba) != length:
278-
raise RuntimeError("Stream has been ended unexpectedly while unmarshaling.")
283+
raise RuntimeError("Stream has been ended unexpectedly while unmarshaling. (%d vs %d)" % (len(ba), length))
279284
return struct.unpack(unpack, ba)
280285

281-
def _readString(self):
282-
(length, ) = self._readStruct(">H")
286+
def _readString(self, mod="H"):
287+
(length, ) = self._readStruct(">" + mod)
283288
ba = self.object_stream.read(length)
284289
return ba
285290

@@ -307,8 +312,9 @@ def do_classdesc(self, parent=None, ident=0):
307312
(serialVersionUID, newHandle, classDescFlags) = self._readStruct(">LLB")
308313
clazz.serialVersionUID = serialVersionUID
309314
clazz.flags = classDescFlags
315+
clazz.handle = newHandle
310316

311-
self._add_reference(clazz)
317+
self._add_reference(clazz, ident)
312318

313319
log_debug("Serial: 0x%X newHandle: 0x%X. classDescFlags: 0x%X" % (serialVersionUID, newHandle, classDescFlags), ident)
314320
(length, ) = self._readStruct(">H")
@@ -324,14 +330,14 @@ def do_classdesc(self, parent=None, ident=0):
324330

325331
if field_type == self.TYPE_ARRAY:
326332
opcode, field_type = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_STRING, self.TC_REFERENCE])
327-
assert type(field_type) is str
333+
assert type(field_type) is JavaString
328334
# if field_type is not None:
329335
# field_type = "array of " + field_type
330336
# else:
331337
# field_type = "array of None"
332338
elif field_type == self.TYPE_OBJECT:
333339
opcode, field_type = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_STRING, self.TC_REFERENCE])
334-
assert type(field_type) is str
340+
assert type(field_type) is JavaString
335341

336342
log_debug("FieldName: 0x%X" % typecode + " " + str(field_name) + " " + str(field_type), ident)
337343
assert field_name is not None
@@ -361,14 +367,22 @@ def do_blockdata(self, parent=None, ident=0):
361367
ba = self.object_stream.read(length)
362368
return ba
363369

370+
def do_blockdata_long(self, parent=None, ident=0):
371+
# TC_BLOCKDATALONG (int)<size> (byte)[size]
372+
log_debug("[blockdata]", ident)
373+
(length, ) = self._readStruct(">I")
374+
ba = self.object_stream.read(length)
375+
return ba
376+
377+
364378
def do_class(self, parent=None, ident=0):
365379
# TC_CLASS classDesc newHandle
366380
log_debug("[class]", ident)
367381

368382
# TODO: what to do with "(ClassDesc)prevObject". (see 3rd line for classDesc:)
369383
opcode, classdesc = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL, self.TC_REFERENCE])
370384
log_debug("Classdesc: %s" % classdesc, ident)
371-
self._add_reference(classdesc)
385+
self._add_reference(classdesc, ident)
372386
return classdesc
373387

374388
def do_object(self, parent=None, ident=0):
@@ -381,7 +395,7 @@ def do_object(self, parent=None, ident=0):
381395
opcode, classdesc = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL, self.TC_REFERENCE])
382396
# self.TC_REFERENCE hasn't shown in spec, but actually is here
383397

384-
self._add_reference(java_object)
398+
self._add_reference(java_object, ident)
385399

386400
# classdata[]
387401

@@ -430,7 +444,7 @@ def do_object(self, parent=None, ident=0):
430444
# Transform object
431445
for transformer in self.object_transformers:
432446
tmp_object = transformer.transform(java_object)
433-
if tmp_object != java_object:
447+
if tmp_object is not java_object:
434448
java_object = tmp_object
435449
break
436450

@@ -439,18 +453,24 @@ def do_object(self, parent=None, ident=0):
439453

440454
def do_string(self, parent=None, ident=0):
441455
log_debug("[string]", ident)
442-
ba = self._readString()
443-
self._add_reference(str(ba))
444-
return str(ba)
456+
ba = JavaString(self._readString())
457+
self._add_reference(ba, ident)
458+
return ba
459+
460+
def do_string_long(self, parent=None, ident=0):
461+
log_debug("[long string]", ident)
462+
ba = JavaString(self._readString("Q"))
463+
self._add_reference(ba, ident)
464+
return ba
445465

446466
def do_array(self, parent=None, ident=0):
447467
# TC_ARRAY classDesc newHandle (int)<size> values[size]
448468
log_debug("[array]", ident)
449469
opcode, classdesc = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL, self.TC_REFERENCE])
450470

451-
array = []
471+
array = JavaArray(classdesc)
452472

453-
self._add_reference(array)
473+
self._add_reference(array, ident)
454474

455475
(size, ) = self._readStruct(">i")
456476
log_debug("size: " + str(size), ident)
@@ -482,11 +502,14 @@ def do_null(self, parent=None, ident=0):
482502

483503
def do_enum(self, parent=None, ident=0):
484504
# TC_ENUM classDesc newHandle enumConstantName
485-
enum = JavaObject()
505+
enum = JavaEnum()
486506
opcode, classdesc = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_CLASSDESC, self.TC_PROXYCLASSDESC, self.TC_NULL, self.TC_REFERENCE])
487-
self._add_reference(enum)
507+
enum.classdesc = classdesc
508+
self._add_reference(enum, ident)
488509
opcode, enumConstantName = self._read_and_exec_opcode(ident=ident+1, expect=[self.TC_STRING, self.TC_REFERENCE])
489-
return enumConstantName
510+
511+
enum.constant = enumConstantName
512+
return enum
490513

491514
def _create_hexdump(self, src, length=16):
492515
FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])
@@ -500,6 +523,7 @@ def _create_hexdump(self, src, length=16):
500523

501524
def _read_value(self, field_type, ident, name = ""):
502525
if len(field_type) > 1:
526+
cls = field_type[1:]
503527
field_type = field_type[0] # We don't need details for arrays and objects
504528

505529
if field_type == self.TYPE_BOOLEAN:
@@ -518,7 +542,13 @@ def _read_value(self, field_type, ident, name = ""):
518542
elif field_type == self.TYPE_DOUBLE:
519543
(res, ) = self._readStruct(">d")
520544
elif field_type == self.TYPE_OBJECT or field_type == self.TYPE_ARRAY:
521-
opcode, res = self._read_and_exec_opcode(ident=ident+1)
545+
try:
546+
opcode, res = self._read_and_exec_opcode(ident=ident+1)
547+
except RuntimeError:
548+
if cls == 'java/lang/String;':
549+
res = JavaString(self._readString())
550+
else:
551+
raise
522552
else:
523553
raise RuntimeError("Unknown typecode: %s" % field_type)
524554
log_debug("* %s %s: " % (field_type, name) + str(res), ident)
@@ -534,14 +564,15 @@ def _convert_char_to_type(self, type_char):
534564
else:
535565
raise RuntimeError("Typecode %s (%s) isn't supported." % (type_char, typecode))
536566

537-
def _add_reference(self, obj):
567+
def _add_reference(self, obj, ident=0):
568+
log_debug('## New reference handle 0x%X' % (len(self.references) + self.BASE_REFERENCE_IDX,), ident)
538569
self.references.append(obj)
539570

540571
def _oops_dump_state(self):
541572
log_error("==Oops state dump" + "=" * (30 - 17))
542573
log_error("References: %s" % str(self.references))
543574
log_error("Stream seeking back at -16 byte (2nd line is an actual position!):")
544-
self.object_stream.seek(-16, mode=1)
575+
self.object_stream.seek(-16, 1)
545576
the_rest = self.object_stream.read()
546577
if len(the_rest):
547578
log_error("Warning!!!!: Stream still has %s bytes left." % len(the_rest))

0 commit comments

Comments
 (0)