Skip to content

Commit dd84751

Browse files
authored
Limit ResponseEntity call changes (#470)
We can only safely make this change when the first argument value is a `String` -- this adds that change and tests it.
1 parent 2c4bb17 commit dd84751

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

framework/codemodder-base/src/main/java/io/codemodder/remediation/xss/ResponseEntityFixStrategy.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import com.github.javaparser.ast.CompilationUnit;
44
import com.github.javaparser.ast.Node;
5+
import com.github.javaparser.ast.expr.Expression;
56
import com.github.javaparser.ast.expr.ObjectCreationExpr;
7+
import com.github.javaparser.resolution.types.ResolvedType;
68
import io.codemodder.remediation.RemediationStrategy;
79
import io.codemodder.remediation.SuccessOrReason;
810
import java.util.Optional;
@@ -32,6 +34,17 @@ static boolean match(final Node node) {
3234
"ResponseEntity".equals(c.getTypeAsString())
3335
|| c.getTypeAsString().startsWith("ResponseEntity<"))
3436
.filter(c -> !c.getArguments().isEmpty())
37+
.filter(
38+
c -> {
39+
Expression firstArg = c.getArguments().getFirst().get();
40+
try {
41+
ResolvedType resolvedType = firstArg.calculateResolvedType();
42+
return "java.lang.String".equals(resolvedType.describe());
43+
} catch (Exception e) {
44+
// this is expected often, and indicates its a non-String type anyway
45+
return false;
46+
}
47+
})
3548
.isPresent();
3649
}
3750
}

framework/codemodder-base/src/test/java/io/codemodder/remediation/xss/ResponseEntityFixStrategyTest.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import static org.assertj.core.api.Assertions.assertThat;
44

5-
import com.github.javaparser.StaticJavaParser;
5+
import com.github.javaparser.JavaParser;
66
import com.github.javaparser.ast.CompilationUnit;
77
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
88
import io.codemodder.CodemodFileScanningResult;
99
import io.codemodder.codetf.DetectorRule;
10+
import io.codemodder.javaparser.JavaParserFactory;
1011
import io.codemodder.remediation.FixCandidateSearcher;
1112
import io.codemodder.remediation.SearcherStrategyRemediator;
13+
import java.io.IOException;
1214
import java.util.List;
1315
import java.util.Optional;
1416
import java.util.stream.Stream;
@@ -21,10 +23,12 @@ final class ResponseEntityFixStrategyTest {
2123

2224
private ResponseEntityFixStrategy fixer;
2325
private DetectorRule rule;
26+
private JavaParser parser;
2427

2528
@BeforeEach
26-
void setup() {
29+
void setup() throws IOException {
2730
this.fixer = new ResponseEntityFixStrategy();
31+
this.parser = JavaParserFactory.newFactory().create(List.of());
2832
this.rule = new DetectorRule("xss", "XSS", null);
2933
}
3034

@@ -67,7 +71,7 @@ ResponseEntity<String> should_be_fixed(String s) {
6771
@ParameterizedTest
6872
@MethodSource("fixableSamples")
6973
void it_fixes_obvious_response_write_methods(final String beforeCode, final String afterCode) {
70-
CompilationUnit cu = StaticJavaParser.parse(beforeCode);
74+
CompilationUnit cu = parser.parse(beforeCode).getResult().orElseThrow();
7175
LexicalPreservingPrinter.setup(cu);
7276

7377
var result = scanAndFix(cu, 3);
@@ -100,7 +104,7 @@ private CodemodFileScanningResult scanAndFix(final CompilationUnit cu, final int
100104
@ParameterizedTest
101105
@MethodSource("unfixableSamples")
102106
void it_does_not_fix_unfixable_samples(final String beforeCode, final int line) {
103-
CompilationUnit cu = StaticJavaParser.parse(beforeCode);
107+
CompilationUnit cu = parser.parse(beforeCode).getResult().orElseThrow();
104108
LexicalPreservingPrinter.setup(cu);
105109
var result = scanAndFix(cu, line);
106110
assertThat(result.changes()).isEmpty();
@@ -110,13 +114,24 @@ private static Stream<Arguments> unfixableSamples() {
110114
return Stream.of(
111115
// this is not a ResponseEntity, shouldn't touch it
112116
Arguments.of(
117+
// this is not a ResponseEntity, shouldn't touch it
113118
"""
114119
class Samples {
115-
String should_be_fixed(String s) {
120+
String should_not_be_fixed(String s) {
116121
return new NotResponseEntity(s, HttpStatus.OK);
117122
}
118123
}
119124
""",
125+
3),
126+
Arguments.of(
127+
// this is not a String, shouldn't touch it
128+
"""
129+
class Samples {
130+
String should_not_be_fixed(BodyType s) {
131+
return new ResponseEntity(s, HttpStatus.OK);
132+
}
133+
}
134+
""",
120135
3));
121136
}
122137
}

0 commit comments

Comments
 (0)