|
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