Skip to content

Commit 8cd85a5

Browse files
author
Alvaro Muñoz
committed
add flow support for unmarshaled object fields
1 parent d17199a commit 8cd85a5

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

java/ql/lib/semmle/code/java/Serializability.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java
66
private import frameworks.jackson.JacksonSerializability
7+
private import frameworks.google.GsonSerializability
78
private import frameworks.google.GoogleHttpClientApi
89

910
/**
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Provides classes and predicates for working with Java Serialization in the context of
3+
* the `com.google.gson` JSON processing framework.
4+
*/
5+
6+
import java
7+
import semmle.code.java.Serializability
8+
import semmle.code.java.dataflow.DataFlow
9+
import semmle.code.java.dataflow.FlowSteps
10+
11+
/**
12+
* A method used for deserializing objects using Gson. The first parameter is the object to be
13+
* deserialized.
14+
*/
15+
private class GsonReadValueMethod extends Method {
16+
GsonReadValueMethod() {
17+
this.getDeclaringType().hasQualifiedName("com.google.gson", "Gson") and
18+
this.getName().matches("fromJson")
19+
}
20+
}
21+
22+
/** A type whose values may be deserialized by the Gson JSON framework. */
23+
abstract class GsonDeserializableType extends Type { }
24+
25+
/** A type whose values are explicitly deserialized in a call to a Gson method. */
26+
private class ExplicitlyReadGsonDeserializableType extends GsonDeserializableType {
27+
ExplicitlyReadGsonDeserializableType() {
28+
exists(MethodAccess ma |
29+
// A call to a Gson read method...
30+
ma.getMethod() instanceof GsonReadValueMethod and
31+
// ...where `this` is used in the final argument, indicating that this type will be deserialized.
32+
// TODO: find a way to get the type represented by java.lang.reflect.Type and com.google.gson.reflect.TypeToken
33+
// fromJson​(String json, TypeToken<T> typeOfT)
34+
// fromJson​(String json, Type typeOfT)
35+
usesType(ma.getArgument(1).getType(), this) and
36+
not this instanceof TypeClass and
37+
not this instanceof TypeObject
38+
)
39+
}
40+
}
41+
42+
predicate test(MethodAccess ma) {
43+
ma.getMethod() instanceof GsonReadValueMethod
44+
}
45+
46+
/** A type used in a `GsonDeserializableField` declaration. */
47+
private class FieldReferencedGsonDeserializableType extends GsonDeserializableType {
48+
FieldReferencedGsonDeserializableType() {
49+
exists(GsonDeserializableField f | usesType(f.getType(), this))
50+
}
51+
}
52+
53+
/** A field that may be deserialized using the Gson JSON framework. */
54+
class GsonDeserializableField extends DeserializableField {
55+
pragma[assume_small_delta]
56+
GsonDeserializableField() {
57+
exists(GsonDeserializableType superType |
58+
superType = this.getDeclaringType().getAnAncestor() and
59+
not superType instanceof TypeObject and
60+
// TODO: if we have the source, can we just track the flow through the backing fields?
61+
//superType.fromSource()
62+
not superType.(RefType).getPackage().getName().matches("java%")
63+
)
64+
}
65+
}
66+
67+
private class GsonInheritTaint extends DataFlow::FieldContent, TaintInheritingContent {
68+
GsonInheritTaint() {
69+
this.getField() instanceof GsonDeserializableField
70+
}
71+
}

0 commit comments

Comments
 (0)