Files
codeql/python/ql/src/external/Thrift.qll
2022-05-17 14:11:05 +02:00

208 lines
6.3 KiB
Plaintext

/**
* Provides classes for working with Apache Thrift IDL files.
* This code is under development and may change without warning.
*/
import external.ExternalArtifact
/** An item in the parse tree of the IDL file */
class ThriftElement extends ExternalData {
string kind;
ThriftElement() { this.getDataPath() = "thrift-" + kind }
string getKind() { result = kind }
string getId() { result = this.getField(0) }
int getIndex() { result = this.getFieldAsInt(1) }
ThriftElement getParent() { result.getId() = this.getField(2) }
string getValue() { result = this.getField(3) }
ThriftElement getChild(int n) { result.getIndex() = n and result.getParent() = this }
ThriftElement getAChild() { result = this.getChild(_) }
override string toString() { result = this.getKind() }
string getPath() { result = this.getField(4) }
private int line() { result = this.getFieldAsInt(5) }
private int column() { result = this.getFieldAsInt(6) }
/**
* 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
) {
filepath = this.getPath() and
startline = this.line() and
startcolumn = this.column() and
endline = this.line() and
endcolumn = this.column() + this.getValue().length() - 1
or
exists(ThriftElement first, ThriftElement last |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
last = this.getChild(max(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
last.hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
}
abstract class ThriftNamedElement extends ThriftElement {
abstract ThriftElement getNameElement();
final string getName() { result = this.getNameElement().getValue() }
override string toString() {
result = this.getKind() + " " + this.getName()
or
not exists(this.getName()) and result = this.getKind() + " ???"
}
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
exists(ThriftElement first |
first = this.getChild(min(int l | exists(this.getChild(l)))) and
first.hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getNameElement().hasLocationInfo(filepath, _, _, endline, endcolumn)
)
}
}
class ThriftType extends ThriftNamedElement {
ThriftType() { kind.matches("%type") }
override ThriftElement getNameElement() {
result = this.getChild(0)
or
result = this.getChild(0).(ThriftType).getNameElement()
}
override string toString() { result = "type " + this.getName() }
predicate references(ThriftStruct struct) {
this.getName() = struct.getName() and
exists(string path |
this.hasLocationInfo(path, _, _, _, _) and
struct.hasLocationInfo(path, _, _, _, _)
)
}
}
/** A thrift typedef */
class ThriftTypeDef extends ThriftNamedElement {
ThriftTypeDef() { kind = "typedef" }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
}
/** A thrift enum declaration */
class ThriftEnum extends ThriftNamedElement {
ThriftEnum() { kind = "enum" }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
}
/** A thrift enum field */
class ThriftEnumField extends ThriftNamedElement {
ThriftEnumField() { kind = "enumfield" }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
}
/** A thrift service declaration */
class ThriftService extends ThriftNamedElement {
ThriftService() { kind = "service" }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftFunction getAFunction() { result = this.getChild(_) }
ThriftFunction getFunction(string name) {
result.getName() = name and
result = this.getAFunction()
}
}
/** A thrift function declaration */
class ThriftFunction extends ThriftNamedElement {
ThriftFunction() { kind = "function" }
override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) }
ThriftField getArgument(int n) { result = this.getChild(n + 3) }
ThriftField getAnArgument() { result = this.getArgument(_) }
private ThriftThrows getAllThrows() { result = this.getChild(_) }
ThriftField getAThrows() { result = this.getAllThrows().getAChild() }
ThriftType getReturnType() { result = this.getChild(1).getChild(0) }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getChild(1).hasLocationInfo(filepath, startline, startcolumn, _, _) and
this.getChild(2).hasLocationInfo(filepath, _, _, endline, endcolumn)
}
ThriftService getService() { result.getAFunction() = this }
string getQualifiedName() { result = this.getService().getName() + "." + this.getName() }
}
class ThriftField extends ThriftNamedElement {
ThriftField() { kind = "field" }
override ThriftElement getNameElement() { result = this.getChild(4) }
ThriftType getType() { result = this.getChild(2) }
}
class ThriftStruct extends ThriftNamedElement {
ThriftStruct() { kind = "struct" }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getAMember() { result = this.getMember(_) }
}
class ThriftException extends ThriftNamedElement {
ThriftException() { kind = "exception" }
override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) }
ThriftField getMember(int n) { result = this.getChild(n + 1) }
ThriftField getAMember() { result = this.getMember(_) }
}
class ThriftThrows extends ThriftElement {
ThriftThrows() { kind = "throws" }
ThriftField getAThrows() { result = this.getChild(_) }
}
/** A parse tree element that holds a primitive value */
class ThriftValue extends ThriftElement {
ThriftValue() { exists(this.getValue()) }
override string toString() { result = this.getKind() + " " + this.getValue() }
}