mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #15923 from hvitved/shared-xml-impl
Properly shared `XML.qll` implementation
This commit is contained in:
@@ -251,12 +251,6 @@
|
||||
"cpp/ql/src/Security/CWE/CWE-020/SafeExternalAPIFunction.qll",
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ir/SafeExternalAPIFunction.qll"
|
||||
],
|
||||
"XML": [
|
||||
"cpp/ql/lib/semmle/code/cpp/XML.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/XML.qll",
|
||||
"java/ql/lib/semmle/code/xml/XML.qll",
|
||||
"python/ql/lib/semmle/python/xml/XML.qll"
|
||||
],
|
||||
"DuplicationProblems.inc.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/DuplicationProblems.inc.qhelp",
|
||||
"javascript/ql/src/Metrics/DuplicationProblems.inc.qhelp",
|
||||
|
||||
@@ -11,4 +11,5 @@ dependencies:
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -3,305 +3,67 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.xml.Xml
|
||||
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
private module Input implements InputSig<File, Location> {
|
||||
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
class XmlParentBase = @xmlparent;
|
||||
|
||||
class XmlNamespaceableBase = @xmlnamespaceable;
|
||||
|
||||
class XmlElementBase = @xmlelement;
|
||||
|
||||
class XmlFileBase = File;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) }
|
||||
|
||||
class XmlDtdBase = @xmldtd;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) {
|
||||
xmlDTDs(e, root, publicId, systemId, file)
|
||||
}
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
) {
|
||||
exists(File f, Location l | l = this.getLocation() |
|
||||
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
xmlElements(e, name, parent, idx, file)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
class XmlAttributeBase = @xmlattribute;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XmlParent extends @xmlparent {
|
||||
XmlParent() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
) {
|
||||
xmlAttrs(e, elementid, name, value, idx, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
string getName() { none() } // overridden in subclasses
|
||||
class XmlNamespaceBase = @xmlnamespace;
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) {
|
||||
xmlNs(e, prefixName, uri, file)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) {
|
||||
xmlHasNs(e, ns, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
class XmlCommentBase = @xmlcomment;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) {
|
||||
xmlComments(e, text, parent, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
class XmlCharactersBase = @xmlcharacters;
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
) {
|
||||
xmlChars(e, text, parent, idx, isCDATA, file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
import Make<File, Location, Input>
|
||||
|
||||
@@ -13,6 +13,7 @@ dependencies:
|
||||
codeql/threat-models: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
dataExtensions:
|
||||
- ext/*.model.yml
|
||||
- ext/generated/*.model.yml
|
||||
|
||||
@@ -3,305 +3,67 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.xml.Xml
|
||||
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
private module Input implements InputSig<File, Location> {
|
||||
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
class XmlParentBase = @xmlparent;
|
||||
|
||||
class XmlNamespaceableBase = @xmlnamespaceable;
|
||||
|
||||
class XmlElementBase = @xmlelement;
|
||||
|
||||
class XmlFileBase = File;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) }
|
||||
|
||||
class XmlDtdBase = @xmldtd;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) {
|
||||
xmlDTDs(e, root, publicId, systemId, file)
|
||||
}
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
) {
|
||||
exists(File f, Location l | l = this.getLocation() |
|
||||
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
xmlElements(e, name, parent, idx, file)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
class XmlAttributeBase = @xmlattribute;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XmlParent extends @xmlparent {
|
||||
XmlParent() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
) {
|
||||
xmlAttrs(e, elementid, name, value, idx, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
string getName() { none() } // overridden in subclasses
|
||||
class XmlNamespaceBase = @xmlnamespace;
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) {
|
||||
xmlNs(e, prefixName, uri, file)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) {
|
||||
xmlHasNs(e, ns, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
class XmlCommentBase = @xmlcomment;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) {
|
||||
xmlComments(e, text, parent, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
class XmlCharactersBase = @xmlcharacters;
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
) {
|
||||
xmlChars(e, text, parent, idx, isCDATA, file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
import Make<File, Location, Input>
|
||||
|
||||
@@ -14,6 +14,7 @@ dependencies:
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/typetracking: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
dataExtensions:
|
||||
- ext/*.model.yml
|
||||
- ext/generated/*.model.yml
|
||||
|
||||
@@ -19,7 +19,8 @@ class SpringBean extends SpringXmlElement {
|
||||
not this.getNamespace().getUri() = "http://camel.apache.org/schema/spring"
|
||||
}
|
||||
|
||||
override string toString() { result = this.getBeanIdentifier() }
|
||||
/** Gets a printable representation of this XML element. */
|
||||
string toString() { result = this.getBeanIdentifier() }
|
||||
|
||||
/**
|
||||
* Holds if this element is a top-level bean definition.
|
||||
|
||||
@@ -9,7 +9,8 @@ import semmle.code.java.frameworks.spring.SpringValue
|
||||
class SpringProperty extends SpringXmlElement {
|
||||
SpringProperty() { this.getName() = "property" }
|
||||
|
||||
override string toString() { result = this.getPropertyName() }
|
||||
/** Gets a printable representation of this XML element. */
|
||||
string toString() { result = this.getPropertyName() }
|
||||
|
||||
/** Gets the value of the `name` attribute. */
|
||||
string getPropertyName() { result = this.getAttributeValue("name") }
|
||||
|
||||
@@ -9,7 +9,7 @@ class AntTarget extends XmlElement {
|
||||
AntTarget() { super.getName() = "target" }
|
||||
|
||||
/** Gets the name of this Ant target. */
|
||||
override string getName() { result = this.getAttributeValue("name") }
|
||||
string getName() { result = this.getAttributeValue("name") }
|
||||
|
||||
/**
|
||||
* Gets a string containing the dependencies of this Ant target,
|
||||
|
||||
@@ -3,305 +3,67 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.xml.Xml
|
||||
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
private module Input implements InputSig<File, Location> {
|
||||
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
class XmlParentBase = @xmlparent;
|
||||
|
||||
class XmlNamespaceableBase = @xmlnamespaceable;
|
||||
|
||||
class XmlElementBase = @xmlelement;
|
||||
|
||||
class XmlFileBase = File;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) }
|
||||
|
||||
class XmlDtdBase = @xmldtd;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) {
|
||||
xmlDTDs(e, root, publicId, systemId, file)
|
||||
}
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
) {
|
||||
exists(File f, Location l | l = this.getLocation() |
|
||||
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
xmlElements(e, name, parent, idx, file)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
class XmlAttributeBase = @xmlattribute;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XmlParent extends @xmlparent {
|
||||
XmlParent() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
) {
|
||||
xmlAttrs(e, elementid, name, value, idx, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
string getName() { none() } // overridden in subclasses
|
||||
class XmlNamespaceBase = @xmlnamespace;
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) {
|
||||
xmlNs(e, prefixName, uri, file)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) {
|
||||
xmlHasNs(e, ns, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
class XmlCommentBase = @xmlcomment;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) {
|
||||
xmlComments(e, text, parent, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
class XmlCharactersBase = @xmlcharacters;
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
) {
|
||||
xmlChars(e, text, parent, idx, isCDATA, file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
import Make<File, Location, Input>
|
||||
|
||||
@@ -11,6 +11,7 @@ dependencies:
|
||||
codeql/regex: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
codeql/yaml: ${workspace}
|
||||
dataExtensions:
|
||||
- semmle/javascript/frameworks/**/model.yml
|
||||
|
||||
@@ -4,302 +4,67 @@
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import semmle.javascript.internal.Locations
|
||||
private import codeql.xml.Xml
|
||||
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
private module Input implements InputSig<File, DbLocation> {
|
||||
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
DbLocation getLocation() { result = getLocatableLocation(this) }
|
||||
predicate xmllocations_(XmlLocatableBase e, DbLocation loc) { loc = getLocatableLocation(e) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
class XmlParentBase = @xmlparent;
|
||||
|
||||
class XmlNamespaceableBase = @xmlnamespaceable;
|
||||
|
||||
class XmlElementBase = @xmlelement;
|
||||
|
||||
class XmlFileBase = File;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) }
|
||||
|
||||
class XmlDtdBase = @xmldtd;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) {
|
||||
xmlDTDs(e, root, publicId, systemId, file)
|
||||
}
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
xmlElements(e, name, parent, idx, file)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
class XmlAttributeBase = @xmlattribute;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XmlParent extends @xmlparent {
|
||||
XmlParent() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
) {
|
||||
xmlAttrs(e, elementid, name, value, idx, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
string getName() { none() } // overridden in subclasses
|
||||
class XmlNamespaceBase = @xmlnamespace;
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) {
|
||||
xmlNs(e, prefixName, uri, file)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) {
|
||||
xmlHasNs(e, ns, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
class XmlCommentBase = @xmlcomment;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) {
|
||||
xmlComments(e, text, parent, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
class XmlCharactersBase = @xmlcharacters;
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
) {
|
||||
xmlChars(e, text, parent, idx, isCDATA, file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
import Make<File, DbLocation, Input>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import codeql.serverless.ServerLess
|
||||
private import codeql.serverless.ServerLess
|
||||
|
||||
private module YamlImpl implements Input {
|
||||
import semmle.javascript.Files
|
||||
|
||||
@@ -11,6 +11,7 @@ dependencies:
|
||||
codeql/regex: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
codeql/xml: ${workspace}
|
||||
codeql/yaml: ${workspace}
|
||||
dataExtensions:
|
||||
- semmle/python/frameworks/**/*.model.yml
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import python
|
||||
import codeql.serverless.ServerLess
|
||||
private import codeql.serverless.ServerLess
|
||||
import semmle.python.dataflow.new.DataFlow
|
||||
import semmle.python.dataflow.new.RemoteFlowSources
|
||||
|
||||
|
||||
@@ -3,305 +3,67 @@
|
||||
*/
|
||||
|
||||
import semmle.files.FileSystem
|
||||
private import codeql.xml.Xml
|
||||
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
private module Input implements InputSig<File, Location> {
|
||||
class XmlLocatableBase = @xmllocatable or @xmlnamespaceable;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XmlLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
predicate xmllocations_(XmlLocatableBase e, Location loc) { xmllocations(e, loc) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
class XmlParentBase = @xmlparent;
|
||||
|
||||
class XmlNamespaceableBase = @xmlnamespaceable;
|
||||
|
||||
class XmlElementBase = @xmlelement;
|
||||
|
||||
class XmlFileBase = File;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc) { xmlEncoding(f, enc) }
|
||||
|
||||
class XmlDtdBase = @xmldtd;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file) {
|
||||
xmlDTDs(e, root, publicId, systemId, file)
|
||||
}
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
) {
|
||||
exists(File f, Location l | l = this.getLocation() |
|
||||
locations_default(l, f, startline, startcolumn, endline, endcolumn) and
|
||||
filepath = f.getAbsolutePath()
|
||||
)
|
||||
xmlElements(e, name, parent, idx, file)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
class XmlAttributeBase = @xmlattribute;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
class XmlParent extends @xmlparent {
|
||||
XmlParent() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof @xmlelement or xmlEncoding(this, _)
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
) {
|
||||
xmlAttrs(e, elementid, name, value, idx, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a printable representation of this XML parent.
|
||||
* (Intended to be overridden in subclasses.)
|
||||
*/
|
||||
string getName() { none() } // overridden in subclasses
|
||||
class XmlNamespaceBase = @xmlnamespace;
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) { xmlElements(result, _, this, _, _) and result.hasName(name) }
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos | xmlChars(_, chars, this, pos, _, _) | chars, " " order by pos)
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file) {
|
||||
xmlNs(e, prefixName, uri, file)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file) {
|
||||
xmlHasNs(e, ns, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
class XmlCommentBase = @xmlcomment;
|
||||
|
||||
/** An XML file. */
|
||||
class XmlFile extends XmlParent, File {
|
||||
XmlFile() { xmlEncoding(this, _) }
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file) {
|
||||
xmlComments(e, text, parent, file)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = this.getName() }
|
||||
class XmlCharactersBase = @xmlcharacters;
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
class XmlDtd extends XmlLocatable, @xmldtd {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
) {
|
||||
xmlChars(e, text, parent, idx, isCDATA, file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
class XmlElement extends @xmlelement, XmlParent, XmlLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
class XmlAttribute extends @xmlattribute, XmlLocatable {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
class XmlNamespace extends XmlLocatable, @xmlnamespace {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
class XmlComment extends @xmlcomment, XmlLocatable {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
class XmlCharacters extends @xmlcharacters, XmlLocatable {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
import Make<File, Location, Input>
|
||||
|
||||
401
shared/xml/codeql/xml/Xml.qll
Normal file
401
shared/xml/codeql/xml/Xml.qll
Normal file
@@ -0,0 +1,401 @@
|
||||
/**
|
||||
* Provides classes and predicates for working with XML files and their content.
|
||||
*/
|
||||
|
||||
private import codeql.util.Location
|
||||
private import codeql.util.FileSystem
|
||||
|
||||
/** Provides the input specification of the XML implementation. */
|
||||
signature module InputSig<FileSig File, LocationSig Location> {
|
||||
class XmlLocatableBase;
|
||||
|
||||
predicate xmllocations_(XmlLocatableBase e, Location loc);
|
||||
|
||||
class XmlParentBase;
|
||||
|
||||
class XmlNamespaceableBase instanceof XmlLocatableBase;
|
||||
|
||||
class XmlElementBase instanceof XmlParentBase, XmlNamespaceableBase;
|
||||
|
||||
class XmlFileBase extends File instanceof XmlParentBase;
|
||||
|
||||
predicate xmlEncoding_(XmlFileBase f, string enc);
|
||||
|
||||
class XmlDtdBase instanceof XmlLocatableBase;
|
||||
|
||||
predicate xmlDTDs_(XmlDtdBase e, string root, string publicId, string systemId, XmlFileBase file);
|
||||
|
||||
predicate xmlElements_(
|
||||
XmlElementBase e, string name, XmlParentBase parent, int idx, XmlFileBase file
|
||||
);
|
||||
|
||||
class XmlAttributeBase instanceof XmlNamespaceableBase;
|
||||
|
||||
predicate xmlAttrs_(
|
||||
XmlAttributeBase e, XmlElementBase elementid, string name, string value, int idx,
|
||||
XmlFileBase file
|
||||
);
|
||||
|
||||
class XmlNamespaceBase instanceof XmlLocatableBase;
|
||||
|
||||
predicate xmlNs_(XmlNamespaceBase e, string prefixName, string uri, XmlFileBase file);
|
||||
|
||||
predicate xmlHasNs_(XmlNamespaceableBase e, XmlNamespaceBase ns, XmlFileBase file);
|
||||
|
||||
class XmlCommentBase instanceof XmlLocatableBase;
|
||||
|
||||
predicate xmlComments_(XmlCommentBase e, string text, XmlParentBase parent, XmlFileBase file);
|
||||
|
||||
class XmlCharactersBase instanceof XmlLocatableBase;
|
||||
|
||||
predicate xmlChars_(
|
||||
XmlCharactersBase e, string text, XmlParentBase parent, int idx, int isCDATA, XmlFileBase file
|
||||
);
|
||||
}
|
||||
|
||||
/** Provides a class hierarchy for working with XML files. */
|
||||
module Make<FileSig File, LocationSig Location, InputSig<File, Location> Input> {
|
||||
private import Input
|
||||
|
||||
final private class XmlLocatableBaseFinal = XmlLocatableBase;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
abstract private class XmlLocatableImpl extends XmlLocatableBaseFinal {
|
||||
/** Gets the location of this element. */
|
||||
Location getLocation() { xmllocations_(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
final class XmlLocatable = XmlLocatableImpl;
|
||||
|
||||
final private class XmlParentBaseFinal = XmlParentBase;
|
||||
|
||||
final private class XmlElementBaseFinal = XmlElementBase;
|
||||
|
||||
/**
|
||||
* An `XmlParent` is either an `XmlElement` or an `XmlFile`,
|
||||
* both of which can contain other elements.
|
||||
*/
|
||||
abstract private class XmlParentImpl extends XmlParentBaseFinal {
|
||||
XmlParentImpl() {
|
||||
// explicitly restrict `this` to be either an `XmlElement` or an `XmlFile`;
|
||||
// the type `@xmlparent` currently also includes non-XML files
|
||||
this instanceof XmlElementBaseFinal or xmlEncoding_(this, _)
|
||||
}
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
abstract string getName();
|
||||
|
||||
/** Gets the file to which this XML parent belongs. */
|
||||
XmlFile getFile() { result = this or xmlElements_(this, _, _, _, result) }
|
||||
|
||||
/** Gets the child element at a specified index of this XML parent. */
|
||||
XmlElement getChild(int index) { xmlElements_(result, _, this, index, _) }
|
||||
|
||||
/** Gets a child element of this XML parent. */
|
||||
XmlElement getAChild() { xmlElements_(result, _, this, _, _) }
|
||||
|
||||
/** Gets a child element of this XML parent with the given `name`. */
|
||||
XmlElement getAChild(string name) {
|
||||
xmlElements_(result, _, this, _, _) and result.hasName(name)
|
||||
}
|
||||
|
||||
/** Gets a comment that is a child of this XML parent. */
|
||||
XmlComment getAComment() { xmlComments_(result, _, this, _) }
|
||||
|
||||
/** Gets a character sequence that is a child of this XML parent. */
|
||||
XmlCharacters getACharactersSet() { xmlChars_(result, _, this, _, _, _) }
|
||||
|
||||
/** Gets the depth in the tree. (Overridden in XmlElement.) */
|
||||
int getDepth() { result = 0 }
|
||||
|
||||
/** Gets the number of child XML elements of this XML parent. */
|
||||
int getNumberOfChildren() { result = count(XmlElement e | xmlElements_(e, _, this, _, _)) }
|
||||
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars_(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
*/
|
||||
string allCharactersString() {
|
||||
result =
|
||||
concat(string chars, int pos |
|
||||
xmlChars_(_, chars, this, pos, _, _)
|
||||
|
|
||||
chars, " " order by pos
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
final class XmlParent = XmlParentImpl;
|
||||
|
||||
final private class XmlFileBaseFinal = XmlFileBase;
|
||||
|
||||
// needed for the `toString` override in `XmlFileImpl`
|
||||
private class XmlFileBaseMid extends XmlFileBaseFinal {
|
||||
/** Gets a printable representation of this XML file. */
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
/** An XML file. */
|
||||
private class XmlFileImpl extends XmlParentImpl, XmlFileBaseMid {
|
||||
XmlFileImpl() { xmlEncoding_(this, _) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = super.getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding_(this, result) }
|
||||
|
||||
/** Gets the XML file itself. */
|
||||
override XmlFile getFile() { result = this }
|
||||
|
||||
/** Gets a top-most element in an XML file. */
|
||||
XmlElement getARootElement() { result = this.getAChild() }
|
||||
|
||||
/** Gets a DTD associated with this XML file. */
|
||||
XmlDtd getADtd() { xmlDTDs_(result, _, _, _, this) }
|
||||
}
|
||||
|
||||
final class XmlFile = XmlFileImpl;
|
||||
|
||||
final private class XmlDtdBaseFinal = XmlDtdBase;
|
||||
|
||||
/**
|
||||
* An XML document type definition (DTD).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!ELEMENT person (firstName, lastName?)>
|
||||
* <!ELEMENT firstName (#PCDATA)>
|
||||
* <!ELEMENT lastName (#PCDATA)>
|
||||
* ```
|
||||
*/
|
||||
private class XmlDtdImpl extends XmlLocatableImpl, XmlDtdBaseFinal {
|
||||
/** Gets the name of the root element of this DTD. */
|
||||
string getRoot() { xmlDTDs_(this, result, _, _, _) }
|
||||
|
||||
/** Gets the public ID of this DTD. */
|
||||
string getPublicId() { xmlDTDs_(this, _, result, _, _) }
|
||||
|
||||
/** Gets the system ID of this DTD. */
|
||||
string getSystemId() { xmlDTDs_(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this DTD is public. */
|
||||
predicate isPublic() { not xmlDTDs_(this, _, "", _, _) }
|
||||
|
||||
/** Gets the parent of this DTD. */
|
||||
XmlParent getParent() { xmlDTDs_(this, _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
this.isPublic() and
|
||||
result = this.getRoot() + " PUBLIC '" + this.getPublicId() + "' '" + this.getSystemId() + "'"
|
||||
or
|
||||
not this.isPublic() and
|
||||
result = this.getRoot() + " SYSTEM '" + this.getSystemId() + "'"
|
||||
}
|
||||
}
|
||||
|
||||
final class XmlDtd = XmlDtdImpl;
|
||||
|
||||
/**
|
||||
* An XML element in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* package="com.example.exampleapp" android:versionCode="1">
|
||||
* </manifest>
|
||||
* ```
|
||||
*/
|
||||
private class XmlElementImpl extends XmlElementBaseFinal, XmlParentImpl, XmlLocatableImpl {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements_(this, result, _, _, _) }
|
||||
|
||||
/** Gets the XML file in which this XML element occurs. */
|
||||
override XmlFile getFile() { xmlElements_(this, _, _, _, result) }
|
||||
|
||||
/** Gets the parent of this XML element. */
|
||||
XmlParent getParent() { xmlElements_(this, _, result, _, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getIndex() { xmlElements_(this, _, _, result, _) }
|
||||
|
||||
/** Holds if this XML element has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs_(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this XML element, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs_(this, result, _) }
|
||||
|
||||
/** Gets the index of this XML element among its parent's children. */
|
||||
int getElementPositionIndex() { xmlElements_(this, _, _, result, _) }
|
||||
|
||||
/** Gets the depth of this element within the XML file tree structure. */
|
||||
override int getDepth() { result = this.getParent().getDepth() + 1 }
|
||||
|
||||
/** Gets an XML attribute of this XML element. */
|
||||
XmlAttribute getAnAttribute() { result.getElement() = this }
|
||||
|
||||
/** Gets the attribute with the specified `name`, if any. */
|
||||
XmlAttribute getAttribute(string name) {
|
||||
result.getElement() = this and result.getName() = name
|
||||
}
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
final class XmlElement = XmlElementImpl;
|
||||
|
||||
final private class XmlAttributeBaseFinal = XmlAttributeBase;
|
||||
|
||||
/**
|
||||
* An attribute that occurs inside an XML element.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* ```
|
||||
* package="com.example.exampleapp"
|
||||
* android:versionCode="1"
|
||||
* ```
|
||||
*/
|
||||
private class XmlAttributeImpl extends XmlAttributeBaseFinal, XmlLocatableImpl {
|
||||
/** Gets the name of this attribute. */
|
||||
string getName() { xmlAttrs_(this, _, result, _, _, _) }
|
||||
|
||||
/** Gets the XML element to which this attribute belongs. */
|
||||
XmlElement getElement() { xmlAttrs_(this, result, _, _, _, _) }
|
||||
|
||||
/** Holds if this attribute has a namespace. */
|
||||
predicate hasNamespace() { xmlHasNs_(this, _, _) }
|
||||
|
||||
/** Gets the namespace of this attribute, if any. */
|
||||
XmlNamespace getNamespace() { xmlHasNs_(this, result, _) }
|
||||
|
||||
/** Gets the value of this attribute. */
|
||||
string getValue() { xmlAttrs_(this, _, _, result, _, _) }
|
||||
|
||||
/** Gets a printable representation of this XML attribute. */
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
final class XmlAttribute = XmlAttributeImpl;
|
||||
|
||||
final private class XmlNamespaceBaseFinal = XmlNamespaceBase;
|
||||
|
||||
/**
|
||||
* A namespace used in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
* ```
|
||||
*/
|
||||
private class XmlNamespaceImpl extends XmlLocatableImpl, XmlNamespaceBaseFinal {
|
||||
/** Gets the prefix of this namespace. */
|
||||
string getPrefix() { xmlNs_(this, result, _, _) }
|
||||
|
||||
/** Gets the URI of this namespace. */
|
||||
string getUri() { xmlNs_(this, _, result, _) }
|
||||
|
||||
/** Holds if this namespace has no prefix. */
|
||||
predicate isDefault() { this.getPrefix() = "" }
|
||||
|
||||
override string toString() {
|
||||
this.isDefault() and result = this.getUri()
|
||||
or
|
||||
not this.isDefault() and result = this.getPrefix() + ":" + this.getUri()
|
||||
}
|
||||
}
|
||||
|
||||
final class XmlNamespace = XmlNamespaceImpl;
|
||||
|
||||
final private class XmlCommentBaseFinal = XmlCommentBase;
|
||||
|
||||
/**
|
||||
* A comment in an XML file.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <!-- This is a comment. -->
|
||||
* ```
|
||||
*/
|
||||
private class XmlCommentImpl extends XmlCommentBaseFinal, XmlLocatableImpl {
|
||||
/** Gets the text content of this XML comment. */
|
||||
string getText() { xmlComments_(this, result, _, _) }
|
||||
|
||||
/** Gets the parent of this XML comment. */
|
||||
XmlParent getParent() { xmlComments_(this, _, result, _) }
|
||||
|
||||
/** Gets a printable representation of this XML comment. */
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
final class XmlComment = XmlCommentImpl;
|
||||
|
||||
final private class XmlCharactersBaseFinal = XmlCharactersBase;
|
||||
|
||||
/**
|
||||
* A sequence of characters that occurs between opening and
|
||||
* closing tags of an XML element, excluding other elements.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* <content>This is a sequence of characters.</content>
|
||||
* ```
|
||||
*/
|
||||
private class XmlCharactersImpl extends XmlCharactersBaseFinal, XmlLocatableImpl {
|
||||
/** Gets the content of this character sequence. */
|
||||
string getCharacters() { xmlChars_(this, result, _, _, _, _) }
|
||||
|
||||
/** Gets the parent of this character sequence. */
|
||||
XmlParent getParent() { xmlChars_(this, _, result, _, _, _) }
|
||||
|
||||
/** Holds if this character sequence is CDATA. */
|
||||
predicate isCDATA() { xmlChars_(this, _, _, _, 1, _) }
|
||||
|
||||
/** Gets a printable representation of this XML character sequence. */
|
||||
override string toString() { result = this.getCharacters() }
|
||||
}
|
||||
|
||||
final class XmlCharacters = XmlCharactersImpl;
|
||||
}
|
||||
7
shared/xml/qlpack.yml
Normal file
7
shared/xml/qlpack.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
name: codeql/xml
|
||||
version: 0.0.1-dev
|
||||
groups: shared
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
Reference in New Issue
Block a user