Skip to content

Commit f8b444b

Browse files
FIX(pmd): @W-18808343@: Prevent AppExchange rules from running in an infinite loop (#312)
1 parent 202a315 commit f8b444b

File tree

9 files changed

+869
-28
lines changed

9 files changed

+869
-28
lines changed

packages/code-analyzer-pmd-engine/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@salesforce/code-analyzer-pmd-engine",
33
"description": "Plugin package that adds 'pmd' and 'cpd' as engines into Salesforce Code Analyzer",
4-
"version": "0.26.0",
4+
"version": "0.26.1-SNAPSHOT",
55
"author": "The Salesforce Code Analyzer Team",
66
"license": "BSD-3-Clause",
77
"homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview",
@@ -71,4 +71,4 @@
7171
"!src/index.ts"
7272
]
7373
}
74-
}
74+
}

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/apex/DangerousChangeProtectionMethods.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,11 @@ public class DangerousChangeProtectionMethods extends AbstractApexRule {
2525

2626
@Override
2727
public Object visit(ASTMethodCallExpression node, Object data) {
28-
if (Helper.isTestMethodOrClass(node)) {
29-
super.visit(node, data);
30-
}
31-
32-
if (node.getFullMethodName().compareToIgnoreCase(
33-
CHANGE_PROTECTION) == 0
34-
|| node.getFullMethodName().compareToIgnoreCase(SYSTEM_CHANGE_PROTECTION) == 0) {
28+
if (!Helper.isTestMethodOrClass(node) && (node.getFullMethodName().compareToIgnoreCase(CHANGE_PROTECTION) == 0
29+
|| node.getFullMethodName().compareToIgnoreCase(SYSTEM_CHANGE_PROTECTION) == 0)) {
3530
this.handleChangeProtection(node, data);
3631
}
37-
super.visit(node, data);
38-
return data;
32+
return super.visit(node, data);
3933
}
4034

4135
private void handleChangeProtection(ASTMethodCallExpression node, Object data) {

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/apex/DangerousPasswordMethods.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import net.sourceforge.pmd.lang.rule.RuleTargetSelector;
1515

1616
public class DangerousPasswordMethods extends AbstractApexRule {
17-
17+
1818
private static final String MOVE_PASSWORD = "movePassword";
1919
private static final String SYSTEM_MOVE_PASSWORD = "System.movePassword";
2020

@@ -74,8 +74,7 @@ public Object visit(ASTMethodCallExpression node, Object data) {
7474
{
7575
this.handleSetPassword(node, data);
7676
}
77-
super.visit(node, data);
78-
return data;
77+
return super.visit(node, data);
7978
}
8079

8180
private void handleMovePassword(ASTMethodCallExpression node, Object data) {
@@ -113,7 +112,7 @@ private void handleSetPassword(ASTMethodCallExpression node, Object data) {
113112
} else {
114113
asCtx(data).addViolationWithMessage(node, String.format(SET_PASSWORD_VIOLATION_LOW_CONFIDENCE, userIdVarName));
115114
}
116-
115+
117116
}
118117
}
119118

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/apex/DetectHardcodedCredentialsInHttpRequests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
public class DetectHardcodedCredentialsInHttpRequests extends DetectHardcodedCredentialsBase {
1717
private static final List<String> HTTP_AUTH_HEADERS = SecretsInPackageUtils.AUTH_FIELD_MAPPINGS_LIST;
1818
private static final List<String> HTTP_AUTH_HEADER_VALUES_TO_IGNORE = Arrays.asList(SecretsInPackageUtils.STRINGS_TO_IGNORE);
19-
19+
2020
private static final String HARD_CODED_SECRET_IN_HTTP_REQUEST_HEADER_VIOLATION = "Potentially hardcoded secret found in HTTP request header";
2121
private static final String MERGE_FIELD_LITERAL="{!$Credential.";
2222

@@ -49,7 +49,7 @@ public Object visit(ASTMethodCallExpression node, Object data) {
4949

5050
Node firstChild = childRefExpr.getNextSibling();
5151
Node secondChild = firstChild.getNextSibling();
52-
52+
5353
List<ASTLiteralExpression> firstArgLiterals = firstChild.descendantsOrSelf()
5454
.filterIs(ASTLiteralExpression.class).toList();
5555
List<ASTVariableExpression> firstArgVars =
@@ -99,8 +99,7 @@ public Object visit(ASTMethodCallExpression node, Object data) {
9999
break;
100100
}
101101
}
102-
super.visit(node, data);
103-
return data;
102+
return super.visit(node, data);
104103
}
105104

106105
private boolean isAMergeField(String value) {

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/apex/DetectHardcodedCredentialsInPasswordMethods.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ public Object visit(ASTMethodCallExpression node, Object data) {
2323
|| node.getFullMethodName().compareToIgnoreCase(SYSTEM_SET_PASSWORD) == 0) {
2424
this.handleSetPassword(node, data);
2525
}
26-
super.visit(node, data);
27-
return data;
26+
return super.visit(node, data);
2827
}
2928

3029
private void handleSetPassword(ASTMethodCallExpression node, Object data) {

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/visualforce/DetectCreateElementScriptTag.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import net.sourceforge.pmd.reporting.RuleContext;
1111

1212
public class DetectCreateElementScriptTag extends AbstractVfRule {
13-
13+
1414
private static ArrayList<Pattern> CREATE_ELEMENT_PATTERNS = new ArrayList<Pattern>();
1515
private static final String[] CREATE_ELEMENT_REGEXES = {
1616
"createElement.*['\"]script",
@@ -35,16 +35,15 @@ public void start(RuleContext ctx) {
3535
public Object visit(ASTHtmlScript node, Object data) {
3636
Chars c = node.getText();
3737
searchForPatterns(node,data,c);
38-
super.visit(node, data);
39-
return data;
38+
return super.visit(node, data);
4039
}
4140

4241
private void searchForPatterns(ASTHtmlScript node, Object data, Chars c) {
4342
String staticJS = c.toString();
4443

4544
for (Pattern nextPattern: CREATE_ELEMENT_PATTERNS) {
4645
Matcher match = nextPattern.matcher(staticJS);
47-
if (match.find()) {
46+
if (match.find()) {
4847
this.asCtx(data)
4948
.addViolationWithMessage(node,
5049
CREATE_ELEMENT_SCRIPT_CSS_VIOLATION);

packages/code-analyzer-pmd-engine/pmd-rules/src/main/java/com/salesforce/security/pmd/visualforce/DetectHardcodedSecretsInAttributes.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@ public Object visit(ASTElement node, Object data) {
2121
} else if (APEX_ATTRIBUTE.equalsIgnoreCase(node.getName())) {
2222
processASTAttribute(node,data);
2323
}
24-
super.visit(node, data);
25-
return data;
24+
return super.visit(node, data);
2625
}
2726

2827
private void processComponentInclusion(ASTElement node,Object data) {
2928
List<ASTAttribute> allAttributes = node.children(ASTAttribute.class).toList();
30-
29+
3130
for (ASTAttribute nextAttr: allAttributes) {
3231
String attrName = nextAttr.getName();
3332
if (SecretsInPackageUtils.isAPotentialSecret(attrName)) {

packages/code-analyzer-pmd-engine/test/pmd-engine.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,22 @@ describe('Tests for the runRules method of PmdEngine', () => {
623623
expect(errorLogEvents).toHaveLength(1);
624624
expect(errorLogEvents[0].message).toContain('Message was null');
625625
});
626+
627+
it('When running a file that has a method that references a class name that is the same as itself, then the AppExchange rules should not run in infinite loop', async () => {
628+
// This test is to ensure that we have resolved the issue associated with: W-18808343
629+
const engine: PmdEngine = new PmdEngine(DEFAULT_PMD_ENGINE_CONFIG);
630+
631+
// Get AppExchange rules
632+
const ruleDescriptions: RuleDescription[] = await engine.describeRules(createDescribeOptions());
633+
const appExchangeRuleNames: string[] = ruleDescriptions.filter(r => r.tags.includes('AppExchange'))
634+
.map(r => r.name);
635+
expect(appExchangeRuleNames.length).toBeGreaterThan(0); // sanity check
636+
637+
const workspace: Workspace = new Workspace('id', [path.join(TEST_DATA_FOLDER, 'samplePmdWorkspaceFor_W-18808343')]);
638+
639+
const results: EngineRunResults = await engine.runRules(appExchangeRuleNames, createRunOptions(workspace)); // This should not run forever and ever.
640+
expect(results.violations.length).toEqual(0);
641+
});
626642
});
627643

628644
describe('Tests for the getEngineVersion method of PmdEngine', () => {

0 commit comments

Comments
 (0)