Purifier1 Special Cases

Stack Order Swap Issue

Brief Description

The StackMap attribute stores the OperandStack from bottom entry to top. Earlier implementations of the Purifier1 incorrectly assumed that the order was from top to bottom.

Status

Fix implemented, but not tested yet.

Action Items

  1. Test the implementation.

Test Cases Exhibiting Issue

Test Cases Exhibiting Exception Handler Object Conflict Issue
Package Class Method Method # Effect Source
org.spruce.midp.alarmclock a a 22 Fails midlet.org
AlarmClock commandAction 5
b(boolean) 16
k 17
a 18
e paint 5
e a 8
e a 13
org.spruce.midp.common c a 8
examples.stock StockMidlet checkAlerts(String) 8 Wireless Toolkit 1.04
Stock convert(int) 11
example.http HttpView run() 6
example.chooser ColorChooser colorPaint(Graphics) 19
com.markcrocker.purifier.testcases SpecialCases newObjectOnStack() 11 Purifier1

Details

A number of methods have been found in a third party free midlet that is being used for testing against Midlets found in "the wild". This Midlet Suite does not have any source code available and has clearly been obfuscated. The StackMap that is in these methods has items on the stack that are out of order compared to what the Purifier1 produces for the same method.

These stack items seem to be out of order, when seen from the point of view of reading the code by hand. However, it is simply an issue of storing the data in reverse order.

Example

The org.spruce.midp.alarmclock.AlarmClock.b(boolean) method provides an example of this situation.

Source Code

No source code is available

Bytecode

The following byte code is from the compiled, preverified and obfuscated class file extracted from the Spruce Alarm Clock distribution. The method is quite large, so only excerpts are presented here. The StackMap has also been reformatted for readability.

80:     invokespecial	org.spruce.midp.alarmclock.AlarmClock.a (Z)V (86)
83:     aload_0
84:     getfield	org.spruce.midp.alarmclock.AlarmClock.c Lorg/spruce/midp/alarmclock/e; (66)
87:     iload_1
88:     ifeq 7
91:     iconst_2
92:     goto 4
95:     iconst_0
96:     invokevirtual	org.spruce.midp.alarmclock.e.a (I)V (67)
99:     return

StackMap(
	(
		offset = 95,
		locals = {
			(type=Object, (183)class=org.spruce.midp.alarmclock.AlarmClock),
			(type=Integer)
		},
		stack items = {
			(type=Object, (64)class=org.spruce.midp.alarmclock.e)
		}
	)
	(
		offset = 96,
		locals = {
			(type=Object, (183)class=org.spruce.midp.alarmclock.AlarmClock),
			(type=Integer)
		},
		stack items = {
			(type=Object, (64)class=org.spruce.midp.alarmclock.e),
			(type=Integer)
		}
	)
)

Data Flow Analysis

According to both the StackMap and the Purifier1's DFA, the only item on the stack at offset 95 is an org.spruce.midp.alarmclock.e object. Executing the instruction at offset 95, iconst_0 should simply add an integer to the top of the stack. However, the StackMap that is associated with the method has the order of these items on the stack in reverse order for the entry at offset 96.

Other ways of evaluating the code lead to the same conclusion. If the control path is followed from after the ifeq instruction at offset 88, the iconst_2 at offset 91 also leaves an integer on the top of the stack before going to offset 96 via the goto instruction at offset 93. Finally, the invokevirtual at offset 96 expects an integer as the argument, so the integer should be on the top of the stack.

The StackMap entry produced by an earlier verion of the Purifier1 for offset 96 was:

stack items = {
	(type=Integer),
	(type=Object, (64)class=org.spruce.midp.alarmclock.e)
}

Although this agrees with the DFA above, it disagrees with the StackMap that is included in the method attributes, but only because the StackMap is printed out in the wrong order.

Solutions

Swap the order of the StackMapEntry[] returned by getStackItems in the OperandStack class.

Back to Developer's Guide   Purifier1 Home Page

Valid HTML 4.01!