/** * Return whether or not the given instruction can throw exceptions. * * @param handle * the instruction * @return true if the instruction can throw an exception, false otherwise */ private boolean isPEI(InstructionHandle handle) { Instruction ins = handle.getInstruction(); if (!(ins instanceof ExceptionThrower)) return false; if (ins instanceof NEW) return false; // if (ins instanceof ATHROW) return false; if (ins instanceof GETSTATIC) return false; if (ins instanceof PUTSTATIC) return false; if (ins instanceof ReturnInstruction) return false; if (ins instanceof INSTANCEOF) return false; if (ins instanceof MONITOREXIT) return false; if (ins instanceof LDC) return false; return true; }
/** * @param aInstruction * @param aPoolGen */ public PUTSTATICReference( PUTSTATIC aInstruction, ConstantPoolGen aPoolGen) { super(aInstruction, aPoolGen); }
public void visitPUTSTATIC(PUTSTATIC s) { String one = s.getClassName(poolGen); String two = s.getFieldName(poolGen); String three = s.getName(poolGen); String four = s.getSignature(poolGen); String five = s.getClassType(poolGen) + ""; String six = s.getFieldType(poolGen) + ""; log.log(" instr(putstatic)a=" + one, Project.MSG_DEBUG); log.log(" instr(putstatic)b=" + two, Project.MSG_DEBUG); log.log(" instr(putstatic)c=" + three, Project.MSG_DEBUG); log.log(" instr(putstatic)d=" + four, Project.MSG_DEBUG); log.log(" instr(putstatic)e=" + five, Project.MSG_DEBUG); log.log(" instr(putstatic)f=" + six, Project.MSG_DEBUG); String className = s.getFieldName(poolGen); if ("staticField".equals(className)) return; if (className.startsWith("class$") || className.startsWith("array$")) ; else return; log.log(" instr(putstatic)1=" + className, Project.MSG_DEBUG); className = className.substring(6, className.length()); log.log(" instr(putstatic)2=" + className, Project.MSG_DEBUG); className = className.replace('$', '.'); log.log(" instr(putstatic)3=" + className, Project.MSG_DEBUG); design.checkClass(className); }
@Override public void visitPUTSTATIC(PUTSTATIC obj) { if (doForwardSubstitution()) { XField xfield = Hierarchy.findXField(obj, getCPG()); if (xfield != null) { storeStaticField(xfield, obj, false); return; } } handleNormalInstruction(obj); }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitPUTSTATIC(PUTSTATIC o){ try { String field_name = o.getFieldName(cpg); JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName()); Field[] fields = jc.getFields(); Field f = null; for (int i=0; i<fields.length; i++){ if (fields[i].getName().equals(field_name)){ f = fields[i]; break; } } if (f == null){ throw new AssertionViolatedException("Field not found?!?"); } if (f.isFinal()){ if (!(myOwner.getClassName().equals(o.getClassType(cpg).getClassName()))){ constraintViolated(o, "Referenced field '"+f+"' is final and must therefore be declared in the current class '"+myOwner.getClassName()+"' which is not the case: it is declared in '"+o.getClassType(cpg).getClassName()+"'."); } } if (! (f.isStatic())){ constraintViolated(o, "Referenced field '"+f+"' is not static which it should be."); } String meth_name = Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getName(); // If it's an interface, it can be set only in <clinit>. if ((!(jc.isClass())) && (!(meth_name.equals(Constants.STATIC_INITIALIZER_NAME)))){ constraintViolated(o, "Interface field '"+f+"' must be set in a '"+Constants.STATIC_INITIALIZER_NAME+"' method."); } } catch (ClassNotFoundException e) { // FIXME: maybe not the best way to handle this throw new AssertionViolatedException("Missing class: " + e.toString()); } }
/** @see org.apache.bcel.generic.Visitor */ public void visitPUTSTATIC(PUTSTATIC aPUTSTATIC) { addFieldReference( new PUTSTATICReference(aPUTSTATIC, mCurrentPoolGen)); }
void initSpawnTargets(InstructionList il) { for (int i = 0; i < idTable.size(); i++) { InstructionList storeIns = getStoreIns(i); if (storeIns == null) { continue; } if (isArrayStore(storeIns.getStart())) { continue; } Instruction store = storeIns.getStart().getInstruction(); if (store instanceof LSTORE) { il.insert(new LCONST(0)); il.append(il.getStart(), store); } else if (store instanceof ISTORE) { il.insert(new ICONST(0)); il.append(il.getStart(), store); } else if (store instanceof FSTORE) { il.insert(new FCONST((float) 0.0)); il.append(il.getStart(), store); } else if (store instanceof DSTORE) { il.insert(new DCONST(0.0)); il.append(il.getStart(), store); } else if (store instanceof ASTORE) { il.insert(new ACONST_NULL()); il.append(il.getStart(), store); } else if (store instanceof PUTFIELD) { // no need to init. } else if (store instanceof PUTSTATIC) { // no need to init. } else if (store instanceof ALOAD) { // no need to init. } else { System.err.println("WARNING: Unhandled store instruction in " + "initSpawnTargets, opcode = " + store.getOpcode() + " ins = " + store); // System.exit(1); } } }
@Override public void run() { String args[] = EntryPoint.getArgs(); String inputJarFileName = args[0]; String outputSrgMappingsFileName = args[1]; try ( PrintWriter outputSrgMappingWriter = new PrintWriter(outputSrgMappingsFileName); JarFile inputJarFile = new JarFile(inputJarFileName) ) { for (JarEntry jarEntry : new EnumerationIterator<>(inputJarFile.entries())) { if (jarEntry.isDirectory() || !jarEntry.getName().endsWith(".class")) { continue; } String original = Utils.stripClassEnding(jarEntry.getName()); JavaClass clazz = new ClassParser(inputJarFile.getInputStream(jarEntry), original).parse(); if (clazz.isEnum()) { Method staticInit = getCLInit(clazz); //skip enums with no static init method if (staticInit == null) { continue; } ConstantPoolGen cpGen = new ClassGen(clazz).getConstantPool(); MethodGen methodGen = new MethodGen(staticInit, clazz.getClassName(), cpGen); Iterator<Instruction> instrIter = Arrays.asList(methodGen.getInstructionList().getInstructions()).iterator(); while (instrIter.hasNext()) { //first goes NEW Instruction instr = instrIter.next(); if (!(instr instanceof NEW)) { break; } //but it may actually be another new, so we check if it is for enum constant if (!((NEW) instr).getLoadClassType(cpGen).getClassName().equals(clazz.getClassName())) { break; } //then goes dup, skip it instrIter.next(); //LDC with our real enum name String realName = (String) ((LDC) instrIter.next()).getValue(cpGen); //now skip everything, until we reach invokespecial with <init> for this enum field while (true) { Instruction nextInstr = instrIter.next(); if (nextInstr instanceof INVOKESPECIAL) { INVOKESPECIAL ispecial = ((INVOKESPECIAL) nextInstr); if (ispecial.getMethodName(cpGen).equals("<init>") && (ispecial.getClassName(cpGen).equals(clazz.getClassName()))) { break; } } } //next is putstatic with our obufscated field name PUTSTATIC putstatic = (PUTSTATIC) instrIter.next(); String obfName = putstatic.getFieldName(cpGen); //now print the mapping outputSrgMappingWriter.println(MappingUtils.createSRG(clazz.getClassName(), obfName, realName)); } } } } catch (Throwable t) { t.printStackTrace(); } }
@Override public void visitPUTSTATIC(PUTSTATIC putstatic) { handleFieldStore(putstatic); }
@Override public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { Instruction instruction = handle.getInstruction(); if (fact.isTop()) return; Location location = new Location(handle, basicBlock); // If this is a call to an assertion method, // change the dataflow value to be TOP. // We don't want to report future derefs that would // be guaranteed only if the assertion methods // returns normally. // TODO: at some point, evaluate whether we should revisit this if (isAssertion(handle) // || handle.getInstruction() instanceof ATHROW ) { if (DEBUG) System.out.println("MAKING BOTTOM0 AT: " + location); fact.clear(); return; } // Get value number frame ValueNumberFrame vnaFrame = vnaDataflow.getFactAtLocation(location); if (!vnaFrame.isValid()) { if (DEBUG) System.out.println("MAKING TOP1 AT: " + location); // Probably dead code. // Assume this location can't be reached. makeFactTop(fact); return; } if (isNullCheck(handle, methodGen.getConstantPool())) { handleNullCheck(location, vnaFrame, fact); } // Check for calls to a method that unconditionally dereferences // a parameter. Mark any such arguments as derefs. if (CHECK_CALLS && instruction instanceof InvokeInstruction) { checkUnconditionalDerefDatabase(location, vnaFrame, fact); } // If this is a method call instruction, // check to see if any of the parameters are @NonNull, // and treat them as dereferences. if (CHECK_ANNOTATIONS && instruction instanceof InvokeInstruction) { checkNonNullParams(location, vnaFrame, fact); } if (CHECK_ANNOTATIONS && instruction instanceof ARETURN) { XMethod thisMethod = XFactory.createXMethod(methodGen); checkNonNullReturnValue(thisMethod, location, vnaFrame, fact); } if (CHECK_ANNOTATIONS && (instruction instanceof PUTFIELD || instruction instanceof PUTSTATIC)) { checkNonNullPutField(location, vnaFrame, fact); } // Check to see if an instance value is dereferenced here checkInstance(location, vnaFrame, fact); if (false) fact.cleanDerefSet(location, vnaFrame); if (DEBUG && fact.isTop()) System.out.println("MAKING TOP2 At: " + location); }
/** * Is the instruction a write of a field? * * @param ins * the Instruction to check * @param cpg * ConstantPoolGen of the method containing the instruction * @return the Field if instruction is a write of a field, null otherwise */ public static FieldAnnotation isWrite(Instruction ins, ConstantPoolGen cpg) { if (ins instanceof PUTFIELD || ins instanceof PUTSTATIC) { FieldInstruction fins = (FieldInstruction) ins; String className = fins.getClassName(cpg); return new FieldAnnotation(className, fins.getName(cpg), fins.getSignature(cpg), fins instanceof PUTSTATIC); } else return null; }