|
|
|
@ -45,6 +45,8 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
public final static int ACCESSPUTSTATIC = 6; |
|
|
|
|
public final static int ACCESSSTATICMETHOD = 7; |
|
|
|
|
public final static int ACCESSCONSTRUCTOR = 8; |
|
|
|
|
public final static int ACCESSDUPPUTFIELD = 9; |
|
|
|
|
public final static int ACCESSDUPPUTSTATIC = 10; |
|
|
|
|
|
|
|
|
|
int kind = UNKNOWN; |
|
|
|
|
Reference reference; |
|
|
|
@ -141,25 +143,23 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private final int modifierMask = (Modifier.PRIVATE | Modifier.PROTECTED | |
|
|
|
|
Modifier.PUBLIC | Modifier.STATIC); |
|
|
|
|
private final int modifierMask = Modifier.PUBLIC | Modifier.STATIC; |
|
|
|
|
|
|
|
|
|
public boolean checkStaticAccess() { |
|
|
|
|
ClassInfo clazzInfo = method.getClazzInfo(); |
|
|
|
|
BytecodeInfo bytecode = method.getBytecode(); |
|
|
|
|
Iterator iter = bytecode.getInstructions().iterator(); |
|
|
|
|
boolean dupSeen = false; |
|
|
|
|
|
|
|
|
|
Instruction instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() == opc_getstatic) { |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
FieldInfo refField |
|
|
|
|
= clazzInfo.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != |
|
|
|
|
(Modifier.PRIVATE | Modifier.STATIC)) |
|
|
|
|
= refClazz.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != Modifier.STATIC) |
|
|
|
|
return false; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() < opc_ireturn |
|
|
|
@ -179,38 +179,50 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
|| instr.getOpcode() == opc_dload) ? 2 : 1; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == (opc_dup - 3) + 3 * slot) { |
|
|
|
|
/* This is probably a opc_dup or opc_dup2, |
|
|
|
|
* preceding a opc_putstatic |
|
|
|
|
*/ |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() != opc_putstatic) |
|
|
|
|
return false; |
|
|
|
|
dupSeen = true; |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == opc_putstatic) { |
|
|
|
|
if (params != 1) |
|
|
|
|
return false; |
|
|
|
|
/* For valid bytecode the type of param matches automatically */ |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
FieldInfo refField |
|
|
|
|
= clazzInfo.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != |
|
|
|
|
(Modifier.PRIVATE | Modifier.STATIC)) |
|
|
|
|
= refClazz.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != Modifier.STATIC) |
|
|
|
|
return false; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() != opc_return) |
|
|
|
|
return false; |
|
|
|
|
if (dupSeen) { |
|
|
|
|
if (instr.getOpcode() < opc_ireturn |
|
|
|
|
|| instr.getOpcode() > opc_areturn) |
|
|
|
|
return false; |
|
|
|
|
kind = ACCESSDUPPUTSTATIC; |
|
|
|
|
} else { |
|
|
|
|
if (instr.getOpcode() != opc_return) |
|
|
|
|
return false; |
|
|
|
|
kind = ACCESSPUTSTATIC; |
|
|
|
|
} |
|
|
|
|
reference = ref; |
|
|
|
|
kind = ACCESSPUTSTATIC; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == opc_invokestatic) { |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
MethodInfo refMethod |
|
|
|
|
= clazzInfo.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
= refClazz.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
MethodType refType = Type.tMethod(ref.getType()); |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != |
|
|
|
|
(Modifier.PRIVATE | Modifier.STATIC) |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != Modifier.STATIC |
|
|
|
|
|| refType.getParameterTypes().length != params) |
|
|
|
|
return false; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
@ -235,6 +247,7 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
ClassInfo clazzInfo = method.getClazzInfo(); |
|
|
|
|
BytecodeInfo bytecode = method.getBytecode(); |
|
|
|
|
Handler[] excHandlers = bytecode.getExceptionHandlers(); |
|
|
|
|
boolean dupSeen = false; |
|
|
|
|
if (excHandlers != null && excHandlers.length != 0) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
@ -251,13 +264,12 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
|
|
|
|
|
if (instr.getOpcode() == opc_getfield) { |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
FieldInfo refField |
|
|
|
|
= clazzInfo.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE) |
|
|
|
|
= refClazz.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != 0) |
|
|
|
|
return false; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() < opc_ireturn |
|
|
|
@ -277,36 +289,51 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
|| instr.getOpcode() == opc_dload) ? 2 : 1; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == (opc_dup_x1 - 6) + 3 * slot) { |
|
|
|
|
/* This is probably a opc_dup_x1 or opc_dup2_x1, |
|
|
|
|
* preceding a opc_putfield |
|
|
|
|
*/ |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() != opc_putfield) |
|
|
|
|
return false; |
|
|
|
|
dupSeen = true; |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == opc_putfield) { |
|
|
|
|
if (params != 1) |
|
|
|
|
return false; |
|
|
|
|
/* For valid bytecode the type of param matches automatically */ |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
FieldInfo refField |
|
|
|
|
= clazzInfo.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != Modifier.PRIVATE) |
|
|
|
|
= refClazz.findField(ref.getName(), ref.getType()); |
|
|
|
|
if ((refField.getModifiers() & modifierMask) != 0) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
|
if (instr.getOpcode() != opc_return) |
|
|
|
|
return false; |
|
|
|
|
if (dupSeen) { |
|
|
|
|
if (instr.getOpcode() < opc_ireturn |
|
|
|
|
|| instr.getOpcode() > opc_areturn) |
|
|
|
|
return false; |
|
|
|
|
kind = ACCESSDUPPUTFIELD; |
|
|
|
|
} else { |
|
|
|
|
if (instr.getOpcode() != opc_return) |
|
|
|
|
return false; |
|
|
|
|
kind = ACCESSPUTFIELD; |
|
|
|
|
} |
|
|
|
|
reference = ref; |
|
|
|
|
kind = ACCESSPUTFIELD; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
if (instr.getOpcode() == opc_invokespecial) { |
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (!refClazz.superClassOf(clazzInfo)) |
|
|
|
|
return false; |
|
|
|
|
MethodInfo refMethod |
|
|
|
|
= clazzInfo.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
= refClazz.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
MethodType refType = Type.tMethod(ref.getType()); |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != 0 |
|
|
|
|
|| refType.getParameterTypes().length != params) |
|
|
|
|
return false; |
|
|
|
|
instr = (Instruction) iter.next(); |
|
|
|
@ -364,14 +391,13 @@ public class SyntheticAnalyzer implements Opcodes { |
|
|
|
|
unifyParam = params++; |
|
|
|
|
|
|
|
|
|
Reference ref = instr.getReference(); |
|
|
|
|
String refClazz = ref.getClazz().substring(1); |
|
|
|
|
if (!(refClazz.substring(0, refClazz.length()-1) |
|
|
|
|
.equals(clazzInfo.getName().replace('.','/')))) |
|
|
|
|
ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); |
|
|
|
|
if (refClazz != clazzInfo) |
|
|
|
|
return false; |
|
|
|
|
MethodInfo refMethod |
|
|
|
|
= clazzInfo.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
= refClazz.findMethod(ref.getName(), ref.getType()); |
|
|
|
|
MethodType refType = Type.tMethod(ref.getType()); |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE |
|
|
|
|
if ((refMethod.getModifiers() & modifierMask) != 0 |
|
|
|
|
|| !refMethod.getName().equals("<init>") |
|
|
|
|
|| unifyParam == -1 |
|
|
|
|
|| refType.getParameterTypes().length != params - 2) |
|
|
|
|