use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class SpoiledChildInterfaceImplementor method buildMethodSet.
/**
* builds a set of all non constructor or static initializer method/signatures
*
* @param cls
* the class to build the method set from
* @return a set of method names/signatures
*/
private static Set<QMethod> buildMethodSet(JavaClass cls) {
Set<QMethod> methods = new HashSet<>();
boolean isInterface = cls.isInterface();
for (Method m : cls.getMethods()) {
boolean isDefaultInterfaceMethod = isInterface && !m.isAbstract();
boolean isSyntheticForParentCall;
if (m.isSynthetic()) {
BitSet bytecodeSet = ClassContext.getBytecodeSet(cls, m);
isSyntheticForParentCall = (bytecodeSet != null) && bytecodeSet.get(Const.INVOKESPECIAL);
} else {
isSyntheticForParentCall = false;
}
if (!isSyntheticForParentCall && !isDefaultInterfaceMethod) {
String methodName = m.getName();
QMethod methodInfo = new QMethod(methodName, m.getSignature());
if (!OBJECT_METHODS.contains(methodInfo)) {
if (!Values.CONSTRUCTOR.equals(methodName) && !Values.STATIC_INITIALIZER.equals(methodName)) {
methods.add(methodInfo);
}
}
}
}
return methods;
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class NonRecycleableTaglibs method sawOpcode.
/**
* implements the visitor to record storing of fields, and where they occur
*
* @param seen
* the currently parsed opcode
*/
@Override
public void sawOpcode(int seen) {
if (seen == PUTFIELD) {
QMethod methodInfo = new QMethod(getMethodName(), getMethodSig());
Map<Map.Entry<String, String>, SourceLineAnnotation> fields = methodWrites.get(methodInfo);
if (fields == null) {
fields = new HashMap<>();
methodWrites.put(methodInfo, fields);
}
String fieldName = getNameConstantOperand();
String fieldSig = getSigConstantOperand();
FieldAnnotation fa = new FieldAnnotation(getDottedClassName(), fieldName, fieldSig, false);
fieldAnnotations.put(fieldName, fa);
fields.put(new AbstractMap.SimpleImmutableEntry(fieldName, fieldSig), SourceLineAnnotation.fromVisitedInstruction(this));
}
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class NonRecycleableTaglibs method reportBugs.
/**
* generates all the bug reports for attributes that are not recycleable
*/
private void reportBugs() {
for (Map.Entry<QMethod, String> attEntry : attributes.entrySet()) {
QMethod methodInfo = attEntry.getKey();
String attType = attEntry.getValue();
Map<Map.Entry<String, String>, SourceLineAnnotation> fields = methodWrites.get(methodInfo);
if ((fields == null) || (fields.size() != 1)) {
continue;
}
Map.Entry<String, String> fieldInfo = fields.keySet().iterator().next();
String fieldType = fieldInfo.getValue();
if (!attType.equals(fieldType)) {
continue;
}
String fieldName = fieldInfo.getKey();
for (Map.Entry<QMethod, Map<Map.Entry<String, String>, SourceLineAnnotation>> fwEntry : methodWrites.entrySet()) {
if (fwEntry.getKey().equals(methodInfo)) {
continue;
}
SourceLineAnnotation sla = fwEntry.getValue().get(fieldInfo);
if (sla != null) {
bugReporter.reportBug(new BugInstance(this, BugType.NRTL_NON_RECYCLEABLE_TAG_LIB.name(), NORMAL_PRIORITY).addClass(this).addField(fieldAnnotations.get(fieldName)).addSourceLine(sla));
break;
}
}
}
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class MapUsageIssues method sawOpcode.
@Override
public void sawOpcode(int seen) {
try {
if (!mapContainsKeyUsed.isEmpty()) {
Iterator<Map.Entry<MapRef, ContainsKey>> it = mapContainsKeyUsed.entrySet().iterator();
int pc = getPC();
while (it.hasNext()) {
Map.Entry<MapRef, ContainsKey> entry = it.next();
if (!entry.getKey().isValid() || entry.getValue().outOfScope(pc)) {
it.remove();
}
}
}
// checking for a branch might be overkill, but for now lets go with it
if (!mapGetUsed.isEmpty() && OpcodeUtils.isBranch(seen)) {
Iterator<Map.Entry<MapRef, Get>> it = mapGetUsed.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<MapRef, Get> entry = it.next();
it.remove();
}
}
if ((seen == Const.IFNULL) || (seen == Const.IFNONNULL)) {
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
XMethod method = itm.getReturnValueOf();
if ((method != null) && (mapClass != null)) {
if (COLLECTION_ACCESSORS.contains(method.getName())) {
JavaClass cls = Repository.lookupClass(method.getClassName());
if (cls.implementationOf(mapClass)) {
bugReporter.reportBug(new BugInstance(this, BugType.MUI_NULL_CHECK_ON_MAP_SUBSET_ACCESSOR.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
}
} else if (seen == Const.INVOKEINTERFACE) {
FQMethod fqm = new FQMethod(getClassConstantOperand(), getNameConstantOperand(), getSigConstantOperand());
if (CONTAINS_METHOD.equals(fqm)) {
if (stack.getStackDepth() >= 2) {
OpcodeStack.Item item = stack.getStackItem(1);
if ((item.getRegisterNumber() < 0) && (item.getXField() == null)) {
XMethod xm = item.getReturnValueOf();
if ((xm != null) && COLLECTION_ACCESSORS.contains(xm.getName()) && Values.DOTTED_JAVA_UTIL_MAP.equals(xm.getClassName())) {
bugReporter.reportBug(new BugInstance(this, BugType.MUI_USE_CONTAINSKEY.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
} else if (CONTAINSKEY_METHOD.equals(fqm)) {
if (getNextOpcode() == Const.IFEQ) {
int ifEnd = getNextPC() + CodeByteUtils.getshort(getCode().getCode(), getNextPC() + 1);
if (stack.getStackDepth() >= 2) {
OpcodeStack.Item itm = stack.getStackItem(1);
mapContainsKeyUsed.put(new MapRef(itm), new ContainsKey(stack.getStackItem(0), ifEnd));
}
}
} else if (GET_METHOD.equals(fqm)) {
if (stack.getStackDepth() >= 2) {
OpcodeStack.Item itm = stack.getStackItem(1);
ContainsKey ck = mapContainsKeyUsed.remove(new MapRef(itm));
if ((ck != null) && new ContainsKey(stack.getStackItem(0), 0).equals(ck)) {
bugReporter.reportBug(new BugInstance(this, BugType.MUI_CONTAINSKEY_BEFORE_GET.name(), ck.getReportLevel()).addClass(this).addMethod(this).addSourceLine(this));
}
mapGetUsed.put(new MapRef(itm), new Get(stack.getStackItem(0)));
}
} else if (REMOVE_METHOD.equals(fqm)) {
if (stack.getStackDepth() >= 2) {
OpcodeStack.Item itm = stack.getStackItem(1);
Get get = mapGetUsed.remove(new MapRef(itm));
if ((get != null) && new Get(stack.getStackItem(0)).equals(get)) {
bugReporter.reportBug(new BugInstance(this, BugType.MUI_GET_BEFORE_REMOVE.name(), get.getReportLevel()).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
QMethod qm = new QMethod(getNameConstantOperand(), getSigConstantOperand());
if (SIZE_METHOD.equals(qm)) {
if (stack.getStackDepth() > 0) {
OpcodeStack.Item itm = stack.getStackItem(0);
if ((itm.getRegisterNumber() < 0) && (itm.getXField() == null)) {
XMethod xm = itm.getReturnValueOf();
if ((xm != null) && Values.DOTTED_JAVA_UTIL_MAP.equals(xm.getClassName()) && COLLECTION_ACCESSORS.contains(xm.getName())) {
bugReporter.reportBug(new BugInstance(this, BugType.MUI_CALLING_SIZE_ON_SUBCONTAINER.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
}
}
}
} catch (ClassNotFoundException e) {
bugReporter.reportMissingClass(e);
} finally {
stack.sawOpcode(this, seen);
}
}
use of com.mebigfatguy.fbcontrib.utils.QMethod in project fb-contrib by mebigfatguy.
the class SillynessPotPourri method stringSilliness.
private SPPUserValue stringSilliness(String methodName, String signature) {
Integer stackOffset = methodsThatAreSillyOnStringLiterals.get(new QMethod(methodName, signature));
int offset;
if ((stackOffset != null) && (stack.getStackDepth() > (offset = stackOffset.intValue()))) {
OpcodeStack.Item itm = stack.getStackItem(offset);
Object constant = itm.getConstant();
if ((constant != null) && constant.getClass().equals(String.class) && (itm.getXField() == null)) {
int priority = NORMAL_PRIORITY;
if (SignatureUtils.getNumParameters(getSigConstantOperand()) > 0) {
// if an argument is passed in, it may be
// locale-specific
priority = LOW_PRIORITY;
}
bugReporter.reportBug(new BugInstance(this, BugType.SPP_CONVERSION_OF_STRING_LITERAL.name(), priority).addClass(this).addMethod(this).addSourceLine(this).addCalledMethod(this));
}
}
// not an elseif because the below cases might be in the set
// methodsThatAreSillyOnStringLiterals
SPPUserValue userValue = null;
if ("intern".equals(methodName)) {
String owningMethod = getMethod().getName();
if (!Values.STATIC_INITIALIZER.equals(owningMethod) && (stack.getStackDepth() > 0)) {
OpcodeStack.Item item = stack.getStackItem(0);
if (item.getConstant() != null) {
bugReporter.reportBug(new BugInstance(this, BugType.SPP_INTERN_ON_CONSTANT.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
} else if ("toCharArray".equals(methodName)) {
userValue = new SPPUserValue(SPPMethod.TOCHARARRAY);
} else if ("toLowerCase".equals(methodName) || "toUpperCase".equals(methodName)) {
userValue = new SPPUserValue(SPPMethod.IGNORECASE);
} else if ("equalsIgnoreCase".equals(methodName) || "compareToIgnoreCase".equals(methodName)) {
if (stack.getStackDepth() > 1) {
OpcodeStack.Item item = stack.getStackItem(1);
SPPUserValue uv = (SPPUserValue) item.getUserValue();
if ((uv != null) && (uv.getMethod() == SPPMethod.IGNORECASE)) {
bugReporter.reportBug(new BugInstance(this, BugType.SPP_USELESS_CASING.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
item = stack.getStackItem(0);
String parm = (String) item.getConstant();
if ("".equals(parm)) {
bugReporter.reportBug(new BugInstance(this, BugType.SPP_EMPTY_CASING.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
}
} else if ("trim".equals(methodName)) {
userValue = getTrimUserValue();
} else if ("length".equals(methodName)) {
if (stack.getStackDepth() > 0) {
checkForTrim(stack.getStackItem(0));
}
} else if ("equals".equals(methodName)) {
if (stack.getStackDepth() > 1) {
checkForTrim(stack.getStackItem(1));
}
} else if (Values.TOSTRING.equals(methodName)) {
bugReporter.reportBug(new BugInstance(this, BugType.SPP_TOSTRING_ON_STRING.name(), NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this));
}
return userValue;
}
Aggregations