forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJAXB.qll
More file actions
203 lines (179 loc) · 6.57 KB
/
Copy pathJAXB.qll
File metadata and controls
203 lines (179 loc) · 6.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/** Definitions related to JAXB. */
import semmle.code.java.Type
library class JAXBElement extends Class {
JAXBElement() {
this.getASupertype*().getQualifiedName() = "javax.xml.bind.JAXBElement" or
this.getAnAnnotation().getType().getName() = "XmlRootElement"
}
}
library class JAXBMarshalMethod extends Method {
JAXBMarshalMethod() {
this.getDeclaringType().getQualifiedName() = "javax.xml.bind.Marshaller" and
this.getName() = "marshal"
}
}
class JaxbAnnotationType extends AnnotationType {
JaxbAnnotationType() { this.getPackage().getName() = "javax.xml.bind.annotation" }
}
class JaxbAnnotated extends Annotatable {
JaxbAnnotated() { this.getAnAnnotation().getType() instanceof JaxbAnnotationType }
predicate hasJaxbAnnotation(string name) { hasJaxbAnnotation(this, name) }
}
private predicate hasJaxbAnnotation(Annotatable annotatable, string name) {
annotatable.getAnAnnotation().getType().(JaxbAnnotationType).hasName(name)
}
/**
* A class that is mapped to an XML schema.
*/
class JaxbType extends Class {
JaxbType() {
// Explicitly an `XmlType`.
hasJaxbAnnotation(this, "XmlType")
or
hasJaxbAnnotation(this, "XmlRootElement")
or
// There is at least one Jaxb annotation on a member of this class. The `@XmlType` is implied
// on any class, but we limit our identification to those that have some reference to JAXB.
exists(AnnotationType at |
at = this.getAMember().getAnAnnotation().getType() and
at instanceof JaxbMemberAnnotation
)
}
private XmlAccessType getDeclaredAccessType() {
// This ignores cases where the `XmlAccessorType` is defined on a supertype.
exists(Annotation a |
this.getAnAnnotation() = a and
a.getType().(JaxbAnnotationType).hasName("XmlAccessorType")
|
result.getAnAccess() = a.getValue("value")
)
}
/**
* Gets the `XmlAccessType` associated with this class.
*/
XmlAccessType getXmlAccessType() {
if exists(this.getDeclaredAccessType())
then result = this.getDeclaredAccessType()
else
// Default access type, if not specified.
result.isPublicMember()
}
}
/**
* An `XmlAccessType` is applied to a `JaxbType` to indicate which members will be automatically bound.
*/
class XmlAccessType extends EnumConstant {
XmlAccessType() {
exists(EnumType type | type.getName() = "XmlAccessType" and type.getAnEnumConstant() = this)
}
/**
* All public getter/setter pairs and public fields will be bound.
*/
predicate isPublicMember() { this.getName() = "PUBLIC_MEMBER" }
/**
* All non-static, non-transient fields will be bound.
*/
predicate isField() { this.getName() = "FIELD" }
/**
* All getter/setter pairs will be bound.
*/
predicate isProperty() { this.getName() = "PROPERTY" }
/**
* Nothing will be bound automatically.
*/
predicate isNone() { this.getName() = "NONE" }
}
/**
* An annotation on a class member indicating that this member corresponds to an XML element or
* attribute in the XML schema represented by this class.
*/
class JaxbMemberAnnotation extends JaxbAnnotationType {
JaxbMemberAnnotation() {
this.hasName("XmlElement") or
this.hasName("XmlAttribute") or
this.hasName("XmlElementRefs") or
this.hasName("XmlElements")
}
}
private predicate isTransient(Member m) { hasJaxbAnnotation(m, "XmlTransient") }
/**
* A field is "bound" to an XML element or attribute if it is either annotated as such, or it is
* bound due to the `XmlAccessType` of the declaring class.
*/
class JaxbBoundField extends Field {
JaxbBoundField() {
// Fields cannot be static, because JAXB creates instances.
not this.isStatic() and
// Fields cannot be final, because JAXB instantiates the object, then sets the properties.
not this.isFinal() and
// No transient fields are ever bound.
not isTransient(this) and
(
// Explicitly annotated to be bound.
exists(this.getAnAnnotation().getType().(JaxbMemberAnnotation))
or
// Within a JAXB type which has an `XmlAcessType` that binds this field.
exists(JaxbType type | this.getDeclaringType() = type |
// All fields are automatically bound in this access type.
type.getXmlAccessType().isField()
or
// Only public fields are automatically bound in this access type.
type.getXmlAccessType().isPublicMember() and this.isPublic()
)
)
}
}
/**
* A getter or setter method, as defined by whether the method name starts with "set" or "get".
*/
library class GetterOrSetterMethod extends Method {
GetterOrSetterMethod() { this.getName().matches("get%") or this.getName().matches("set%") }
Field getField() {
result.getDeclaringType() = this.getDeclaringType() and
result.getName().toLowerCase() = this.getName().suffix(3).toLowerCase()
}
/**
* Holds if this method has a "pair"ed method, e.g. whether there is an equivalent getter if this
* is a setter, and vice versa.
*/
predicate isProperty() { exists(this.getPair()) }
/**
* Gets the "pair" method, if one exists; that is, the getter if this is a setter, and vice versa.
*/
GetterOrSetterMethod getPair() { result.getField() = this.getField() and not result = this }
/**
* Gets either this method or its pair.
*/
GetterOrSetterMethod getThisOrPair() { result.getField() = this.getField() }
}
/**
* A getter or setter that is "bound" to an XML element or attribute.
*/
class JaxbBoundGetterSetter extends GetterOrSetterMethod {
JaxbBoundGetterSetter() {
// Neither setter nor getter should be marked transient.
not isTransient(this) and
not isTransient(this.getPair()) and
(
// An annotated field which indicates that this is a getter or setter.
this.getField() instanceof JaxbBoundField
or
// An annotation on this method or the pair that indicate that it is a valid setter/getter.
this.getThisOrPair().getAnAnnotation().getType() instanceof JaxbMemberAnnotation
or
// Within a JAXB type which has an `XmlAcessType` that binds this method.
exists(JaxbType c | this.getDeclaringType() = c |
// If this is a "property" - both a setter and getter present for the XML element or attribute
// - the `XmlAccessType` of the declaring type may cause this property to be bound.
this.isProperty() and
(
// In the `PUBLIC_MEMBER` case all public properties are considered bound.
c.getXmlAccessType().isPublicMember() and this.isPublic()
or
// In "property" all properties are considered bound.
c.getXmlAccessType().isProperty()
)
)
)
}
}