Skip to content

Commit 8d65e93

Browse files
committed
Adjustments and test
1 parent de81008 commit 8d65e93

File tree

7 files changed

+100
-13
lines changed

7 files changed

+100
-13
lines changed

core-codemods/src/test/java/io/codemodder/codemods/SQLParameterizerCodemodTest.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@
22

33
import io.codemodder.testutils.CodemodTestMixin;
44
import io.codemodder.testutils.Metadata;
5+
import org.junit.jupiter.api.Nested;
56

6-
@Metadata(
7-
codemodType = SQLParameterizerCodemod.class,
8-
testResourceDir = "sql-parameterizer",
9-
dependencies = {})
10-
final class SQLParameterizerCodemodTest implements CodemodTestMixin {}
7+
final class SQLParameterizerCodemodTest {
8+
9+
@Nested
10+
@Metadata(
11+
codemodType = SQLParameterizerCodemod.class,
12+
testResourceDir = "sql-parameterizer/defaultTransformation",
13+
dependencies = {})
14+
class DefaultTransformationTest implements CodemodTestMixin {}
15+
16+
@Nested
17+
@Metadata(
18+
codemodType = SQLParameterizerCodemod.class,
19+
testResourceDir = "sql-parameterizer/hijackTransformation",
20+
dependencies = {})
21+
class HijackTransformationTest implements CodemodTestMixin {}
22+
}

core-codemods/src/test/resources/sql-parameterizer/Test.java.after renamed to core-codemods/src/test/resources/sql-parameterizer/defaultTransformation/Test.java.after

File renamed without changes.

core-codemods/src/test/resources/sql-parameterizer/Test.java.before renamed to core-codemods/src/test/resources/sql-parameterizer/defaultTransformation/Test.java.before

File renamed without changes.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.acme.testcode;
2+
3+
import java.sql.Connection;
4+
import java.sql.PreparedStatement;
5+
import java.sql.ResultSet;
6+
import java.sql.SQLException;
7+
import java.sql.Statement;
8+
9+
public final class Test {
10+
11+
private Connection conn;
12+
13+
public void queryAfterDeclaration() throws SQLException {
14+
Statement stmt;
15+
String query2 = "SELECT * FROM users WHERE username = ?";
16+
PreparedStatement statement = conn.prepareStatement(query2);
17+
statement.setString(1, request.getParameter("username"));
18+
ResultSet rs2 = statement.execute();
19+
stmt = statement;
20+
while (rs2.next()) {
21+
System.out.println("User: " + rs2.getString("username"));
22+
}
23+
String query3 = "SELECT * FROM users WHERE email = ?";
24+
stmt.close();
25+
PreparedStatement stmt1 = conn.prepareStatement(query3);
26+
stmt1.setString(1, request.getParameter("email"));
27+
ResultSet rs3 = stmt1.execute();
28+
stmt = stmt1;
29+
while (rs3.next()) {
30+
System.out.println("User: " + rs3.getString("username"));
31+
}
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
}
46+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.acme.testcode;
2+
3+
import java.sql.Connection;
4+
import java.sql.ResultSet;
5+
import java.sql.SQLException;
6+
import java.sql.Statement;
7+
8+
public final class Test {
9+
10+
private Connection conn;
11+
12+
public void queryAfterDeclaration() throws SQLException {
13+
Statement stmt = conn.createStatement();
14+
String username = request.getParameter("username");
15+
String query2 = "SELECT * FROM users WHERE username = '" + username + "'";
16+
ResultSet rs2 = stmt.executeQuery(query2);
17+
while (rs2.next()) {
18+
System.out.println("User: " + rs2.getString("username"));
19+
}
20+
String email = request.getParameter("email");
21+
String query3 = "SELECT * FROM users WHERE email = '" + email + "'";
22+
ResultSet rs3 = stmt.executeQuery(query3);
23+
while (rs3.next()) {
24+
System.out.println("User: " + rs3.getString("username"));
25+
}
26+
}
27+
}

framework/codemodder-base/src/main/java/io/codemodder/javaparser/JavaParserCodemodRunner.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public CodemodFileScanningResult run(final CodemodInvocationContext context) thr
5858
Path file = context.path();
5959
CompilationUnit cu = parser.parseJavaFile(file);
6060
CodemodFileScanningResult result = javaParserChanger.visit(context, cu);
61-
System.out.println(cu);
6261
List<CodemodChange> changes = result.changes();
6362
if (!changes.isEmpty()) {
6463
String encodingName = encodingDetector.detect(file).orElse("UTF-8");

framework/codemodder-base/src/main/java/io/codemodder/remediation/sqlinjection/SQLParameterizer.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,13 @@ private Optional<MethodCallExpr> isConnectionCreateStatement(final Expression ex
101101
return false;
102102
}
103103
};
104+
var stmtCreationMethods = List.of("createStatement", "prepareStatement");
104105
return Optional.of(expr)
105106
.map(e -> e instanceof MethodCallExpr ? expr.asMethodCallExpr() : null)
106107
.filter(
107108
mce ->
108109
mce.getScope().filter(isConnection).isPresent()
109-
&& mce.getNameAsString().equals("createStatement"));
110+
&& (stmtCreationMethods.contains(mce.getNameAsString())));
110111
}
111112

