use of com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException in project fb-contrib by mebigfatguy.
the class MethodInfo method visitCode.
/**
* implements the visitor to check to see what Const were returned from a comparator. If no Const were returned it can't determine anything, however if only
* Const were returned, it looks to see if negative positive and zero was returned. It also looks to see if a non zero value is returned unconditionally.
* While it is possible that later check is ok, it usually means something is wrong.
*
* @param obj
* the currently parsed code block
*/
@Override
public void visitCode(Code obj) {
if (getMethod().isSynthetic()) {
return;
}
String methodName = getMethodName();
String methodSig = getMethodSig();
if (methodName.equals(methodInfo.methodName) && methodSig.endsWith(methodInfo.signatureEnding) && (SignatureUtils.getNumParameters(methodSig) == methodInfo.argumentCount)) {
stack.resetForMethodEntry(this);
seenNegative = false;
seenPositive = false;
seenZero = false;
seenUnconditionalNonZero = false;
furthestBranchTarget = -1;
sawConstant = null;
try {
super.visitCode(obj);
if (!seenZero || seenUnconditionalNonZero || (obj.getCode().length > 2)) {
boolean seenAll = seenNegative & seenPositive & seenZero;
if (!seenAll || seenUnconditionalNonZero) {
bugReporter.reportBug(new BugInstance(this, BugType.SCRV_SUSPICIOUS_COMPARATOR_RETURN_VALUES.name(), seenAll ? LOW_PRIORITY : NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this, 0));
}
}
} catch (StopOpcodeParsingException e) {
// indeterminate
}
}
}
use of com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException in project fb-contrib by mebigfatguy.
the class OverlyConcreteParameter method sawOpcode.
/**
* implements the visitor to filter out parameter use where the actual defined type of the method declaration is needed. What remains could be more
* abstractly defined.
*
* @param seen
* the currently parsed opcode
*/
@Override
public void sawOpcode(final int seen) {
try {
stack.precomputation(this);
if (OpcodeUtils.isInvoke(seen)) {
String methodSig = getSigConstantOperand();
List<String> parmTypes = SignatureUtils.getParameterSignatures(methodSig);
int stackDepth = stack.getStackDepth();
if (stackDepth >= parmTypes.size()) {
for (int i = 0; i < parmTypes.size(); i++) {
OpcodeStack.Item itm = stack.getStackItem(i);
int reg = itm.getRegisterNumber();
removeUselessDefiners(parmTypes.get(parmTypes.size() - i - 1), reg);
}
}
if ((seen != Const.INVOKESPECIAL) && (seen != Const.INVOKESTATIC)) {
if (stackDepth > parmTypes.size()) {
OpcodeStack.Item itm = stack.getStackItem(parmTypes.size());
int reg = itm.getRegisterNumber();
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
removeUselessDefiners(reg);
}
} else {
parameterDefiners.clear();
}
}
} else if ((seen == Const.PUTFIELD) || (seen == Const.GETFIELD) || (seen == Const.PUTSTATIC) || (seen == Const.GETSTATIC) || OpcodeUtils.isAStore(seen)) {
// Don't check parameters that are aliased
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
int reg = itm.getRegisterNumber();
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
}
} else {
parameterDefiners.clear();
}
if ((seen == Const.GETFIELD) || (seen == Const.PUTFIELD)) {
if (stack.getStackDepth() > 1) {
OpcodeStack.Item itm = stack.getStackItem(1);
int reg = itm.getRegisterNumber();
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
}
} else {
parameterDefiners.clear();
}
}
} else if (OpcodeUtils.isALoad(seen)) {
int reg = RegisterUtils.getALoadReg(this, seen);
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
usedParameters.set(reg);
}
} else if (seen == Const.AASTORE) {
// Don't check parameters that are stored in
if (stack.getStackDepth() >= 3) {
OpcodeStack.Item itm = stack.getStackItem(0);
int reg = itm.getRegisterNumber();
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
}
} else {
parameterDefiners.clear();
}
} else if (seen == Const.ARETURN) {
if (stack.getStackDepth() >= 1) {
OpcodeStack.Item item = stack.getStackItem(0);
int reg = item.getRegisterNumber();
int parm = reg;
if (!methodIsStatic) {
parm--;
}
if ((parm >= 0) && (parm < parmCount)) {
parameterDefiners.remove(Integer.valueOf(reg));
}
} else {
parameterDefiners.clear();
}
}
if (parameterDefiners.isEmpty()) {
throw new StopOpcodeParsingException();
}
} finally {
stack.sawOpcode(this, seen);
}
}
use of com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException in project fb-contrib by mebigfatguy.
the class PartiallyConstructedObjectAccess method visitCode.
@Override
public void visitCode(final Code obj) {
stack.resetForMethodEntry(this);
String methodName = getMethodName();
isCtor = Values.CONSTRUCTOR.equals(methodName);
if (!Values.STATIC_INITIALIZER.equals(methodName)) {
Method m = getMethod();
methodToCalledMethods.put(m, new HashMap<Method, SourceLineAnnotation>());
try {
super.visitCode(obj);
if (methodToCalledMethods.get(m).isEmpty()) {
methodToCalledMethods.remove(getMethod());
}
} catch (StopOpcodeParsingException e) {
methodToCalledMethods.remove(getMethod());
}
}
}
use of com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException in project fb-contrib by mebigfatguy.
the class PoorMansEnum method visitClassContext.
@Override
public void visitClassContext(ClassContext classContext) {
try {
JavaClass cls = classContext.getJavaClass();
if (cls.getMajor() >= Const.MAJOR_1_5) {
fieldValues = new HashMap<>();
nameToField = new HashMap<>();
for (Field f : cls.getFields()) {
if (f.isPrivate() && !f.isSynthetic()) {
String fieldName = f.getName();
// preallocating a set per field is just a waste, so just insert the empty set as a place holder
fieldValues.put(fieldName, Collections.emptySet());
nameToField.put(fieldName, f);
}
}
if (!fieldValues.isEmpty()) {
stack = new OpcodeStack();
firstFieldUse = new HashMap<>();
try {
super.visitClassContext(classContext);
for (Map.Entry<String, Set<Object>> fieldInfo : fieldValues.entrySet()) {
Set<Object> values = fieldInfo.getValue();
if (values.size() >= 3) {
String fieldName = fieldInfo.getKey();
bugReporter.reportBug(new BugInstance(this, BugType.PME_POOR_MANS_ENUM.name(), NORMAL_PRIORITY).addClass(this).addField(XFactory.createXField(cls, nameToField.get(fieldName))).addSourceLine(firstFieldUse.get(fieldName)));
}
}
} catch (StopOpcodeParsingException e) {
// no fields left
}
}
}
} finally {
fieldValues = null;
nameToField = null;
firstFieldUse = null;
stack = null;
}
}
use of com.mebigfatguy.fbcontrib.utils.StopOpcodeParsingException in project fb-contrib by mebigfatguy.
the class MethodReturnsConstant method sawOpcode.
/**
* implements the visitor to look for methods that return a constant
*
* @param seen
* the opcode of the currently parsed instruction
*/
@Override
public void sawOpcode(int seen) {
boolean sawSBToString = false;
try {
stack.precomputation(this);
if ((seen >= Const.IRETURN) && (seen <= Const.ARETURN)) {
if (stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
Integer register = Integer.valueOf(item.getRegisterNumber());
Object constant = registerConstants.get(register);
if (CONSTANT_DOESNT_EXIST.equals(constant)) {
throw new StopOpcodeParsingException();
}
String returnSig = item.getSignature();
if ((returnSig != null) && returnSig.startsWith(Values.SIG_ARRAY_PREFIX)) {
XField f = item.getXField();
if ((f == null) || (!f.isStatic())) {
throw new StopOpcodeParsingException();
}
}
constant = item.getConstant();
if (constant == null) {
throw new StopOpcodeParsingException();
}
if (Boolean.TRUE.equals(item.getUserValue()) && ("".equals(constant))) {
throw new StopOpcodeParsingException();
}
if ((returnConstant != null) && (!returnConstant.equals(constant))) {
throw new StopOpcodeParsingException();
}
returnRegister = Integer.valueOf(item.getRegisterNumber());
returnConstant = constant;
returnPC = getPC();
}
} else if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) {
if (stack.getStackDepth() > 0) {
// Ternaries confuse us too much, if the code has a ternary well - oh well
throw new StopOpcodeParsingException();
}
} else if (seen == Const.ATHROW) {
throw new StopOpcodeParsingException();
} else if (seen == Const.INVOKEVIRTUAL) {
String clsName = getClassConstantOperand();
if (SignatureUtils.isPlainStringConvertableClass(clsName)) {
sawSBToString = Values.TOSTRING.equals(getNameConstantOperand());
}
} else if (((seen >= Const.ISTORE) && (seen <= Const.ASTORE_3)) || (seen == Const.IINC)) {
Integer register = Integer.valueOf(getRegisterOperand());
if ((returnRegister.intValue() != -1) && (register.equals(returnRegister))) {
throw new StopOpcodeParsingException();
}
if (stack.getStackDepth() > 0) {
OpcodeStack.Item item = stack.getStackItem(0);
Object constant = item.getConstant();
Object regConstant = registerConstants.get(register);
if (regConstant != null) {
if ((constant == null) || !constant.equals(regConstant)) {
registerConstants.put(register, CONSTANT_DOESNT_EXIST);
}
} else {
if (item.getSignature().contains(Values.SIG_ARRAY_PREFIX)) {
registerConstants.put(register, CONSTANT_DOESNT_EXIST);
} else {
registerConstants.put(register, constant == null ? CONSTANT_DOESNT_EXIST : constant);
}
}
} else {
registerConstants.put(register, CONSTANT_DOESNT_EXIST);
}
if (returnRegister.equals(register)) {
Object constant = registerConstants.get(returnRegister);
if (CONSTANT_DOESNT_EXIST.equals(constant)) {
throw new StopOpcodeParsingException();
}
}
}
} finally {
TernaryPatcher.pre(stack, seen);
stack.sawOpcode(this, seen);
TernaryPatcher.post(stack, seen);
if (sawSBToString && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
item.setUserValue(Boolean.TRUE);
}
}
}
Aggregations