|
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