private Object sawInvokeSpecial(Object userObject) { Object returnValue = userObject; String methodName = getNameConstantOperand(); if (Values.CONSTRUCTOR.equals(methodName)) { String clsName = getClassConstantOperand().replace('/', '.'); if (doesObjectNeedToBeWatched(clsName)) { returnValue = Boolean.TRUE; } } processMethodParms(); return returnValue; }
/** * looks for methods that have it's parameters all follow the form arg0, arg1, arg2, or parm0, * parm1, parm2 etc, where the method actually has code in it * * @param cls the class to check */ private void checkIDEGeneratedParmNames(JavaClass cls) { methods: for (Method m : cls.getMethods()) { if (!m.isPublic()) { continue; } String name = m.getName(); if (Values.CONSTRUCTOR.equals(name) || Values.STATIC_INITIALIZER.equals(name)) { continue; } LocalVariableTable lvt = m.getLocalVariableTable(); if (lvt == null) { continue; } if (m.getCode().getCode().length <= MAX_EMPTY_METHOD_SIZE) { continue; } int numArgs = m.getArgumentTypes().length; if (numArgs == 0) { continue; } int offset = m.isStatic() ? 0 : 1; for (int i = 0; i < numArgs; i++) { LocalVariable lv = lvt.getLocalVariable(offset + i, 0); if ((lv == null) || (lv.getName() == null)) { continue methods; } Matcher ma = ARG_PATTERN.matcher(lv.getName()); if (!ma.matches()) { continue methods; } } bugReporter.reportBug( new BugInstance( this, BugType.IMC_IMMATURE_CLASS_IDE_GENERATED_PARAMETER_NAMES.name(), NORMAL_PRIORITY) .addClass(cls) .addMethod(cls, m)); return; } }
@Override public void sawOpcode(int seen) { try { stack.precomputation(this); int pc = getPC(); if ((loopEnd != -1) && (pc > loopEnd)) { loopStart = -1; loopEnd = -1; regValueType.clear(); } if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) { int reg = RegisterUtils.getALoadReg(this, seen); State type = regValueType.get(Integer.valueOf(reg)); if (type != null) state = type; else state = State.SEEN_NOTHING; return; } if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); int reg = RegisterUtils.getAStoreReg(this, seen); regValueType.put(Integer.valueOf(reg), (State) item.getUserValue()); } state = State.SEEN_NOTHING; return; } if ((seen == ILOAD) || ((seen >= ILOAD_0) && (seen <= ILOAD_3))) { int reg = RegisterUtils.getLoadReg(this, seen); State type = regValueType.get(Integer.valueOf(reg)); if (type != null) state = type; else state = State.SEEN_NOTHING; return; } if ((seen == ISTORE) || ((seen >= ISTORE_0) && (seen <= ISTORE_3))) { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); int reg = RegisterUtils.getStoreReg(this, seen); regValueType.put(Integer.valueOf(reg), (State) item.getUserValue()); } state = State.SEEN_NOTHING; return; } switch (state) { case SEEN_NOTHING: if (seen == INVOKESPECIAL) { if (("java/util/StringTokenizer".equals(getClassConstantOperand())) && (Values.CONSTRUCTOR.equals(getNameConstantOperand())) && ("(Ljava/lang/String;Ljava/lang/String;)V".equals(getSigConstantOperand()))) state = State.SEEN_STRINGTOKENIZER; } break; case SEEN_STRINGTOKENIZER: if (seen == INVOKEVIRTUAL) { String methodName = getNameConstantOperand(); String signature = getSigConstantOperand(); if (("countTokens".equals(methodName)) && ("()I".equals(signature))) state = State.SEEN_COUNTTOKENS; else if ("hasMoreTokens".equals(methodName) || "hasMoreElements".equals(methodName)) state = State.SEEN_HASMORE; else if ("nextToken".equals(methodName) || "nextElement".equals(methodName)) { if ((pc < loopStart) || (pc > loopEnd)) regValueType.clear(); else state = State.SEEN_NEXT; } } break; case SEEN_COUNTTOKENS: if (seen == ANEWARRAY) state = State.SEEN_NEWARRAY; else if (seen == IF_ICMPGE) { int target = getBranchTarget() - 3; // sizeof goto byte[] code = getCode().getCode(); if ((code[target] & 0x000000FF) == GOTO) { int offset = (code[target + 1] << 1) + code[target + 2]; int gotoTarget = target + offset + 3; if (gotoTarget < getPC()) { loopStart = gotoTarget; loopEnd = target; } } } break; case SEEN_HASMORE: if (seen == IFEQ) { int target = getBranchTarget() - 3; // sizeof goto byte[] code = getCode().getCode(); if ((code[target] & 0x000000FF) == GOTO) { int offset = (code[target + 1] << 1) + code[target + 2]; int gotoTarget = target + offset + 3; if (gotoTarget < getPC()) { loopStart = gotoTarget; loopEnd = target; } } } state = State.SEEN_NOTHING; break; case SEEN_NEXT: if (seen == AASTORE) { if ((pc > loopStart) && (pc < loopEnd)) { if (stack.getStackDepth() > 2) { OpcodeStack.Item arrayItem = stack.getStackItem(2); State arrayType = (State) arrayItem.getUserValue(); OpcodeStack.Item elemItem = stack.getStackItem(0); State elemType = (State) elemItem.getUserValue(); if ((arrayType == State.SEEN_NEWARRAY) && (elemType == State.SEEN_NEXT)) { bugReporter.reportBug( new BugInstance(this, BugType.USS_USE_STRING_SPLIT.name(), NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this)); } } } } state = State.SEEN_NOTHING; break; case SEEN_ARRAYSTORE: case SEEN_NEWARRAY: break; } } finally { TernaryPatcher.pre(stack, seen); stack.sawOpcode(this, seen); TernaryPatcher.post(stack, seen); if (state != State.SEEN_NOTHING) { if (stack.getStackDepth() > 0) { OpcodeStack.Item item = stack.getStackItem(0); item.setUserValue(state); } } } }