Skip to content

Commit ac218ba

Browse files
committed
Replace private classes with one method to predicates
1 parent 0307860 commit ac218ba

File tree

1 file changed

+63
-69
lines changed

1 file changed

+63
-69
lines changed

java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -223,76 +223,72 @@ class UnsafeDeserializationSink extends DataFlow::ExprNode {
223223
MethodAccess getMethodAccess() { unsafeDeserialization(result, this.getExpr()) }
224224
}
225225

226-
/** A sanitizer for unsafe deserialization */
227-
private class UnsafeDeserializationSanitizer extends DataFlow::Node {
228-
UnsafeDeserializationSanitizer() {
229-
exists(ClassInstanceExpr cie |
230-
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and
231-
cie = this.asExpr() and
232-
SafeJsonIoFlow::flowToExpr(cie.getArgument(1))
233-
)
234-
or
235-
exists(MethodAccess ma |
236-
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
237-
ma.getArgument(0) = this.asExpr() and
238-
SafeJsonIoFlow::flowToExpr(ma.getArgument(1))
239-
)
240-
or
241-
exists(MethodAccess ma |
242-
// Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears
243-
// to be called with an explicit class argument limiting those types that can
244-
// be instantiated during deserialization.
245-
ma.getMethod() instanceof JoddJsonParseMethod and
226+
/** Holds if `node` is a sanitizer for unsafe deserialization */
227+
private predicate isUnsafeDeserializationSanitizer(DataFlow::Node node) {
228+
exists(ClassInstanceExpr cie |
229+
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and
230+
cie = node.asExpr() and
231+
SafeJsonIoFlow::flowToExpr(cie.getArgument(1))
232+
)
233+
or
234+
exists(MethodAccess ma |
235+
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
236+
ma.getArgument(0) = node.asExpr() and
237+
SafeJsonIoFlow::flowToExpr(ma.getArgument(1))
238+
)
239+
or
240+
exists(MethodAccess ma |
241+
// Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears
242+
// to be called with an explicit class argument limiting those types that can
243+
// be instantiated during deserialization.
244+
ma.getMethod() instanceof JoddJsonParseMethod and
245+
ma.getArgument(1).getType() instanceof TypeClass and
246+
not ma.getArgument(1) instanceof NullLiteral and
247+
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"] and
248+
node.asExpr() = ma.getAnArgument()
249+
)
250+
or
251+
exists(MethodAccess ma |
252+
// Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears
253+
// to be called with an explicit class argument limiting those types that can
254+
// be instantiated during deserialization, or if the deserializer has already been
255+
// configured to use a specified root class.
256+
ma.getMethod() instanceof FlexjsonDeserializeMethod and
257+
node.asExpr() = ma.getAnArgument() and
258+
(
246259
ma.getArgument(1).getType() instanceof TypeClass and
247260
not ma.getArgument(1) instanceof NullLiteral and
248-
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"] and
249-
this.asExpr() = ma.getAnArgument()
250-
)
251-
or
252-
exists(MethodAccess ma |
253-
// Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears
254-
// to be called with an explicit class argument limiting those types that can
255-
// be instantiated during deserialization, or if the deserializer has already been
256-
// configured to use a specified root class.
257-
ma.getMethod() instanceof FlexjsonDeserializeMethod and
258-
this.asExpr() = ma.getAnArgument() and
259-
(
260-
ma.getArgument(1).getType() instanceof TypeClass and
261-
not ma.getArgument(1) instanceof NullLiteral and
262-
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"]
263-
or
264-
isSafeFlexjsonDeserializer(ma.getQualifier())
265-
)
261+
not ma.getArgument(1).getType().getName() = ["Class<Object>", "Class<?>"]
262+
or
263+
isSafeFlexjsonDeserializer(ma.getQualifier())
266264
)
267-
}
265+
)
268266
}
269267

270268
/** Taint step for Unsafe deserialization */
271-
private class UnsafeDeserializationAdditionalTaintStep extends Unit {
272-
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
273-
exists(ClassInstanceExpr cie |
274-
cie.getArgument(0) = pred.asExpr() and
275-
cie = succ.asExpr() and
276-
(
277-
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or
278-
cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or
279-
cie.getConstructor().getDeclaringType().getAnAncestor() instanceof UnsafeHessianInput or
280-
cie.getConstructor().getDeclaringType() instanceof BurlapInput
281-
)
282-
)
283-
or
284-
exists(MethodAccess ma |
285-
ma.getMethod() instanceof BurlapInputInitMethod and
286-
ma.getArgument(0) = pred.asExpr() and
287-
ma.getQualifier() = succ.asExpr()
269+
private predicate isUnsafeDeserializationTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
270+
exists(ClassInstanceExpr cie |
271+
cie.getArgument(0) = pred.asExpr() and
272+
cie = succ.asExpr() and
273+
(
274+
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or
275+
cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or
276+
cie.getConstructor().getDeclaringType().getAnAncestor() instanceof UnsafeHessianInput or
277+
cie.getConstructor().getDeclaringType() instanceof BurlapInput
288278
)
289-
or
290-
createJacksonJsonParserStep(pred, succ)
291-
or
292-
createJacksonTreeNodeStep(pred, succ)
293-
or
294-
intentFlowsToParcel(pred, succ)
295-
}
279+
)
280+
or
281+
exists(MethodAccess ma |
282+
ma.getMethod() instanceof BurlapInputInitMethod and
283+
ma.getArgument(0) = pred.asExpr() and
284+
ma.getQualifier() = succ.asExpr()
285+
)
286+
or
287+
createJacksonJsonParserStep(pred, succ)
288+
or
289+
createJacksonTreeNodeStep(pred, succ)
290+
or
291+
intentFlowsToParcel(pred, succ)
296292
}
297293

298294
/**
@@ -308,12 +304,10 @@ deprecated class UnsafeDeserializationConfig extends TaintTracking::Configuratio
308304
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink }
309305

310306
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
311-
any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ)
307+
isUnsafeDeserializationTaintStep(pred, succ)
312308
}
313309

314-
override predicate isSanitizer(DataFlow::Node node) {
315-
node instanceof UnsafeDeserializationSanitizer
316-
}
310+
override predicate isSanitizer(DataFlow::Node node) { isUnsafeDeserializationSanitizer(node) }
317311
}
318312

319313
/** Tracks flows from remote user input to a deserialization sink. */
@@ -323,10 +317,10 @@ private module UnsafeDeserializationConfig implements DataFlow::ConfigSig {
323317
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink }
324318

325319
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
326-
any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ)
320+
isUnsafeDeserializationTaintStep(pred, succ)
327321
}
328322

329-
predicate isBarrier(DataFlow::Node node) { node instanceof UnsafeDeserializationSanitizer }
323+
predicate isBarrier(DataFlow::Node node) { isUnsafeDeserializationSanitizer(node) }
330324
}
331325

332326
module UnsafeDeserializationFlow = TaintTracking::Global<UnsafeDeserializationConfig>;

0 commit comments

Comments
 (0)