Bug 503435: [otdre][impl] use ASM's CheckClassAdapter to harden the
transformer implementation
- improve verification support (classLoader)
- ensure return exists at all stages
- remove handlers and locals when removing code
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java
index 10a076b..1673139 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AbstractTransformableClassNode.java
@@ -277,6 +277,41 @@
 		}

 	}

 

+	protected void addReturn(InsnList instructions, Type returnType) {

+		switch (returnType.getSort()) {

+		case Type.VOID:

+			instructions.add(new InsnNode(Opcodes.RETURN));

+			break;

+		case Type.OBJECT:

+		case Type.ARRAY:

+			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

+			instructions.add(new InsnNode(Opcodes.ARETURN));

+			break;

+		case Type.INT:

+		case Type.BOOLEAN:

+		case Type.BYTE:

+		case Type.CHAR:

+		case Type.SHORT:

+			instructions.add(new InsnNode(Opcodes.ICONST_0));

+			instructions.add(new InsnNode(Opcodes.IRETURN));

+			break;

+		case Type.LONG:

+			instructions.add(new InsnNode(Opcodes.LCONST_0));

+			instructions.add(new InsnNode(Opcodes.LRETURN));

+			break;

+		case Type.FLOAT:

+			instructions.add(new InsnNode(Opcodes.FCONST_0));

+			instructions.add(new InsnNode(Opcodes.FRETURN));

+			break;

+		case Type.DOUBLE:

+			instructions.add(new InsnNode(Opcodes.DCONST_0));

+			instructions.add(new InsnNode(Opcodes.DRETURN));

+			break;

+		default:

+			throw new IllegalArgumentException("Unexpected type "+returnType);

+		}

+	}

+

 	/**

 	 * Create an instruction for loading an integer constant,

 	 * using the most compact possible format. 

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
index bea403d..7b32cc1 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmWritableBoundClass.java
@@ -174,7 +174,7 @@
 					if (verifying) {

 						final String [] prints = new String[1];

 						ByteArrayOutputStream out = new ByteArrayOutputStream(); 

-						CheckClassAdapter.verify(new ClassReader(bytes), false, new PrintWriter(out) {

+						CheckClassAdapter.verify(new ClassReader(bytes), this.loader, false, new PrintWriter(out) {

 							public void println(String x) {

 								super.println(x);

 								prints[0] = x;

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java
index 8d76ea0..ad16013 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/MoveCodeToCallOrigAdapter.java
@@ -115,15 +115,22 @@
 			}

 		}

 

+		InsnList orgInstructions = orgMethod.instructions;

+

 		if (superIsWeavable)

-			adjustSuperCalls(orgMethod.instructions, orgMethod.name, orgMethod.desc, args, returnType, boundMethodIdSlot);

+			adjustSuperCalls(orgInstructions, orgMethod.name, orgMethod.desc, args, returnType, boundMethodIdSlot);

 		

 		// replace return of the original method with areturn and box the result value if needed

-		replaceReturn(orgMethod.instructions, returnType);

+		replaceReturn(orgInstructions, returnType);

 		

-		newInstructions.add(orgMethod.instructions);

+		newInstructions.add(orgInstructions); // this wipes orgInstructions

+		addReturn(orgMethod.instructions,Type.getReturnType(orgMethod.desc)); // restores minimal code

 		if (orgMethod.tryCatchBlocks != null) {

 			addTryCatchBlocks(orgMethod, callOrig);

+			orgMethod.tryCatchBlocks.clear();

+		}

+		if (orgMethod.localVariables != null) {

+			orgMethod.localVariables.clear();

 		}

 		

 		addNewLabelToSwitch(callOrig.instructions, newInstructions, boundMethodId);