diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java index f56a3b9833..654bb5bbdf 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/security/ApexCRUDViolationRule.java @@ -47,6 +47,7 @@ import net.sourceforge.pmd.lang.ast.Node; import apex.jorje.data.ast.Identifier; import apex.jorje.data.ast.TypeRef; +import apex.jorje.data.ast.TypeRef.ArrayTypeRef; import apex.jorje.data.ast.TypeRef.ClassTypeRef; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; @@ -183,30 +184,33 @@ public class ApexCRUDViolationRule extends AbstractApexRule { classNameField.setAccessible(true); typeArgsField.setAccessible(true); - if (typeArgsField.get(a) instanceof Optional) { - Optional optionalContainer = (Optional) typeArgsField.get(a); - if (optionalContainer.isPresent()) { - @SuppressWarnings("unchecked") - ArrayList inner = (ArrayList) optionalContainer.get(); - if (!inner.isEmpty()) { - ClassTypeRef innerClassRef = inner.get(0); - List ids = innerClassRef.className; - String argType = ids.get(0).value; - addVariableToMapping(Helper.getFQVariableName(node), argType); - } - } - } - if (classNameField.get(a) instanceof ArrayList) { @SuppressWarnings("unchecked") ArrayList innerField = (ArrayList) classNameField.get(a); if (!innerField.isEmpty()) { - String type = innerField.get(0).value; - addVariableToMapping(Helper.getFQVariableName(node), type); + StringBuffer sb = new StringBuffer(); + for (Identifier id : innerField) { + sb.append(id.value).append("."); + } + sb.deleteCharAt(sb.length() - 1); + + switch (sb.toString().toLowerCase()) { + case "list": + case "map": + if (typeArgsField.get(a) instanceof Optional) { + addParametersToMapping(node, a, typeArgsField); + } + break; + default: + varToTypeMapping.put(Helper.getFQVariableName(node), getSimpleType(sb.toString())); + break; + } + } } } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException | SecurityException e) { + e.printStackTrace(); } } @@ -219,6 +223,36 @@ public class ApexCRUDViolationRule extends AbstractApexRule { } + private void addParametersToMapping(final ASTFieldDeclaration node, TypeRef a, Field typeArgsField) + throws IllegalAccessException { + Optional optionalContainer = (Optional) typeArgsField.get(a); + if (optionalContainer.isPresent()) { + ArrayList inner = (ArrayList) optionalContainer.get(); + for (int i = 0; i < inner.size(); i++) { + if (inner.get(i) instanceof ClassTypeRef) { + innerAddParametrizedClassToMapping(node, (ClassTypeRef) inner.get(i)); + } + if (inner.get(i) instanceof ArrayTypeRef) { + ArrayTypeRef atr = (ArrayTypeRef) inner.get(i); + if (atr.heldType instanceof ClassTypeRef) { + innerAddParametrizedClassToMapping(node, (ClassTypeRef) atr.heldType); + } + } + + } + } + } + + private void innerAddParametrizedClassToMapping(final ASTFieldDeclaration node, final ClassTypeRef innerClassRef) { + List ids = innerClassRef.className; + StringBuffer argType = new StringBuffer(); + for (Identifier id : ids) { + argType.append(id.value).append("."); + } + argType.deleteCharAt(argType.length() - 1); + addVariableToMapping(Helper.getFQVariableName(node), argType.toString()); + } + @Override public Object visit(final ASTReturnStatement node, Object data) { final ASTSoqlExpression soql = node.getFirstChildOfType(ASTSoqlExpression.class); diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml index 9acf01186c..325bfbf2ef 100644 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml +++ b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/security/xml/ApexCRUDViolation.xml @@ -798,6 +798,17 @@ public class MyProfilePageController { } } +]]> + + + + ClassCastException detection + 0 + bar; + public map baz; +} ]]>