112113
private Optional<MethodCallExpr> validateExecuteCall(final MethodCallExpr executeCall) {
@@ -187,16 +188,17 @@ private Optional<MethodCallExpr> validateExecuteCall(final MethodCallExpr execut
187188
.map(expr -> expr instanceof NameExpr ? expr.asNameExpr() : null)
188189
.flatMap(ne -> ASTs.findEarliestLocalVariableDeclarationOf(ne, ne.getNameAsString()));
189190

190-
// Has a single assignment
191-
// We erroniously assume that it always shadows the init expression
192191
// Needs some flow analysis to correctly address this case
193192
final Optional<AssignExpr> maybeSingleAssigned =
194193
maybeLVD
195194
.map(lvd -> ASTs.findAllAssignments(lvd).limit(2).toList())
196-
.filter(allAssignments -> allAssignments.size() == 1)
197-
.map(allAssignments -> allAssignments.get(0))
195+
.filter(allAssignments -> !allAssignments.isEmpty())
196+
.map(allAssignments -> allAssignments.get(allAssignments.size() - 1))
198197
.filter(assign -> assign.getTarget().isNameExpr())
199-
.filter(assign -> isConnectionCreateStatement(assign.getValue()).isPresent());
198+
.filter(
199+
assign ->
200+
isConnectionCreateStatement(ASTs.resolveLocalExpression(assign.getValue()))
201+
.isPresent());
200202

201203
if (maybeSingleAssigned.isPresent()) {
202204
return maybeSingleAssigned.map(a -> Either.right(Either.left(a)));
@@ -665,7 +667,7 @@ private Expression getConnectionExpression(
665667
final Either<AssignExpr, LocalVariableDeclaration> stmtCreation) {
666668
return stmtCreation
667669
.ifLeftOrElseGet(
668-
ae -> ae.getValue().asMethodCallExpr(),
670+
ae -> ASTs.resolveLocalExpression(ae.getValue()).asMethodCallExpr(),
669671
lvd -> lvd.getDeclaration().getInitializer().get().asMethodCallExpr())
670672
.getScope()
671673
.get();
@@ -707,6 +709,7 @@ private MethodCallExpr fixByHijackedStatement(
707709
prepareStatementCall)));
708710
ASTTransforms.addStatementBeforeStatement(topStatement, pStmtCreation);
709711
topStatement = pStmtCreation;
712+
ASTTransforms.addImportIfMissing(compilationUnit, "java.sql.PreparedStatement");
710713

711714
// Test if stmt.execute*() is the first usage of the stmt object
712715
// If so, remove initializer

0 commit comments

Comments
 (0)