Skip to content

Commit 61ef9e2

Browse files
committed
JS: Switch to shared XML.qll implementation
1 parent a6c1471 commit 61ef9e2

File tree

3 files changed

+42
-276
lines changed

3 files changed

+42
-276
lines changed

javascript/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dependencies:
1111
codeql/regex: ${workspace}
1212
codeql/tutorial: ${workspace}
1313
codeql/util: ${workspace}
14+
codeql/xml: ${workspace}
1415
codeql/yaml: ${workspace}
1516
dataExtensions:
1617
- semmle/javascript/frameworks/**/model.yml

javascript/ql/lib/semmle/javascript/XML.qll

Lines changed: 40 additions & 275 deletions
Original file line numberDiff line numberDiff line change
@@ -4,302 +4,67 @@
44

55
import semmle.files.FileSystem
66
private import semmle.javascript.internal.Locations
7+
private import codeql.xml.Xml
78

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;
1011

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) }
1513

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;
5215

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;
5517

56-
/** Gets a child element of this XML parent. */
57-
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
18+
class XmlElementBase = @xmlelement;
5819

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;
6121

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) }
6423

65-
/** Gets a character sequence that is a child of this XML parent. */
66-
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
24+
class XmlDtdBase = @xmldtd;
6725

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)
8428
}
8529

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)
14934
}
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, _, _, _) }
16935

170-
/** Gets the XML file in which this XML element occurs. */
171-
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
36+
class XmlAttributeBase = @xmlattribute;
17237

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+
}
23244

233-
/** Gets a printable representation of this XML attribute. */
234-
override string toString() { result = this.getName() + "=" + this.getValue() }
235-
}
45+
class XmlNamespaceBase = @xmlnamespace;
23646

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+
}
24950

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+
}
25254

253-
/** Holds if this namespace has no prefix. */
254-
predicate isDefault() { this.getPrefix() = "" }
55+
class XmlCommentBase = @xmlcomment;
25556

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)
26059
}
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, _, _) }
27560

276-
/** Gets the parent of this XML comment. */
277-
XmlParent getParent() { xmlComments(this, _, result, _) }
61+
class XmlCharactersBase = @xmlcharacters;
27862

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+
}
28168
}
28269

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>

javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import javascript
8-
import codeql.serverless.ServerLess
8+
private import codeql.serverless.ServerLess
99

1010
private module YamlImpl implements Input {
1111
import semmle.javascript.Files

0 commit comments

Comments
 (0)