|
3 | 3 | */ |
4 | 4 |
|
5 | 5 | import semmle.files.FileSystem |
| 6 | +private import codeql.xml.Xml |
6 | 7 |
|
7 | | -private class TXmlLocatable = |
8 | | - @xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters; |
| 8 | +private module Input implements InputSig<File, Location> { |
| 9 | + class XmlLocatableBase = @xmllocatable or @xmlnamespaceable; |
9 | 10 |
|
10 | | -/** An XML element that has a location. */ |
11 | | -class XmlLocatable extends @xmllocatable, TXmlLocatable { |
12 | | - /** Gets the source location for this element. */ |
13 | | - Location getLocation() { xmllocations(this, result) } |
| 11 | + predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) } |
14 | 12 |
|
15 | | - /** |
16 | | - * Holds if this element is at the specified location. |
17 | | - * The location spans column `startcolumn` of line `startline` to |
18 | | - * column `endcolumn` of line `endline` in file `filepath`. |
19 | | - * For more information, see |
20 | | - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). |
21 | | - */ |
22 | | - predicate hasLocationInfo( |
23 | | - string filepath, int startline, int startcolumn, int endline, int endcolumn |
24 | | - ) { |
25 | | - exists(File f, Location l | l = this.getLocation() | |
26 | | - locations_default(l, f, startline, startcolumn, endline, endcolumn) and |
27 | | - filepath = f.getAbsolutePath() |
28 | | - ) |
29 | | - } |
30 | | - |
31 | | - /** Gets a textual representation of this element. */ |
32 | | - string toString() { none() } // overridden in subclasses |
33 | | -} |
34 | | - |
35 | | -/** |
36 | | - * An `XmlParent` is either an `XmlElement` or an `XmlFile`, |
37 | | - * both of which can contain other elements. |
38 | | - */ |
39 | | -class XmlParent extends @xmlparent { |
40 | | - XmlParent() { |
41 | | - // explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`; |
42 | | - // the type `@xmlparent` currently also includes non-XML files |
43 | | - this instanceof @xmlelement or xmlEncoding(this, _) |
44 | | - } |
45 | | - |
46 | | - /** |
47 | | - * Gets a printable representation of this XML parent. |
48 | | - * (Intended to be overridden in subclasses.) |
49 | | - */ |
50 | | - string getName() { none() } // overridden in subclasses |
51 | | - |
52 | | - /** Gets the file to which this XML parent belongs. */ |
53 | | - XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) } |
| 13 | + class XmlParentBase = @xmlparent; |
54 | 14 |
|
55 | | - /** Gets the child element at a specified index of this XML parent. */ |
56 | | - XmlElement getChild(int index) { xmlElements(result, _, this, index, _) } |
| 15 | + class XmlNamespaceableBase = @xmlnamespaceable; |
57 | 16 |
|
58 | | - /** Gets a child element of this XML parent. */ |
59 | | - XmlElement getAChild() { xmlElements(result, _, this, _, _) } |
| 17 | + class XmlElementBase = @xmlelement; |
60 | 18 |
|
61 | | - /** Gets a child element of this XML parent with the given `name`. */ |
62 | | - XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) } |
| 19 | + class XmlFileBase = File; |
63 | 20 |
|
64 | | - /** Gets a comment that is a child of this XML parent. */ |
65 | | - XmlComment getAComment() { xmlComments(result, _, this, _) } |
| 21 | + predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) } |
66 | 22 |
|
67 | | - /** Gets a character sequence that is a child of this XML parent. */ |
68 | | - XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) } |
| 23 | + class XmlDtdBase = @xmldtd; |
69 | 24 |
|
70 | | - /** Gets the depth in the tree. (Overridden in XmlElement.) */ |
71 | | - int getDepth() { result = 0 } |
72 | | - |
73 | | - /** Gets the number of child XML elements of this XML parent. */ |
74 | | - int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) } |
75 | | - |
76 | | - /** Gets the number of places in the body of this XML parent where text occurs. */ |
77 | | - int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) } |
78 | | - |
79 | | - /** |
80 | | - * Gets the result of appending all the character sequences of this XML parent from |
81 | | - * left to right, separated by a space. |
82 | | - */ |
83 | | - string allCharactersString() { |
84 | | - result = |
85 | | - concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos) |
| 25 | + predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) { |
| 26 | + xmlDTDs(e, root, publicId, systemId, file) |
86 | 27 | } |
87 | 28 |
|
88 | | - /** Gets the text value contained in this XML parent. */ |
89 | | - string getTextValue() { result = this.allCharactersString() } |
90 | | - |
91 | | - /** Gets a printable representation of this XML parent. */ |
92 | | - string toString() { result = this.getName() } |
93 | | -} |
94 | | - |
95 | | -/** An XML file. */ |
96 | | -class XmlFile extends XmlParent, File { |
97 | | - XmlFile() { xmlEncoding(this, _) } |
98 | | - |
99 | | - /** Gets a printable representation of this XML file. */ |
100 | | - override string toString() { result = this.getName() } |
101 | | - |
102 | | - /** Gets the name of this XML file. */ |
103 | | - override string getName() { result = File.super.getAbsolutePath() } |
104 | | - |
105 | | - /** Gets the encoding of this XML file. */ |
106 | | - string getEncoding() { xmlEncoding(this, result) } |
107 | | - |
108 | | - /** Gets the XML file itself. */ |
109 | | - override XmlFile getFile() { result = this } |
110 | | - |
111 | | - /** Gets a top-most element in an XML file. */ |
112 | | - XmlElement getARootElement() { result = this.getAChild() } |
113 | | - |
114 | | - /** Gets a DTD associated with this XML file. */ |
115 | | - XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) } |
116 | | -} |
117 | | - |
118 | | -/** |
119 | | - * An XML document type definition (DTD). |
120 | | - * |
121 | | - * Example: |
122 | | - * |
123 | | - * ``` |
124 | | - * <!ELEMENT person (firstName, lastName?)> |
125 | | - * <!ELEMENT firstName (#PCDATA)> |
126 | | - * <!ELEMENT lastName (#PCDATA)> |
127 | | - * ``` |
128 | | - */ |
129 | | -class XmlDtd extends XmlLocatable, @xmldtd { |
130 | | - /** Gets the name of the root element of this DTD. */ |
131 | | - string getRoot() { xmlDTDs(this, result, _, _, _) } |
132 | | - |
133 | | - /** Gets the public ID of this DTD. */ |
134 | | - string getPublicId() { xmlDTDs(this, _, result, _, _) } |
135 | | - |
136 | | - /** Gets the system ID of this DTD. */ |
137 | | - string getSystemId() { xmlDTDs(this, _, _, result, _) } |
138 | | - |
139 | | - /** Holds if this DTD is public. */ |
140 | | - predicate isPublic() { not xmlDTDs(this, _, "", _, _) } |
141 | | - |
142 | | - /** Gets the parent of this DTD. */ |
143 | | - XmlParent getParent() { xmlDTDs(this, _, _, _, result) } |
144 | | - |
145 | | - override string toString() { |
146 | | - this.isPublic() and |
147 | | - result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'" |
148 | | - or |
149 | | - not this.isPublic() and |
150 | | - result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'" |
| 29 | + predicate xmlElements_( |
| 30 | + XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file |
| 31 | + ) { |
| 32 | + xmlElements(e, name, parent, idx, file) |
151 | 33 | } |
152 | | -} |
153 | | - |
154 | | -/** |
155 | | - * An XML element in an XML file. |
156 | | - * |
157 | | - * Example: |
158 | | - * |
159 | | - * ``` |
160 | | - * <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
161 | | - * package="com.example.exampleapp" android:versionCode="1"> |
162 | | - * </manifest> |
163 | | - * ``` |
164 | | - */ |
165 | | -class XmlElement extends @xmlelement, XmlParent, XmlLocatable { |
166 | | - /** Holds if this XML element has the given `name`. */ |
167 | | - predicate hasName(string name) { name = this.getName() } |
168 | | - |
169 | | - /** Gets the name of this XML element. */ |
170 | | - override string getName() { xmlElements(this, result, _, _, _) } |
171 | 34 |
|
172 | | - /** Gets the XML file in which this XML element occurs. */ |
173 | | - override XmlFile getFile() { xmlElements(this, _, _, _, result) } |
| 35 | + class XmlAttributeBase = @xmlattribute; |
174 | 36 |
|
175 | | - /** Gets the parent of this XML element. */ |
176 | | - XmlParent getParent() { xmlElements(this, _, result, _, _) } |
177 | | - |
178 | | - /** Gets the index of this XML element among its parent's children. */ |
179 | | - int getIndex() { xmlElements(this, _, _, result, _) } |
180 | | - |
181 | | - /** Holds if this XML element has a namespace. */ |
182 | | - predicate hasNamespace() { xmlHasNs(this, _, _) } |
183 | | - |
184 | | - /** Gets the namespace of this XML element, if any. */ |
185 | | - XmlNamespace getNamespace() { xmlHasNs(this, result, _) } |
186 | | - |
187 | | - /** Gets the index of this XML element among its parent's children. */ |
188 | | - int getElementPositionIndex() { xmlElements(this, _, _, result, _) } |
189 | | - |
190 | | - /** Gets the depth of this element within the XML file tree structure. */ |
191 | | - override int getDepth() { result = this.getParent().getDepth() + 1 } |
192 | | - |
193 | | - /** Gets an XML attribute of this XML element. */ |
194 | | - XmlAttribute getAnAttribute() { result.getElement() = this } |
195 | | - |
196 | | - /** Gets the attribute with the specified `name`, if any. */ |
197 | | - XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name } |
198 | | - |
199 | | - /** Holds if this XML element has an attribute with the specified `name`. */ |
200 | | - predicate hasAttribute(string name) { exists(this.getAttribute(name)) } |
201 | | - |
202 | | - /** Gets the value of the attribute with the specified `name`, if any. */ |
203 | | - string getAttributeValue(string name) { result = this.getAttribute(name).getValue() } |
204 | | - |
205 | | - /** Gets a printable representation of this XML element. */ |
206 | | - override string toString() { result = this.getName() } |
207 | | -} |
208 | | - |
209 | | -/** |
210 | | - * An attribute that occurs inside an XML element. |
211 | | - * |
212 | | - * Examples: |
213 | | - * |
214 | | - * ``` |
215 | | - * package="com.example.exampleapp" |
216 | | - * android:versionCode="1" |
217 | | - * ``` |
218 | | - */ |
219 | | -class XmlAttribute extends @xmlattribute, XmlLocatable { |
220 | | - /** Gets the name of this attribute. */ |
221 | | - string getName() { xmlAttrs(this, _, result, _, _, _) } |
222 | | - |
223 | | - /** Gets the XML element to which this attribute belongs. */ |
224 | | - XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) } |
225 | | - |
226 | | - /** Holds if this attribute has a namespace. */ |
227 | | - predicate hasNamespace() { xmlHasNs(this, _, _) } |
228 | | - |
229 | | - /** Gets the namespace of this attribute, if any. */ |
230 | | - XmlNamespace getNamespace() { xmlHasNs(this, result, _) } |
231 | | - |
232 | | - /** Gets the value of this attribute. */ |
233 | | - string getValue() { xmlAttrs(this, _, _, result, _, _) } |
| 37 | + predicate xmlAttrs_( |
| 38 | + XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx, |
| 39 | + XmlFileBase file |
| 40 | + ) { |
| 41 | + xmlAttrs(e, elementid, name, value, idx, file) |
| 42 | + } |
234 | 43 |
|
235 | | - /** Gets a printable representation of this XML attribute. */ |
236 | | - override string toString() { result = this.getName() + "=" + this.getValue() } |
237 | | -} |
| 44 | + class XmlNamespaceBase = @xmlnamespace; |
238 | 45 |
|
239 | | -/** |
240 | | - * A namespace used in an XML file. |
241 | | - * |
242 | | - * Example: |
243 | | - * |
244 | | - * ``` |
245 | | - * xmlns:android="http://schemas.android.com/apk/res/android" |
246 | | - * ``` |
247 | | - */ |
248 | | -class XmlNamespace extends XmlLocatable, @xmlnamespace { |
249 | | - /** Gets the prefix of this namespace. */ |
250 | | - string getPrefix() { xmlNs(this, result, _, _) } |
| 46 | + predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) { |
| 47 | + xmlNs(e, prefixName, uri, file) |
| 48 | + } |
251 | 49 |
|
252 | | - /** Gets the URI of this namespace. */ |
253 | | - string getUri() { xmlNs(this, _, result, _) } |
| 50 | + predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) { |
| 51 | + xmlHasNs(e, ns, file) |
| 52 | + } |
254 | 53 |
|
255 | | - /** Holds if this namespace has no prefix. */ |
256 | | - predicate isDefault() { this.getPrefix() = "" } |
| 54 | + class XmlCommentBase = @xmlcomment; |
257 | 55 |
|
258 | | - override string toString() { |
259 | | - this.isDefault() and result = this.getUri() |
260 | | - or |
261 | | - not this.isDefault() and result = this.getPrefix() + ":" + this.getUri() |
| 56 | + predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) { |
| 57 | + xmlComments(e, text, parent, file) |
262 | 58 | } |
263 | | -} |
264 | | - |
265 | | -/** |
266 | | - * A comment in an XML file. |
267 | | - * |
268 | | - * Example: |
269 | | - * |
270 | | - * ``` |
271 | | - * <!-- This is a comment. --> |
272 | | - * ``` |
273 | | - */ |
274 | | -class XmlComment extends @xmlcomment, XmlLocatable { |
275 | | - /** Gets the text content of this XML comment. */ |
276 | | - string getText() { xmlComments(this, result, _, _) } |
277 | 59 |
|
278 | | - /** Gets the parent of this XML comment. */ |
279 | | - XmlParent getParent() { xmlComments(this, _, result, _) } |
| 60 | + class XmlCharactersBase = @xmlcharacters; |
280 | 61 |
|
281 | | - /** Gets a printable representation of this XML comment. */ |
282 | | - override string toString() { result = this.getText() } |
| 62 | + predicate xmlChars_( |
| 63 | + XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file |
| 64 | + ) { |
| 65 | + xmlChars(e, text, parent, idx, isCDATA, file) |
| 66 | + } |
283 | 67 | } |
284 | 68 |
|
285 | | -/** |
286 | | - * A sequence of characters that occurs between opening and |
287 | | - * closing tags of an XML element, excluding other elements. |
288 | | - * |
289 | | - * Example: |
290 | | - * |
291 | | - * ``` |
292 | | - * <content>This is a sequence of characters.</content> |
293 | | - * ``` |
294 | | - */ |
295 | | -class XmlCharacters extends @xmlcharacters, XmlLocatable { |
296 | | - /** Gets the content of this character sequence. */ |
297 | | - string getCharacters() { xmlChars(this, result, _, _, _, _) } |
298 | | - |
299 | | - /** Gets the parent of this character sequence. */ |
300 | | - XmlParent getParent() { xmlChars(this, _, result, _, _, _) } |
301 | | - |
302 | | - /** Holds if this character sequence is CDATA. */ |
303 | | - predicate isCDATA() { xmlChars(this, _, _, _, 1, _) } |
304 | | - |
305 | | - /** Gets a printable representation of this XML character sequence. */ |
306 | | - override string toString() { result = this.getCharacters() } |
307 | | -} |
| 69 | +import Make<File, Location, Input> |
0 commit comments