io.codemodder.codemods.FixUnsafeNIOPathComparisonCodemod Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-codemods Show documentation
Show all versions of core-codemods Show documentation
Codemods for fixing common errors across many Java projects
package io.codemodder.codemods;
import static io.codemodder.javaparser.ASTExpectations.expect;
import com.contrastsecurity.sarif.Result;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr;
import io.codemodder.*;
import io.codemodder.javaparser.ChangesResult;
import io.codemodder.providers.sarif.semgrep.SemgrepScan;
import java.util.Optional;
import javax.inject.Inject;
/** Fix unsafe NIO path comparison. */
@Codemod(
id = "pixee:java/fix-unsafe-nio-path-comparison",
importance = Importance.MEDIUM,
reviewGuidance = ReviewGuidance.MERGE_AFTER_CURSORY_REVIEW)
public final class FixUnsafeNIOPathComparisonCodemod
extends SarifPluginJavaParserChanger {
private static final String RULE =
"""
rules:
- id: fix-unsafe-nio-path-comparison
patterns:
- pattern: (File $CHILD).getCanonicalPath().startsWith((File $PARENT).getCanonicalPath())
""";
@Inject
public FixUnsafeNIOPathComparisonCodemod(@SemgrepScan(yaml = RULE) final RuleSarif sarif) {
super(sarif, MethodCallExpr.class);
}
@Override
public ChangesResult onResultFound(
final CodemodInvocationContext context,
final CompilationUnit cu,
final MethodCallExpr methodCallExpr,
final Result result) {
// make sure we have the event for the startsWith() call, not the getCanonicalPath() calls
if (!"startsWith".equals(methodCallExpr.getNameAsString())) {
return ChangesResult.noChanges;
}
// fix the child reference
Expression child = methodCallExpr.getScope().orElseThrow();
Optional childGetCanonicalPathCall =
expect(child).toBeMethodCallExpression().withName("getCanonicalPath").result();
if (childGetCanonicalPathCall.isEmpty()) {
return ChangesResult.noChanges;
}
Expression childScope = childGetCanonicalPathCall.get().getScope().get();
MethodCallExpr newChild = new MethodCallExpr(childScope, "getCanonicalFile().toPath");
methodCallExpr.setScope(newChild);
// fix the parent reference
Expression parent = methodCallExpr.getArgument(0);
Optional parentGetCanonicalPathCall =
expect(parent).toBeMethodCallExpression().withName("getCanonicalPath").result();
if (parentGetCanonicalPathCall.isEmpty()) {
return ChangesResult.noChanges;
}
Expression parentScope = parentGetCanonicalPathCall.get().getScope().get();
MethodCallExpr newParentArgument = new MethodCallExpr(parentScope, "getCanonicalFile().toPath");
methodCallExpr.setArgument(0, newParentArgument);
return ChangesResult.changesApplied;
}
}