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