mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
QL: Merge branch 'main' into tausbn/add-override-test
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: "CodeQL"
|
||||
name: "CodeQL with bleeding edge queries and extractor"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -12,6 +12,30 @@ on:
|
||||
|
||||
jobs:
|
||||
|
||||
build_query_pack:
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- name: Build query pack
|
||||
run: |
|
||||
cd ql/src
|
||||
"${CODEQL}" pack create
|
||||
cd .codeql/pack/codeql/ql-all/0.0.0
|
||||
zip "${PACKZIP}" -r .
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
PACKZIP: ${{ runner.temp }}/query-pack.zip
|
||||
- name: Upload query pack
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: query-pack
|
||||
path: ${{ runner.temp }}/query-pack.zip
|
||||
|
||||
# XXX this is mostly an inlined copy of the 'build' job in build.yml
|
||||
build_extractor_pack:
|
||||
strategy:
|
||||
@@ -79,9 +103,11 @@ jobs:
|
||||
|
||||
analyze:
|
||||
name: Analyze
|
||||
needs: build_extractor_pack
|
||||
needs:
|
||||
- build_query_pack
|
||||
- build_extractor_pack
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-latest-xl
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
@@ -89,61 +115,55 @@ jobs:
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Download pack
|
||||
- name: Download query pack
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: query-pack
|
||||
path: ${{ runner.temp }}/query-pack-artifact
|
||||
|
||||
- name: Download extractor pack
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: extractor-pack
|
||||
path: ${{ runner.temp }}/extractor-pack-artifact
|
||||
|
||||
- name: Unzip pack
|
||||
- name: Prepare packs
|
||||
id: prepare-packs
|
||||
run: |
|
||||
set -x
|
||||
mkdir "${PACKTMP}"
|
||||
cd "${PACKTMP}"
|
||||
unzip "${PACKARTIFACT}/*.zip" -d unzipped
|
||||
cp -r unzipped/ql "${PACK}"
|
||||
mkdir -p "${COMPLETE_PACK}" "${PACKS_TMP}"
|
||||
cd "${PACKS_TMP}"
|
||||
unzip "${QUERY_PACK_ARTIFACT}/*.zip" -d query-pack-artifact-unzipped
|
||||
cp -r query-pack-artifact-unzipped/. "${COMPLETE_PACK}"
|
||||
unzip "${EXTRACTOR_PACK_ARTIFACT}/*.zip" -d extractor-pack-artifact-unzipped
|
||||
cp -r extractor-pack-artifact-unzipped/ql/. "${COMPLETE_PACK}"
|
||||
cd "${COMPLETE_PACK}"
|
||||
zip "${COMPLETE_PACK_ZIP}" -r .
|
||||
env:
|
||||
PACKTMP: ${{ runner.temp }}/extractor-pack-artifact.tmp
|
||||
PACKARTIFACT: ${{ runner.temp }}/extractor-pack-artifact
|
||||
PACK: ${{ runner.temp }}/extractor-pack
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Make config file
|
||||
run: |
|
||||
set -x
|
||||
echo "name: CodeQL config for QL" >> "${CONFIG_FILE}"
|
||||
echo "" >> "${CONFIG_FILE}"
|
||||
echo "disable-default-queries: true" >> "${CONFIG_FILE}"
|
||||
echo "" >> "${CONFIG_FILE}"
|
||||
echo "queries: " >> "${CONFIG_FILE}"
|
||||
echo " - name: Standard queries" >> "${CONFIG_FILE}"
|
||||
echo " uses: ${SUITE}" >> "${CONFIG_FILE}"
|
||||
cat "${CONFIG_FILE}"
|
||||
env:
|
||||
SUITE: ./ql/src/codeql-suites/ql-code-scanning.qls
|
||||
CONFIG_FILE: ./.custom-codeql-actions-config.yml
|
||||
PACKS_TMP: ${{ runner.temp }}/pack-artifacts.tmp
|
||||
QUERY_PACK_ARTIFACT: ${{ runner.temp }}/query-pack-artifact
|
||||
EXTRACTOR_PACK_ARTIFACT: ${{ runner.temp }}/extractor-pack-artifact
|
||||
COMPLETE_PACK: ${{ runner.temp }}/pack
|
||||
COMPLETE_PACK_ZIP: ${{ runner.temp }}/pack.zip
|
||||
|
||||
- name: Hack codeql-action options
|
||||
run: |
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
JSON=$(jq -nc --arg pack "${COMPLETE_PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/extractor-pack
|
||||
COMPLETE_PACK: ${{ runner.temp }}/pack
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
config-file: ./.custom-codeql-actions-config.yml
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@esbena/ql
|
||||
with:
|
||||
results: ${{ runner.temp }}/results
|
||||
add-snippets: true
|
||||
|
||||
- name: Upload db
|
||||
uses: actions/upload-artifact@v2
|
||||
@@ -152,9 +172,9 @@ jobs:
|
||||
path: ${{ runner.temp }}/db
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload results
|
||||
- name: Upload complete pack
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: results
|
||||
path: ${{ runner.temp }}/results
|
||||
name: complete-pack
|
||||
path: ${{ runner.temp }}/pack.zip
|
||||
retention-days: 1
|
||||
53
.github/workflows/published-codeql-analysis.yml
vendored
Normal file
53
.github/workflows/published-codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: "CodeQL with published queries and extractor"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
|
||||
analyze:
|
||||
name: Analyze
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Download pack
|
||||
run: |
|
||||
# adjust this line to make the workflow work in other repositories
|
||||
# the ql-qlpack.zip file can be downloaded at:
|
||||
# - https://github.com/github/codeql-ql/releases
|
||||
# - https://github.com/github/codeql-ql/actions/workflows/bleeding-codeql-analysis.yml
|
||||
gh release download latest --pattern ql-qlpack.zip
|
||||
unzip ql-qlpack.zip -d "${PACK}"
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/ql-qlpack
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Hack codeql-action options
|
||||
run: |
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/ql-qlpack
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@esbena/ql
|
||||
1
ql/consistency-queries/BuildinsConsistency.ql
Normal file
1
ql/consistency-queries/BuildinsConsistency.ql
Normal file
@@ -0,0 +1 @@
|
||||
import codeql_ql.ast.internal.Builtins::BuildinsConsistency
|
||||
244
ql/src/codeql/GlobalValueNumbering.qll
Normal file
244
ql/src/codeql/GlobalValueNumbering.qll
Normal file
@@ -0,0 +1,244 @@
|
||||
private import ql
|
||||
private import codeql_ql.ast.internal.Predicate
|
||||
private import codeql_ql.ast.internal.Type
|
||||
private import codeql_ql.ast.internal.Builtins
|
||||
|
||||
private newtype TValueNumber =
|
||||
TVariableValueNumber(VarDecl var) { variableAccessValueNumber(_, var) } or
|
||||
TFieldValueNumber(VarDecl var) { fieldAccessValueNumber(_, var) } or
|
||||
TThisValueNumber(Predicate pred) { thisAccessValueNumber(_, pred) } or
|
||||
TPredicateValueNumber(PredicateOrBuiltin pred, ValueNumberArgumentList args) {
|
||||
predicateCallValueNumber(_, pred, args)
|
||||
} or
|
||||
TClassPredicateValueNumber(PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args) {
|
||||
classPredicateCallValueNumber(_, pred, base, args)
|
||||
} or
|
||||
TLiteralValueNumber(string value, Type t) { literalValueNumber(_, value, t) } or
|
||||
TBinaryOpValueNumber(FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand) {
|
||||
binaryOperandValueNumber(_, symbol, leftOperand, rightOperand)
|
||||
} or
|
||||
TUnaryOpValueNumber(FunctionSymbol symbol, ValueNumber operand) {
|
||||
unaryOperandValueNumber(_, symbol, operand)
|
||||
} or
|
||||
TInlineCastValueNumber(ValueNumber operand, Type t) { inlineCastValueNumber(_, operand, t) } or
|
||||
TDontCareValueNumber() or
|
||||
TRangeValueNumber(ValueNumber lower, ValueNumber high) { rangeValueNumber(_, lower, high) } or
|
||||
TSetValueNumber(ValueNumberElementList elements) { setValueNumber(_, elements) } or
|
||||
TUniqueValueNumber(Expr e) { uniqueValueNumber(e) }
|
||||
|
||||
private newtype ValueNumberArgumentList =
|
||||
MkArgsNil() or
|
||||
MkArgsCons(ValueNumber head, ValueNumberArgumentList tail) {
|
||||
argumentValueNumbers(_, _, head, tail)
|
||||
}
|
||||
|
||||
private newtype ValueNumberElementList =
|
||||
MkElementsNil() or
|
||||
MkElementsCons(ValueNumber head, ValueNumberElementList tail) {
|
||||
setValueNumbers(_, _, head, tail)
|
||||
}
|
||||
|
||||
private ValueNumberArgumentList argumentValueNumbers(Call call, int start) {
|
||||
start = call.getNumberOfArguments() and
|
||||
result = MkArgsNil()
|
||||
or
|
||||
exists(ValueNumber head, ValueNumberArgumentList tail |
|
||||
argumentValueNumbers(call, start, head, tail) and
|
||||
result = MkArgsCons(head, tail)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate argumentValueNumbers(
|
||||
Call call, int start, ValueNumber head, ValueNumberArgumentList tail
|
||||
) {
|
||||
head = valueNumber(call.getArgument(start)) and
|
||||
tail = argumentValueNumbers(call, start + 1)
|
||||
}
|
||||
|
||||
private ValueNumberElementList setValueNumbers(Set set, int start) {
|
||||
start = set.getNumberOfElements() and
|
||||
result = MkElementsNil()
|
||||
or
|
||||
exists(ValueNumber head, ValueNumberElementList tail |
|
||||
setValueNumbers(set, start, head, tail) and
|
||||
result = MkElementsCons(head, tail)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate setValueNumbers(Set set, int start, ValueNumber head, ValueNumberElementList tail) {
|
||||
head = valueNumber(set.getElement(start)) and
|
||||
tail = setValueNumbers(set, start + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* A value number. A value number represents a collection of expressions that compute to the same value
|
||||
* at runtime.
|
||||
*/
|
||||
class ValueNumber extends TValueNumber {
|
||||
string toString() { result = "GVN" }
|
||||
|
||||
/** Gets an expression that has this value number. */
|
||||
final Expr getAnExpr() { this = valueNumber(result) }
|
||||
}
|
||||
|
||||
private predicate uniqueValueNumber(Expr e) { not numberable(e) }
|
||||
|
||||
private predicate numberable(Expr e) {
|
||||
e instanceof VarAccess or
|
||||
e instanceof FieldAccess or
|
||||
e instanceof ThisAccess or
|
||||
e instanceof Call or
|
||||
e instanceof Literal or
|
||||
e instanceof BinOpExpr or
|
||||
e instanceof UnaryExpr or
|
||||
e instanceof InlineCast or
|
||||
e instanceof ExprAnnotation or
|
||||
e instanceof DontCare or
|
||||
e instanceof Range or
|
||||
e instanceof Set or
|
||||
e instanceof AsExpr
|
||||
}
|
||||
|
||||
private predicate variableAccessValueNumber(VarAccess access, VarDef var) {
|
||||
access.getDeclaration() = var
|
||||
}
|
||||
|
||||
private predicate fieldAccessValueNumber(FieldAccess access, VarDef var) {
|
||||
access.getDeclaration() = var
|
||||
}
|
||||
|
||||
private predicate thisAccessValueNumber(ThisAccess access, Predicate pred) {
|
||||
access.getEnclosingPredicate() = pred
|
||||
}
|
||||
|
||||
private predicate predicateCallValueNumber(
|
||||
Call call, PredicateOrBuiltin pred, ValueNumberArgumentList args
|
||||
) {
|
||||
call.getTarget() = pred and
|
||||
not exists(call.(MemberCall).getBase()) and
|
||||
args = argumentValueNumbers(call, 0)
|
||||
}
|
||||
|
||||
private predicate classPredicateCallValueNumber(
|
||||
MemberCall call, PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args
|
||||
) {
|
||||
call.getTarget() = pred and
|
||||
valueNumber(call.getBase()) = base and
|
||||
args = argumentValueNumbers(call, 0)
|
||||
}
|
||||
|
||||
private predicate literalValueNumber(Literal lit, string value, Type t) {
|
||||
lit.(String).getValue() = value and
|
||||
t instanceof StringClass
|
||||
or
|
||||
lit.(Integer).getValue().toString() = value and
|
||||
t instanceof IntClass
|
||||
or
|
||||
lit.(Float).getValue().toString() = value and
|
||||
t instanceof FloatClass
|
||||
or
|
||||
lit.(Boolean).isFalse() and
|
||||
value = "false" and
|
||||
t instanceof BooleanClass
|
||||
or
|
||||
lit.(Boolean).isTrue() and
|
||||
value = "true" and
|
||||
t instanceof BooleanClass
|
||||
}
|
||||
|
||||
private predicate binaryOperandValueNumber(
|
||||
BinOpExpr e, FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand
|
||||
) {
|
||||
e.getOperator() = symbol and
|
||||
valueNumber(e.getLeftOperand()) = leftOperand and
|
||||
valueNumber(e.getRightOperand()) = rightOperand
|
||||
}
|
||||
|
||||
private predicate unaryOperandValueNumber(UnaryExpr e, FunctionSymbol symbol, ValueNumber operand) {
|
||||
e.getOperator() = symbol and
|
||||
valueNumber(e.getOperand()) = operand
|
||||
}
|
||||
|
||||
private predicate inlineCastValueNumber(InlineCast cast, ValueNumber operand, Type t) {
|
||||
valueNumber(cast.getBase()) = operand and
|
||||
cast.getTypeExpr().getResolvedType() = t
|
||||
}
|
||||
|
||||
private predicate rangeValueNumber(Range range, ValueNumber lower, ValueNumber high) {
|
||||
valueNumber(range.getLowEndpoint()) = lower and
|
||||
valueNumber(range.getHighEndpoint()) = high
|
||||
}
|
||||
|
||||
private predicate setValueNumber(Set set, ValueNumberElementList elements) {
|
||||
elements = setValueNumbers(set, 0)
|
||||
}
|
||||
|
||||
private TValueNumber nonUniqueValueNumber(Expr e) {
|
||||
exists(VarDecl var |
|
||||
variableAccessValueNumber(e, var) and
|
||||
result = TVariableValueNumber(var)
|
||||
)
|
||||
or
|
||||
exists(VarDecl var |
|
||||
fieldAccessValueNumber(e, var) and
|
||||
result = TFieldValueNumber(var)
|
||||
)
|
||||
or
|
||||
exists(Predicate pred |
|
||||
thisAccessValueNumber(e, pred) and
|
||||
result = TThisValueNumber(pred)
|
||||
)
|
||||
or
|
||||
exists(PredicateOrBuiltin pred, ValueNumberArgumentList args |
|
||||
predicateCallValueNumber(e, pred, args) and
|
||||
result = TPredicateValueNumber(pred, args)
|
||||
)
|
||||
or
|
||||
exists(PredicateOrBuiltin pred, ValueNumber base, ValueNumberArgumentList args |
|
||||
classPredicateCallValueNumber(e, pred, base, args) and
|
||||
result = TClassPredicateValueNumber(pred, base, args)
|
||||
)
|
||||
or
|
||||
exists(string value, Type t |
|
||||
literalValueNumber(e, value, t) and
|
||||
result = TLiteralValueNumber(value, t)
|
||||
)
|
||||
or
|
||||
exists(FunctionSymbol symbol, ValueNumber leftOperand, ValueNumber rightOperand |
|
||||
binaryOperandValueNumber(e, symbol, leftOperand, rightOperand) and
|
||||
result = TBinaryOpValueNumber(symbol, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(FunctionSymbol symbol, ValueNumber operand |
|
||||
unaryOperandValueNumber(e, symbol, operand) and
|
||||
result = TUnaryOpValueNumber(symbol, operand)
|
||||
)
|
||||
or
|
||||
exists(ValueNumber operand, Type t |
|
||||
inlineCastValueNumber(e, operand, t) and
|
||||
result = TInlineCastValueNumber(operand, t)
|
||||
)
|
||||
or
|
||||
result = valueNumber([e.(ExprAnnotation).getExpression(), e.(AsExpr).getInnerExpr()])
|
||||
or
|
||||
e instanceof DontCare and result = TDontCareValueNumber()
|
||||
or
|
||||
exists(ValueNumber lower, ValueNumber high |
|
||||
rangeValueNumber(e, lower, high) and
|
||||
result = TRangeValueNumber(lower, high)
|
||||
)
|
||||
or
|
||||
exists(ValueNumberElementList elements |
|
||||
setValueNumber(e, elements) and
|
||||
result = TSetValueNumber(elements)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the value number of an expression `e`. */
|
||||
cached
|
||||
TValueNumber valueNumber(Expr e) {
|
||||
result = nonUniqueValueNumber(e)
|
||||
or
|
||||
uniqueValueNumber(e) and
|
||||
result = TUniqueValueNumber(e)
|
||||
}
|
||||
@@ -9,10 +9,10 @@ abstract class Container extends @container {
|
||||
Container getAChildContainer() { this = result.getParentContainer() }
|
||||
|
||||
/** Gets a file in this container. */
|
||||
File getAFile() { result = getAChildContainer() }
|
||||
File getAFile() { result = this.getAChildContainer() }
|
||||
|
||||
/** Gets a sub-folder in this container. */
|
||||
Folder getAFolder() { result = getAChildContainer() }
|
||||
Folder getAFolder() { result = this.getAChildContainer() }
|
||||
|
||||
/**
|
||||
* Gets the absolute, canonical path of this container, using forward slashes
|
||||
@@ -58,7 +58,7 @@ abstract class Container extends @container {
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,17 +84,19 @@ abstract class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) }
|
||||
string getExtension() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
|
||||
}
|
||||
|
||||
/** Gets the file in this container that has the given `baseName`, if any. */
|
||||
File getFile(string baseName) {
|
||||
result = getAFile() and
|
||||
result = this.getAFile() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
|
||||
Folder getFolder(string baseName) {
|
||||
result = getAFolder() and
|
||||
result = this.getAFolder() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
@@ -111,7 +113,7 @@ abstract class Container extends @container {
|
||||
*/
|
||||
string getRelativePath() {
|
||||
exists(string absPath, string pref |
|
||||
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
|
|
||||
absPath = pref and result = ""
|
||||
or
|
||||
@@ -137,7 +139,9 @@ abstract class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) }
|
||||
string getStem() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a URL representing the location of this container.
|
||||
@@ -151,7 +155,7 @@ abstract class Container extends @container {
|
||||
*
|
||||
* This is the absolute path of the container.
|
||||
*/
|
||||
string toString() { result = getAbsolutePath() }
|
||||
string toString() { result = this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** A folder. */
|
||||
@@ -159,7 +163,7 @@ class Folder extends Container, @folder {
|
||||
override string getAbsolutePath() { folders(this, result, _) }
|
||||
|
||||
/** Gets the URL of this folder. */
|
||||
override string getURL() { result = "folder://" + getAbsolutePath() }
|
||||
override string getURL() { result = "folder://" + this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** A file. */
|
||||
|
||||
@@ -4,6 +4,7 @@ private import codeql_ql.ast.internal.Module
|
||||
private import codeql_ql.ast.internal.Predicate
|
||||
import codeql_ql.ast.internal.Type
|
||||
private import codeql_ql.ast.internal.Variable
|
||||
private import codeql_ql.ast.internal.Builtins
|
||||
|
||||
bindingset[name]
|
||||
private string directMember(string name) { result = name + "()" }
|
||||
@@ -16,18 +17,9 @@ private string stringIndexedMember(string name, string index) {
|
||||
result = name + "(_)" and exists(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` has an annotation with `name`.
|
||||
*/
|
||||
private predicate hasAnnotation(AstNode node, string name) {
|
||||
exists(Generated::Annotation annotation | annotation.getName().getValue() = name |
|
||||
toGenerated(node).getParent() = annotation.getParent()
|
||||
)
|
||||
}
|
||||
|
||||
/** An AST node of a QL program */
|
||||
class AstNode extends TAstNode {
|
||||
string toString() { result = getAPrimaryQlClass() }
|
||||
string toString() { result = this.getAPrimaryQlClass() }
|
||||
|
||||
/**
|
||||
* Gets the location of the AST node.
|
||||
@@ -40,6 +32,20 @@ class AstNode extends TAstNode {
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
if exists(this.getLocation())
|
||||
then this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
else (
|
||||
filepath = "" and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parent in the AST for this node.
|
||||
*/
|
||||
@@ -60,6 +66,12 @@ class AstNode extends TAstNode {
|
||||
/** Gets the QLDoc comment for this AST node, if any. */
|
||||
QLDoc getQLDoc() { none() }
|
||||
|
||||
/** Holds if `node` has an annotation with `name`. */
|
||||
predicate hasAnnotation(string name) { this.getAnAnnotation().getName() = name }
|
||||
|
||||
/** Gets an annotation of this AST node. */
|
||||
Annotation getAnAnnotation() { toGenerated(this).getParent() = toGenerated(result).getParent() }
|
||||
|
||||
/**
|
||||
* Gets the predicate that contains this AST node.
|
||||
*/
|
||||
@@ -80,7 +92,7 @@ class TopLevel extends TTopLevel, AstNode {
|
||||
* Gets a member from contained in this top-level module.
|
||||
* Includes private members.
|
||||
*/
|
||||
ModuleMember getAMember() { result = getMember(_) }
|
||||
ModuleMember getAMember() { result = this.getMember(_) }
|
||||
|
||||
/** Gets the `i`'th member of this top-level module. */
|
||||
ModuleMember getMember(int i) {
|
||||
@@ -180,11 +192,62 @@ class Select extends TSelect, AstNode {
|
||||
override string getAPrimaryQlClass() { result = "Select" }
|
||||
}
|
||||
|
||||
class PredicateOrBuiltin extends TPredOrBuiltin, AstNode {
|
||||
string getName() { none() }
|
||||
|
||||
Type getDeclaringType() { none() }
|
||||
|
||||
Type getParameterType(int i) { none() }
|
||||
|
||||
Type getReturnType() { none() }
|
||||
|
||||
int getArity() { result = count(int i | exists(this.getParameterType(i))) }
|
||||
|
||||
predicate isPrivate() { none() }
|
||||
}
|
||||
|
||||
class BuiltinPredicate extends PredicateOrBuiltin, TBuiltin {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltinPredicate" }
|
||||
}
|
||||
|
||||
private class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
|
||||
string name;
|
||||
string ret;
|
||||
string args;
|
||||
|
||||
BuiltinClassless() { this = TBuiltinClassless(ret, name, args) }
|
||||
|
||||
override string getName() { result = name }
|
||||
|
||||
override PrimitiveType getReturnType() { result.getName() = ret }
|
||||
|
||||
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
||||
}
|
||||
|
||||
private class BuiltinMember extends BuiltinPredicate, TBuiltinMember {
|
||||
string name;
|
||||
string qual;
|
||||
string ret;
|
||||
string args;
|
||||
|
||||
BuiltinMember() { this = TBuiltinMember(qual, ret, name, args) }
|
||||
|
||||
override string getName() { result = name }
|
||||
|
||||
override PrimitiveType getReturnType() { result.getName() = ret }
|
||||
|
||||
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
||||
|
||||
override PrimitiveType getDeclaringType() { result.getName() = qual }
|
||||
}
|
||||
|
||||
/**
|
||||
* A QL predicate.
|
||||
* Either a classless predicate, a class predicate, or a characteristic predicate.
|
||||
*/
|
||||
class Predicate extends TPredicate, AstNode, Declaration {
|
||||
class Predicate extends TPredicate, AstNode, PredicateOrBuiltin, Declaration {
|
||||
/**
|
||||
* Gets the body of the predicate.
|
||||
*/
|
||||
@@ -203,21 +266,28 @@ class Predicate extends TPredicate, AstNode, Declaration {
|
||||
/**
|
||||
* Gets the number of parameters.
|
||||
*/
|
||||
int getArity() {
|
||||
override int getArity() {
|
||||
not this.(ClasslessPredicate).getAlias() instanceof PredicateExpr and
|
||||
result = count(getParameter(_))
|
||||
result = count(this.getParameter(_))
|
||||
or
|
||||
exists(PredicateExpr alias | alias = this.(ClasslessPredicate).getAlias() |
|
||||
result = alias.getArity()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this predicate is private.
|
||||
*/
|
||||
override predicate isPrivate() { this.hasAnnotation("private") }
|
||||
|
||||
/**
|
||||
* Gets the return type (if any) of the predicate.
|
||||
*/
|
||||
TypeExpr getReturnTypeExpr() { none() }
|
||||
|
||||
Type getReturnType() { result = this.getReturnTypeExpr().getResolvedType() }
|
||||
override Type getReturnType() { result = this.getReturnTypeExpr().getResolvedType() }
|
||||
|
||||
override Type getParameterType(int i) { result = this.getParameter(i).getType() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
@@ -255,18 +325,18 @@ class Relation extends TDBRelation, AstNode, Declaration {
|
||||
}
|
||||
|
||||
/** Gets the `i`th parameter name */
|
||||
string getParameterName(int i) { result = getColumn(i).getColName().getValue() }
|
||||
string getParameterName(int i) { result = this.getColumn(i).getColName().getValue() }
|
||||
|
||||
/** Gets the `i`th parameter type */
|
||||
string getParameterType(int i) {
|
||||
// TODO: This is just using the name of the type, not the actual type. Checkout Type.qll
|
||||
result = getColumn(i).getColType().getChild().(Generated::Token).getValue()
|
||||
result = this.getColumn(i).getColType().getChild().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of parameters.
|
||||
*/
|
||||
int getArity() { result = count(getColumn(_)) }
|
||||
int getArity() { result = count(this.getColumn(_)) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Relation" }
|
||||
}
|
||||
@@ -379,6 +449,8 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati
|
||||
or
|
||||
pred_name = directMember("getReturnTypeExpr") and result = this.getReturnTypeExpr()
|
||||
}
|
||||
|
||||
override predicate isPrivate() { Predicate.super.isPrivate() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,15 +469,10 @@ class ClassPredicate extends TClassPredicate, Predicate {
|
||||
|
||||
override Class getParent() { result.getAClassPredicate() = this }
|
||||
|
||||
/**
|
||||
* Holds if this predicate is private.
|
||||
*/
|
||||
predicate isPrivate() { hasAnnotation(this, "private") }
|
||||
|
||||
/**
|
||||
* Holds if this predicate is annotated as overriding another predicate.
|
||||
*/
|
||||
predicate isOverride() { hasAnnotation(this, "override") }
|
||||
predicate isOverride() { this.hasAnnotation("override") }
|
||||
|
||||
override VarDecl getParameter(int i) {
|
||||
toGenerated(result) =
|
||||
@@ -419,7 +486,7 @@ class ClassPredicate extends TClassPredicate, Predicate {
|
||||
/**
|
||||
* Gets the type representing this class.
|
||||
*/
|
||||
ClassType getDeclaringType() { result.getDeclaration() = getParent() }
|
||||
override ClassType getDeclaringType() { result.getDeclaration() = this.getParent() }
|
||||
|
||||
predicate overrides(ClassPredicate other) { predOverrides(this, other) }
|
||||
|
||||
@@ -448,7 +515,7 @@ class CharPred extends TCharPred, Predicate {
|
||||
|
||||
override Formula getBody() { toGenerated(result) = pred.getBody() }
|
||||
|
||||
override string getName() { result = getParent().(Class).getName() }
|
||||
override string getName() { result = this.getParent().(Class).getName() }
|
||||
|
||||
override AstNode getAChild(string pred_name) {
|
||||
result = super.getAChild(pred_name)
|
||||
@@ -456,7 +523,7 @@ class CharPred extends TCharPred, Predicate {
|
||||
pred_name = directMember("getBody") and result = this.getBody()
|
||||
}
|
||||
|
||||
ClassType getDeclaringType() { result.getDeclaration() = getParent() }
|
||||
override ClassType getDeclaringType() { result.getDeclaration() = this.getParent() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -618,7 +685,7 @@ class Module extends TModule, ModuleDeclaration {
|
||||
*/
|
||||
class ModuleMember extends TModuleMember, AstNode {
|
||||
/** Holds if this member is declared as `private`. */
|
||||
predicate isPrivate() { hasAnnotation(this, "private") }
|
||||
predicate isPrivate() { this.hasAnnotation("private") }
|
||||
}
|
||||
|
||||
/** A declaration. E.g. a class, type, predicate, newtype... */
|
||||
@@ -689,7 +756,7 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration {
|
||||
* Gets predicate `name` implemented in this class.
|
||||
*/
|
||||
ClassPredicate getClassPredicate(string name) {
|
||||
result = getAClassPredicate() and
|
||||
result = this.getAClassPredicate() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
@@ -767,7 +834,7 @@ class NewType extends TNewType, TypeDeclaration, ModuleDeclaration {
|
||||
* A branch in a `newtype`.
|
||||
* E.g. `Bar()` or `Baz()` in `newtype Foo = Bar() or Baz()`.
|
||||
*/
|
||||
class NewTypeBranch extends TNewTypeBranch, TypeDeclaration {
|
||||
class NewTypeBranch extends TNewTypeBranch, PredicateOrBuiltin, TypeDeclaration {
|
||||
Generated::DatatypeBranch branch;
|
||||
|
||||
NewTypeBranch() { this = TNewTypeBranch(branch) }
|
||||
@@ -789,6 +856,16 @@ class NewTypeBranch extends TNewTypeBranch, TypeDeclaration {
|
||||
/** Gets the body of this branch. */
|
||||
Formula getBody() { toGenerated(result) = branch.getChild(_).(Generated::Body).getChild() }
|
||||
|
||||
override NewTypeBranchType getReturnType() { result.getDeclaration() = this }
|
||||
|
||||
override Type getParameterType(int i) { result = this.getField(i).getType() }
|
||||
|
||||
override int getArity() { result = count(this.getField(_)) }
|
||||
|
||||
override Type getDeclaringType() { none() }
|
||||
|
||||
override predicate isPrivate() { this.getNewType().isPrivate() }
|
||||
|
||||
override QLDoc getQLDoc() { toGenerated(result) = branch.getChild(_) }
|
||||
|
||||
NewType getNewType() { result.getABranch() = this }
|
||||
@@ -816,6 +893,9 @@ class Call extends TCall, Expr, Formula {
|
||||
none() // overriden in sublcasses.
|
||||
}
|
||||
|
||||
/** Gets an argument of this call, if any. */
|
||||
final Expr getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
PredicateOrBuiltin getTarget() { resolveCall(this, result) }
|
||||
|
||||
override Type getType() { result = this.getTarget().getReturnType() }
|
||||
@@ -1191,7 +1271,7 @@ class ComparisonFormula extends TComparisonFormula, Formula {
|
||||
Expr getRightOperand() { toGenerated(result) = comp.getRight() }
|
||||
|
||||
/** Gets an operand of this comparison. */
|
||||
Expr getAnOperand() { result in [getLeftOperand(), getRightOperand()] }
|
||||
Expr getAnOperand() { result in [this.getLeftOperand(), this.getRightOperand()] }
|
||||
|
||||
/** Gets the operator of this comparison. */
|
||||
ComparisonOp getOperator() { toGenerated(result) = comp.getChild() }
|
||||
@@ -1249,7 +1329,7 @@ class Quantifier extends TQuantifier, Formula {
|
||||
* Holds if this is the "expression only" form of an exists quantifier.
|
||||
* In other words, the quantifier is of the form `exists( expr )`.
|
||||
*/
|
||||
predicate hasExpr() { exists(getExpr()) }
|
||||
predicate hasExpr() { exists(this.getExpr()) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Quantifier" }
|
||||
|
||||
@@ -1421,7 +1501,7 @@ class HigherOrderFormula extends THigherOrderFormula, Formula {
|
||||
* Gets the `i`th argument to this higher-order formula.
|
||||
* E.g. for `fastTC(pathSucc/2)(n1, n2)` the result is `n1` and `n2`.
|
||||
*/
|
||||
Expr getArgument(int i) { toGenerated(result) = hop.getChild(i + getNumInputs()) }
|
||||
Expr getArgument(int i) { toGenerated(result) = hop.getChild(i + this.getNumInputs()) }
|
||||
|
||||
/**
|
||||
* Gets the name of this higher-order predicate.
|
||||
@@ -1510,7 +1590,7 @@ class ExprAggregate extends TExprAggregate, Aggregate {
|
||||
)
|
||||
or
|
||||
not kind = ["count", "strictcount"] and
|
||||
result = getExpr(0).getType()
|
||||
result = this.getExpr(0).getType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1574,11 +1654,11 @@ class FullAggregate extends TFullAggregate, Aggregate {
|
||||
)
|
||||
or
|
||||
kind = ["any", "min", "max", "unique"] and
|
||||
not exists(getExpr(_)) and
|
||||
result = getArgument(0).getTypeExpr().getResolvedType()
|
||||
not exists(this.getExpr(_)) and
|
||||
result = this.getArgument(0).getTypeExpr().getResolvedType()
|
||||
or
|
||||
not kind = ["count", "strictcount"] and
|
||||
result = getExpr(0).getType()
|
||||
result = this.getExpr(0).getType()
|
||||
}
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
@@ -1791,7 +1871,19 @@ class FunctionSymbol extends string {
|
||||
/**
|
||||
* A binary operation expression, such as `x + 3` or `y / 2`.
|
||||
*/
|
||||
class BinOpExpr extends TBinOpExpr, Expr { }
|
||||
class BinOpExpr extends TBinOpExpr, Expr {
|
||||
/** Gets the left operand of the binary expression. */
|
||||
Expr getLeftOperand() { none() } // overriden in subclasses
|
||||
|
||||
/* Gets the right operand of the binary expression. */
|
||||
Expr getRightOperand() { none() } // overriden in subclasses
|
||||
|
||||
/** Gets the operator of the binary expression. */
|
||||
FunctionSymbol getOperator() { none() } // overriden in subclasses
|
||||
|
||||
/* Gets an operand of the binary expression. */
|
||||
final Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An addition or subtraction expression.
|
||||
@@ -1802,17 +1894,11 @@ class AddSubExpr extends TAddSubExpr, BinOpExpr {
|
||||
|
||||
AddSubExpr() { this = TAddSubExpr(expr) and operator = expr.getChild().getValue() }
|
||||
|
||||
/** Gets the left operand of the binary expression. */
|
||||
Expr getLeftOperand() { toGenerated(result) = expr.getLeft() }
|
||||
override Expr getLeftOperand() { toGenerated(result) = expr.getLeft() }
|
||||
|
||||
/* Gets the right operand of the binary expression. */
|
||||
Expr getRightOperand() { toGenerated(result) = expr.getRight() }
|
||||
override Expr getRightOperand() { toGenerated(result) = expr.getRight() }
|
||||
|
||||
/* Gets an operand of the binary expression. */
|
||||
Expr getAnOperand() { result = getLeftOperand() or result = getRightOperand() }
|
||||
|
||||
/** Gets the operator of the binary expression. */
|
||||
FunctionSymbol getOperator() { result = operator }
|
||||
override FunctionSymbol getOperator() { result = operator }
|
||||
|
||||
override PrimitiveType getType() {
|
||||
// Both operands are the same type
|
||||
@@ -1872,16 +1958,12 @@ class MulDivModExpr extends TMulDivModExpr, BinOpExpr {
|
||||
MulDivModExpr() { this = TMulDivModExpr(expr) and operator = expr.getChild().getValue() }
|
||||
|
||||
/** Gets the left operand of the binary expression. */
|
||||
Expr getLeftOperand() { toGenerated(result) = expr.getLeft() }
|
||||
override Expr getLeftOperand() { toGenerated(result) = expr.getLeft() }
|
||||
|
||||
/** Gets the right operand of the binary expression. */
|
||||
Expr getRightOperand() { toGenerated(result) = expr.getRight() }
|
||||
override Expr getRightOperand() { toGenerated(result) = expr.getRight() }
|
||||
|
||||
/** Gets an operand of the binary expression. */
|
||||
Expr getAnOperand() { result = getLeftOperand() or result = getRightOperand() }
|
||||
|
||||
/** Gets the operator of the binary expression. */
|
||||
FunctionSymbol getOperator() { result = operator }
|
||||
override FunctionSymbol getOperator() { result = operator }
|
||||
|
||||
override PrimitiveType getType() {
|
||||
// Both operands are of the same type
|
||||
@@ -1954,6 +2036,11 @@ class Range extends TRange, Expr {
|
||||
*/
|
||||
Expr getHighEndpoint() { toGenerated(result) = range.getUpper() }
|
||||
|
||||
/**
|
||||
* Gets the lower and upper bounds of the range.
|
||||
*/
|
||||
Expr getAnEndpoint() { result = [this.getLowEndpoint(), this.getHighEndpoint()] }
|
||||
|
||||
override PrimitiveType getType() { result.getName() = "int" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Range" }
|
||||
@@ -1980,6 +2067,16 @@ class Set extends TSet, Expr {
|
||||
*/
|
||||
Expr getElement(int i) { toGenerated(result) = set.getChild(i) }
|
||||
|
||||
/**
|
||||
* Gets an element in this set literal expression, if any.
|
||||
*/
|
||||
Expr getAnElement() { result = this.getElement(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of elements in this set literal expression.
|
||||
*/
|
||||
int getNumberOfElements() { result = count(this.getAnElement()) }
|
||||
|
||||
override Type getType() { result = this.getElement(0).getType() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Set" }
|
||||
@@ -1987,7 +2084,7 @@ class Set extends TSet, Expr {
|
||||
override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
or
|
||||
exists(int i | pred = indexedMember("getElement", i) and result = getElement(i))
|
||||
exists(int i | pred = indexedMember("getElement", i) and result = this.getElement(i))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2070,6 +2167,112 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
|
||||
}
|
||||
}
|
||||
|
||||
/** An argument to an annotation. */
|
||||
private class AnnotationArg extends TAnnotationArg, AstNode {
|
||||
Generated::AnnotArg arg;
|
||||
|
||||
AnnotationArg() { this = TAnnotationArg(arg) }
|
||||
|
||||
/** Gets the name of this argument. */
|
||||
string getValue() {
|
||||
result =
|
||||
[
|
||||
arg.getChild().(Generated::SimpleId).getValue(),
|
||||
arg.getChild().(Generated::Result).getValue(), arg.getChild().(Generated::This).getValue()
|
||||
]
|
||||
}
|
||||
|
||||
override string toString() { result = this.getValue() }
|
||||
}
|
||||
|
||||
private class NoInlineArg extends AnnotationArg {
|
||||
NoInlineArg() { this.getValue() = "noinline" }
|
||||
}
|
||||
|
||||
private class NoMagicArg extends AnnotationArg {
|
||||
NoMagicArg() { this.getValue() = "nomagic" }
|
||||
}
|
||||
|
||||
private class InlineArg extends AnnotationArg {
|
||||
InlineArg() { this.getValue() = "inline" }
|
||||
}
|
||||
|
||||
private class NoOptArg extends AnnotationArg {
|
||||
NoOptArg() { this.getValue() = "noopt" }
|
||||
}
|
||||
|
||||
private class MonotonicAggregatesArg extends AnnotationArg {
|
||||
MonotonicAggregatesArg() { this.getValue() = "monotonicAggregates" }
|
||||
}
|
||||
|
||||
/** An annotation on an element. */
|
||||
class Annotation extends TAnnotation, AstNode {
|
||||
Generated::Annotation annot;
|
||||
|
||||
Annotation() { this = TAnnotation(annot) }
|
||||
|
||||
override string toString() { result = "annotation" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Annotation" }
|
||||
|
||||
override Location getLocation() { result = annot.getLocation() }
|
||||
|
||||
/** Gets the node corresponding to the field `args`. */
|
||||
AnnotationArg getArgs(int i) { toGenerated(result) = annot.getArgs(i) }
|
||||
|
||||
/** Gets the node corresponding to the field `name`. */
|
||||
string getName() { result = annot.getName().getValue() }
|
||||
}
|
||||
|
||||
/** A `pragma[noinline]` annotation. */
|
||||
class NoInline extends Annotation {
|
||||
NoInline() { this.getArgs(0) instanceof NoInlineArg }
|
||||
|
||||
override string toString() { result = "noinline" }
|
||||
}
|
||||
|
||||
/** A `pragma[inline]` annotation. */
|
||||
class Inline extends Annotation {
|
||||
Inline() { this.getArgs(0) instanceof InlineArg }
|
||||
|
||||
override string toString() { result = "inline" }
|
||||
}
|
||||
|
||||
/** A `pragma[nomagic]` annotation. */
|
||||
class NoMagic extends Annotation {
|
||||
NoMagic() { this.getArgs(0) instanceof NoMagicArg }
|
||||
|
||||
override string toString() { result = "nomagic" }
|
||||
}
|
||||
|
||||
/** A `pragma[noopt]` annotation. */
|
||||
class NoOpt extends Annotation {
|
||||
NoOpt() { this.getArgs(0) instanceof NoOptArg }
|
||||
|
||||
override string toString() { result = "noopt" }
|
||||
}
|
||||
|
||||
/** A `language[monotonicAggregates]` annotation. */
|
||||
class MonotonicAggregates extends Annotation {
|
||||
MonotonicAggregates() { this.getArgs(0) instanceof MonotonicAggregatesArg }
|
||||
|
||||
override string toString() { result = "monotonicaggregates" }
|
||||
}
|
||||
|
||||
/** A `bindingset` annotation. */
|
||||
class BindingSet extends Annotation {
|
||||
BindingSet() { this.getName() = "bindingset" }
|
||||
|
||||
/** Gets the `index`'th bound name in this bindingset. */
|
||||
string getBoundName(int index) { result = this.getArgs(index).getValue() }
|
||||
|
||||
/** Gets a name bound by this bindingset, if any. */
|
||||
string getABoundName() { result = this.getBoundName(_) }
|
||||
|
||||
/** Gets the number of names bound by this bindingset. */
|
||||
int getNumberOfBoundNames() { result = count(this.getABoundName()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Classes modelling YAML AST nodes.
|
||||
*/
|
||||
@@ -2077,7 +2280,7 @@ module YAML {
|
||||
/** A node in a YAML file */
|
||||
class YAMLNode extends TYAMLNode, AstNode {
|
||||
/** Holds if the predicate is a root node (has no parent) */
|
||||
predicate isRoot() { not exists(getParent()) }
|
||||
predicate isRoot() { not exists(this.getParent()) }
|
||||
}
|
||||
|
||||
/** A YAML comment. */
|
||||
@@ -2146,7 +2349,7 @@ module YAML {
|
||||
* Dashes are replaced with `/` (because we don't have that information in the generated AST).
|
||||
*/
|
||||
string getQualifiedName() {
|
||||
result = concat(string part, int i | part = getNamePart(i) | part, "/" order by i)
|
||||
result = concat(string part, int i | part = this.getNamePart(i) | part, "/" order by i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2179,8 +2382,6 @@ module YAML {
|
||||
// to not expose the entire `File` API on `QlPack`.
|
||||
private newtype TQLPack = MKQlPack(File file) { file.getBaseName() = "qlpack.yml" }
|
||||
|
||||
YAMLEntry test() { not result.isRoot() }
|
||||
|
||||
/**
|
||||
* A `qlpack.yml` file.
|
||||
*/
|
||||
@@ -2199,15 +2400,15 @@ module YAML {
|
||||
}
|
||||
|
||||
/** Gets the name of this qlpack */
|
||||
string getName() { result = getProperty("name") }
|
||||
string getName() { result = this.getProperty("name") }
|
||||
|
||||
/** Gets the version of this qlpack */
|
||||
string getVersion() { result = getProperty("version") }
|
||||
string getVersion() { result = this.getProperty("version") }
|
||||
|
||||
/** Gets the extractor of this qlpack */
|
||||
string getExtractor() { result = getProperty("extractor") }
|
||||
string getExtractor() { result = this.getProperty("extractor") }
|
||||
|
||||
string toString() { result = getName() }
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the file that this `QLPack` represents. */
|
||||
File getFile() { result = file }
|
||||
@@ -2222,7 +2423,7 @@ module YAML {
|
||||
entry.getLocation().getStartColumn() > deps.getLocation().getStartColumn()
|
||||
)
|
||||
or
|
||||
exists(YAMLEntry prev | isADependency(prev) |
|
||||
exists(YAMLEntry prev | this.isADependency(prev) |
|
||||
prev.getLocation().getFile() = file and
|
||||
entry.getLocation().getFile() = file and
|
||||
entry.getLocation().getStartLine() = 1 + prev.getLocation().getStartLine() and
|
||||
@@ -2231,7 +2432,7 @@ module YAML {
|
||||
}
|
||||
|
||||
predicate hasDependency(string name, string version) {
|
||||
exists(YAMLEntry entry | isADependency(entry) |
|
||||
exists(YAMLEntry entry | this.isADependency(entry) |
|
||||
entry.getKey().getQualifiedName() = name and
|
||||
entry.getValue().getValue() = version
|
||||
)
|
||||
@@ -2239,7 +2440,7 @@ module YAML {
|
||||
|
||||
/** Gets the database scheme of this qlpack */
|
||||
File getDBScheme() {
|
||||
result.getBaseName() = getProperty("dbscheme") and
|
||||
result.getBaseName() = this.getProperty("dbscheme") and
|
||||
result = file.getParentContainer().getFile(any(string s | s.matches("%.dbscheme")))
|
||||
}
|
||||
|
||||
@@ -2247,14 +2448,16 @@ module YAML {
|
||||
Container getAFileInPack() {
|
||||
result.getParentContainer() = file.getParentContainer()
|
||||
or
|
||||
result = getAFileInPack().(Folder).getAChildContainer()
|
||||
result = this.getAFileInPack().(Folder).getAChildContainer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a QLPack that this QLPack depends on.
|
||||
*/
|
||||
QLPack getADependency() {
|
||||
exists(string name | hasDependency(name, _) | result.getName().replaceAll("-", "/") = name)
|
||||
exists(string name | this.hasDependency(name, _) |
|
||||
result.getName().replaceAll("-", "/") = name
|
||||
)
|
||||
}
|
||||
|
||||
Location getLocation() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import codeql_ql.ast.Ast as AST
|
||||
import TreeSitter
|
||||
private import Builtins
|
||||
|
||||
cached
|
||||
newtype TAstNode =
|
||||
@@ -59,11 +60,17 @@ newtype TAstNode =
|
||||
TDontCare(Generated::Underscore dontcare) or
|
||||
TModuleExpr(Generated::ModuleExpr me) or
|
||||
TPredicateExpr(Generated::PredicateExpr pe) or
|
||||
TAnnotation(Generated::Annotation annot) or
|
||||
TAnnotationArg(Generated::AnnotArg arg) or
|
||||
TYamlCommemt(Generated::YamlComment yc) or
|
||||
TYamlEntry(Generated::YamlEntry ye) or
|
||||
TYamlKey(Generated::YamlKey yk) or
|
||||
TYamlListitem(Generated::YamlListitem yli) or
|
||||
TYamlValue(Generated::YamlValue yv)
|
||||
TYamlValue(Generated::YamlValue yv) or
|
||||
TBuiltinClassless(string ret, string name, string args) { isBuiltinClassless(ret, name, args) } or
|
||||
TBuiltinMember(string qual, string ret, string name, string args) {
|
||||
isBuiltinMember(qual, ret, name, args)
|
||||
}
|
||||
|
||||
class TFormula =
|
||||
TDisjunction or TConjunction or TComparisonFormula or TQuantifier or TNegation or TIfFormula or
|
||||
@@ -184,10 +191,18 @@ Generated::AstNode toGenerated(AST::AstNode n) {
|
||||
n = TAnyCall(result)
|
||||
or
|
||||
n = TSuper(result)
|
||||
or
|
||||
n = TAnnotation(result)
|
||||
or
|
||||
n = TAnnotationArg(result)
|
||||
}
|
||||
|
||||
class TPredicate = TCharPred or TClasslessPredicate or TClassPredicate or TDBRelation;
|
||||
|
||||
class TPredOrBuiltin = TPredicate or TNewTypeBranch or TBuiltin;
|
||||
|
||||
class TBuiltin = TBuiltinClassless or TBuiltinMember;
|
||||
|
||||
class TModuleMember = TModuleDeclaration or TImport or TSelect or TQLDoc;
|
||||
|
||||
class TDeclaration = TTypeDeclaration or TModuleDeclaration or TPredicate or TVarDecl;
|
||||
|
||||
@@ -35,8 +35,8 @@ predicate isBuiltinMember(string sig) {
|
||||
"string int.toString()", "string string.charAt(int)", "int string.indexOf(string)",
|
||||
"int string.indexOf(string, int, int)", "predicate string.isLowercase()",
|
||||
"predicate string.isUppercase()", "int string.length()", "predicate string.matches(string)",
|
||||
"string string.prefix(int)", "string regexpCapture(string, int)",
|
||||
"string regexpFind(string, int, int)", "predicate string.regexpMatch(string)",
|
||||
"string string.prefix(int)", "string string.regexpCapture(string, int)",
|
||||
"string string.regexpFind(string, int, int)", "predicate string.regexpMatch(string)",
|
||||
"string string.regexpReplaceAll(string, string)", "string string.replaceAll(string, string)",
|
||||
"string string.splitAt(string)", "string string.splitAt(string, int)",
|
||||
"string string.substring(int, int)", "string string.suffix(int)", "date string.toDate()",
|
||||
@@ -58,6 +58,18 @@ predicate isBuiltinMember(string qual, string ret, string name, string args) {
|
||||
)
|
||||
}
|
||||
|
||||
module BuildinsConsistency {
|
||||
query predicate noBuildinParse(string sig) {
|
||||
isBuiltinMember(sig) and
|
||||
not exists(sig.regexpCapture("(\\w+) (\\w+)\\.(\\w+)\\(([\\w, ]*)\\)", _))
|
||||
}
|
||||
|
||||
query predicate noBuildinClasslessParse(string sig) {
|
||||
isBuiltinClassless(sig) and
|
||||
not exists(sig.regexpCapture("(\\w+) (\\w+)\\(([\\w, ]*)\\)", _))
|
||||
}
|
||||
}
|
||||
|
||||
bindingset[args]
|
||||
string getArgType(string args, int i) { result = args.splitAt(",", i).trim() }
|
||||
|
||||
@@ -65,3 +77,18 @@ string getArgType(string args, int i) { result = args.splitAt(",", i).trim() }
|
||||
class StringClass extends PrimitiveType {
|
||||
StringClass() { this.getName() = "string" }
|
||||
}
|
||||
|
||||
/** The primitive 'int' class. */
|
||||
class IntClass extends PrimitiveType {
|
||||
IntClass() { this.getName() = "int" }
|
||||
}
|
||||
|
||||
/** The primitive 'float' class. */
|
||||
class FloatClass extends PrimitiveType {
|
||||
FloatClass() { this.getName() = "float" }
|
||||
}
|
||||
|
||||
/** The primitive 'boolean' class. */
|
||||
class BooleanClass extends PrimitiveType {
|
||||
BooleanClass() { this.getName() = "boolean" }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import ql
|
||||
private import Builtins
|
||||
private import codeql_ql.ast.internal.Module
|
||||
private import codeql_ql.ast.internal.AstNodes as AstNodes
|
||||
private import codeql_ql.ast.internal.AstNodes
|
||||
|
||||
private class TClasslessPredicateOrNewTypeBranch =
|
||||
AstNodes::TClasslessPredicate or AstNodes::TNewTypeBranch;
|
||||
private class TClasslessPredicateOrNewTypeBranch = TClasslessPredicate or TNewTypeBranch;
|
||||
|
||||
string getPredicateName(TClasslessPredicateOrNewTypeBranch p) {
|
||||
private string getPredicateName(TClasslessPredicateOrNewTypeBranch p) {
|
||||
result = p.(ClasslessPredicate).getName() or
|
||||
result = p.(NewTypeBranch).getName()
|
||||
}
|
||||
@@ -69,8 +68,7 @@ private module Cached {
|
||||
m = pc.getQualifier().getResolvedModule() and
|
||||
public = true
|
||||
|
|
||||
definesPredicate(m, pc.getPredicateName(), pc.getNumberOfArguments(), p.getDeclaration(),
|
||||
public)
|
||||
definesPredicate(m, pc.getPredicateName(), pc.getNumberOfArguments(), p, public)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -93,8 +91,8 @@ private module Cached {
|
||||
rel.getName() = pc.getPredicateName()
|
||||
}
|
||||
|
||||
private predicate resolveDBRelation(PredicateCall pc, DefinedPredicate p) {
|
||||
exists(Relation rel | p = TPred(rel) |
|
||||
private predicate resolveDBRelation(PredicateCall pc, Predicate p) {
|
||||
exists(Relation rel | p = rel |
|
||||
candidate(rel, pc) and
|
||||
rel.getArity() = pc.getNumberOfArguments() and
|
||||
(
|
||||
@@ -120,142 +118,9 @@ private module Cached {
|
||||
not resolvePredicateCall(c, _) and
|
||||
resolveDBRelation(c, p)
|
||||
}
|
||||
|
||||
cached
|
||||
module NewTypeDef {
|
||||
cached
|
||||
newtype TPredOrBuiltin =
|
||||
TPred(Predicate p) or
|
||||
TNewTypeBranch(NewTypeBranch b) or
|
||||
TBuiltinClassless(string ret, string name, string args) {
|
||||
isBuiltinClassless(ret, name, args)
|
||||
} or
|
||||
TBuiltinMember(string qual, string ret, string name, string args) {
|
||||
isBuiltinMember(qual, ret, name, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
private import NewTypeDef
|
||||
|
||||
class PredicateOrBuiltin extends TPredOrBuiltin {
|
||||
string getName() { none() }
|
||||
|
||||
string toString() { result = getName() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
if exists(getDeclaration())
|
||||
then
|
||||
getDeclaration()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
else (
|
||||
filepath = "" and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
endline = 0 and
|
||||
endcolumn = 0
|
||||
)
|
||||
}
|
||||
|
||||
AstNode getDeclaration() { none() }
|
||||
|
||||
Type getDeclaringType() { none() }
|
||||
|
||||
Type getParameterType(int i) { none() }
|
||||
|
||||
Type getReturnType() { none() }
|
||||
|
||||
int getArity() { result = count(getParameterType(_)) }
|
||||
|
||||
predicate isPrivate() { none() }
|
||||
}
|
||||
|
||||
private class DefinedPredicate extends PredicateOrBuiltin, TPred {
|
||||
Predicate decl;
|
||||
|
||||
DefinedPredicate() { this = TPred(decl) }
|
||||
|
||||
override Predicate getDeclaration() { result = decl }
|
||||
|
||||
override string getName() { result = decl.getName() }
|
||||
|
||||
override Type getReturnType() { result = decl.getReturnType() }
|
||||
|
||||
override Type getParameterType(int i) { result = decl.getParameter(i).getType() }
|
||||
|
||||
// Can be removed when all types can be resolved
|
||||
override int getArity() { result = decl.getArity() }
|
||||
|
||||
override Type getDeclaringType() {
|
||||
result = decl.(ClassPredicate).getDeclaringType()
|
||||
or
|
||||
result = decl.(CharPred).getDeclaringType()
|
||||
}
|
||||
|
||||
override predicate isPrivate() {
|
||||
decl.(ClassPredicate).isPrivate() or decl.(ClassPredicate).isPrivate()
|
||||
}
|
||||
}
|
||||
|
||||
private class DefinedNewTypeBranch extends PredicateOrBuiltin, TNewTypeBranch {
|
||||
NewTypeBranch b;
|
||||
|
||||
DefinedNewTypeBranch() { this = TNewTypeBranch(b) }
|
||||
|
||||
override NewTypeBranch getDeclaration() { result = b }
|
||||
|
||||
override string getName() { result = b.getName() }
|
||||
|
||||
override NewTypeBranchType getReturnType() { result.getDeclaration() = b }
|
||||
|
||||
override Type getParameterType(int i) { result = b.getField(i).getType() }
|
||||
|
||||
// Can be removed when all types can be resolved
|
||||
override int getArity() { result = count(b.getField(_)) }
|
||||
|
||||
override Type getDeclaringType() { none() }
|
||||
|
||||
override predicate isPrivate() { b.getNewType().isPrivate() }
|
||||
}
|
||||
|
||||
private class TBuiltin = TBuiltinClassless or TBuiltinMember;
|
||||
|
||||
class BuiltinPredicate extends PredicateOrBuiltin, TBuiltin { }
|
||||
|
||||
private class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
|
||||
string name;
|
||||
string ret;
|
||||
string args;
|
||||
|
||||
BuiltinClassless() { this = TBuiltinClassless(ret, name, args) }
|
||||
|
||||
override string getName() { result = name }
|
||||
|
||||
override PrimitiveType getReturnType() { result.getName() = ret }
|
||||
|
||||
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
||||
}
|
||||
|
||||
private class BuiltinMember extends BuiltinPredicate, TBuiltinMember {
|
||||
string name;
|
||||
string qual;
|
||||
string ret;
|
||||
string args;
|
||||
|
||||
BuiltinMember() { this = TBuiltinMember(qual, ret, name, args) }
|
||||
|
||||
override string getName() { result = name }
|
||||
|
||||
override PrimitiveType getReturnType() { result.getName() = ret }
|
||||
|
||||
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
||||
|
||||
override PrimitiveType getDeclaringType() { result.getName() = qual }
|
||||
}
|
||||
|
||||
module PredConsistency {
|
||||
query predicate noResolvePredicateExpr(PredicateExpr pe) {
|
||||
@@ -287,9 +152,9 @@ module PredConsistency {
|
||||
strictcount(PredicateOrBuiltin p0 |
|
||||
resolveCall(call, p0) and
|
||||
// aliases are expected to resolve to multiple.
|
||||
not exists(p0.getDeclaration().(ClasslessPredicate).getAlias()) and
|
||||
not exists(p0.(ClasslessPredicate).getAlias())
|
||||
// overridden predicates may have multiple targets
|
||||
not p0.getDeclaration().(ClassPredicate).isOverride()
|
||||
not p0.(ClassPredicate).isOverride()
|
||||
) and
|
||||
c > 1 and
|
||||
resolveCall(call, p)
|
||||
|
||||
@@ -27,7 +27,7 @@ private predicate isActualClass(Class c) {
|
||||
* A type, such as `int` or `Node`.
|
||||
*/
|
||||
class Type extends TType {
|
||||
string toString() { result = getName() }
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
string getName() { result = "???" }
|
||||
|
||||
@@ -48,9 +48,9 @@ class Type extends TType {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
if exists(getDeclaration())
|
||||
if exists(this.getDeclaration())
|
||||
then
|
||||
getDeclaration()
|
||||
this.getDeclaration()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
else (
|
||||
@@ -72,14 +72,14 @@ class Type extends TType {
|
||||
private predicate getClassPredicate1(
|
||||
string name, int arity, PredicateOrBuiltin p1, PredicateOrBuiltin p2
|
||||
) {
|
||||
getClassPredicate0(name, arity, p1, p2.getDeclaringType()) and
|
||||
this.getClassPredicate0(name, arity, p1, p2.getDeclaringType()) and
|
||||
p2 = classPredCandidate(this, name, arity)
|
||||
}
|
||||
|
||||
cached
|
||||
PredicateOrBuiltin getClassPredicate(string name, int arity) {
|
||||
result = classPredCandidate(this, name, arity) and
|
||||
not getClassPredicate1(name, arity, _, result)
|
||||
not this.getClassPredicate1(name, arity, _, result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ private PredicateOrBuiltin declaredPred(Type ty, string name, int arity) {
|
||||
result.getArity() = arity
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PredicateOrBuiltin classPredCandidate(Type ty, string name, int arity) {
|
||||
result = declaredPred(ty, name, arity)
|
||||
or
|
||||
@@ -127,8 +128,7 @@ private PredicateOrBuiltin inherClassPredCandidate(Type ty, string name, int ari
|
||||
}
|
||||
|
||||
predicate predOverrides(ClassPredicate sub, ClassPredicate sup) {
|
||||
sup =
|
||||
inherClassPredCandidate(sub.getDeclaringType(), sub.getName(), sub.getArity()).getDeclaration()
|
||||
sup = inherClassPredCandidate(sub.getDeclaringType(), sub.getName(), sub.getArity())
|
||||
}
|
||||
|
||||
private VarDecl declaredField(ClassType ty, string name) {
|
||||
@@ -179,7 +179,7 @@ class ClassDomainType extends Type, TClassDomain {
|
||||
|
||||
ClassType getClassType() { result = TClass(decl) }
|
||||
|
||||
override Type getAnInternalSuperType() { result = getClassType().getASuperType() }
|
||||
override Type getAnInternalSuperType() { result = this.getClassType().getASuperType() }
|
||||
}
|
||||
|
||||
class PrimitiveType extends Type, TPrimitive {
|
||||
@@ -192,7 +192,7 @@ class PrimitiveType extends Type, TPrimitive {
|
||||
override Type getASuperType() { name = "int" and result.(PrimitiveType).getName() = "float" }
|
||||
|
||||
override Type getAnInternalSuperType() {
|
||||
result = getASuperType()
|
||||
result = this.getASuperType()
|
||||
or
|
||||
result = super.getAnInternalSuperType()
|
||||
}
|
||||
@@ -232,7 +232,7 @@ class NewTypeBranchType extends Type, TNewTypeBranch {
|
||||
}
|
||||
|
||||
override Type getAnInternalSuperType() {
|
||||
result = getASuperType()
|
||||
result = this.getASuperType()
|
||||
or
|
||||
result = super.getAnInternalSuperType()
|
||||
}
|
||||
@@ -283,6 +283,7 @@ private predicate qualifier(TypeExpr te, FileOrModule m, boolean public, string
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate defines(FileOrModule m, string name, Type t, boolean public) {
|
||||
exists(Class ty | t = TClass(ty) |
|
||||
getEnclosingModule(ty) = m and
|
||||
|
||||
@@ -54,7 +54,7 @@ private predicate resolveField(FieldAccess va, VarDecl decl, string kind) {
|
||||
}
|
||||
|
||||
private predicate resolveCall(Call c, Predicate p, string kind) {
|
||||
p = c.getTarget().getDeclaration() and
|
||||
p = c.getTarget() and
|
||||
kind = "call"
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ name: codeql-ql
|
||||
version: 0.0.0
|
||||
dbscheme: ql.dbscheme
|
||||
suites: codeql-suites
|
||||
defaultSuiteFile: codeql-suites/ql-code-scanning.qls
|
||||
extractor: ql
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @name Class predicate doesn't mention `this`
|
||||
* @description A class predicate that doesn't use `this` (or a field) could instead be a classless predicate, and may cause a cartesian product.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id ql/class-predicate-doesnt-use-this
|
||||
* @tags performance
|
||||
* @precision medium
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
predicate usesThis(ClassPredicate pred) {
|
||||
exists(ThisAccess th | th.getEnclosingPredicate() = pred)
|
||||
or
|
||||
exists(Super sup | sup.getEnclosingPredicate() = pred)
|
||||
or
|
||||
exists(FieldAccess f | f.getEnclosingPredicate() = pred)
|
||||
or
|
||||
// implicit this
|
||||
exists(PredicateCall pc | pc.getEnclosingPredicate() = pred |
|
||||
pc.getTarget() instanceof ClassPredicate
|
||||
)
|
||||
}
|
||||
|
||||
predicate isLiteralComparison(ComparisonFormula eq) {
|
||||
exists(Expr lhs, Expr rhs |
|
||||
eq.getSymbol() = "=" and
|
||||
eq.getAnOperand() = lhs and
|
||||
eq.getAnOperand() = rhs and
|
||||
(
|
||||
lhs instanceof ResultAccess
|
||||
or
|
||||
lhs instanceof ThisAccess
|
||||
or
|
||||
lhs instanceof VarAccess
|
||||
) and
|
||||
(
|
||||
rhs instanceof Literal
|
||||
or
|
||||
exists(NewTypeBranch nt |
|
||||
rhs.(Call).getTarget() = nt and
|
||||
count(nt.getField(_)) = 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate conjParent(Formula par, Formula child) { child = par.(Conjunction).getAnOperand() }
|
||||
|
||||
predicate isLiteralComparisons(Formula f) {
|
||||
forex(ComparisonFormula child | conjParent*(f, child) | isLiteralComparison(child))
|
||||
}
|
||||
|
||||
predicate isTrivialImplementation(Predicate pred) {
|
||||
not exists(pred.getBody())
|
||||
or
|
||||
exists(Formula bod | bod = pred.getBody() |
|
||||
bod instanceof AnyCall
|
||||
or
|
||||
bod instanceof NoneCall
|
||||
or
|
||||
isLiteralComparisons(bod)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSingleton(Type ty) {
|
||||
isTrivialImplementation(ty.(ClassType).getDeclaration().getCharPred())
|
||||
or
|
||||
isSingleton(ty.getASuperType())
|
||||
or
|
||||
exists(NewTypeBranch br | count(br.getField(_)) = 0 |
|
||||
ty.(NewTypeBranchType).getDeclaration() = br
|
||||
or
|
||||
br = unique(NewTypeBranch br2 | br2 = ty.(NewTypeType).getDeclaration().getABranch())
|
||||
)
|
||||
}
|
||||
|
||||
from ClassPredicate pred
|
||||
where
|
||||
not usesThis(pred) and
|
||||
not isTrivialImplementation(pred) and
|
||||
not isSingleton(pred.getDeclaringType()) and
|
||||
not exists(ClassPredicate other | pred.overrides(other) or other.overrides(pred)) and
|
||||
not pred.isOverride()
|
||||
select pred, "This predicate could be a classless predicate, as it doesn't depend on `this`."
|
||||
22
ql/src/queries/performance/DontUseGetAQlClass.ql
Normal file
22
ql/src/queries/performance/DontUseGetAQlClass.ql
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Don't use getAQlClass.
|
||||
* @description Any use of getAQlClass causes both compile-time and runtime to be significantly slower.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id ql/dont-use-getaqlclass
|
||||
* @tags performance
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from Call call
|
||||
where
|
||||
(
|
||||
call.(PredicateCall).getPredicateName() = "getAQlClass" or
|
||||
call.(MemberCall).getMemberName() = "getAQlClass"
|
||||
) and
|
||||
not call.getLocation().getFile().getAbsolutePath().matches("%/" + ["meta", "test"] + "/%") and
|
||||
not call.getLocation().getFile().getBaseName().toLowerCase() =
|
||||
["consistency.ql", "test.ql", "tst.ql", "tests.ql"]
|
||||
select call, "Don't use .getAQlClass"
|
||||
23
ql/src/queries/performance/MissingNoinline.ql
Normal file
23
ql/src/queries/performance/MissingNoinline.ql
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Missing `noinline` or `nomagic` annotation
|
||||
* @description When a predicate is factored out to improve join-ordering, it should be marked as `noinline` or `nomagic`.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id ql/missing-noinline
|
||||
* @tags performance
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from QLDoc doc, Predicate decl
|
||||
where
|
||||
doc.getContents().matches(["%join order%", "%join-order%"]) and
|
||||
decl.getQLDoc() = doc and
|
||||
not decl.getAnAnnotation() instanceof NoInline and
|
||||
not decl.getAnAnnotation() instanceof NoMagic and
|
||||
not decl.getAnAnnotation() instanceof NoOpt and
|
||||
// If it's marked as inline it's probably because the QLDoc says something like
|
||||
// "this predicate is inlined because it gives a better join-order".
|
||||
not decl.getAnAnnotation() instanceof Inline
|
||||
select decl, "This predicate might be inlined."
|
||||
30
ql/src/queries/performance/NonInitialStdLibImport.ql
Normal file
30
ql/src/queries/performance/NonInitialStdLibImport.ql
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @name Standard library is not the first import
|
||||
* @description Importing other libraries before the standard library can cause a change in
|
||||
* evaluation order and may lead to performance errors.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id ql/noninitial-stdlib-import
|
||||
* @tags performance
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
predicate isStdLibImport(Import i, string name) {
|
||||
name = i.getQualifiedName(0) and
|
||||
i.getLocation().getFile().getRelativePath().matches(name + "%") and
|
||||
not exists(i.getQualifiedName(1))
|
||||
}
|
||||
|
||||
Import importBefore(Import i) {
|
||||
exists(Module m, int bi, int ii |
|
||||
result = m.getMember(bi) and
|
||||
i = m.getMember(ii) and
|
||||
bi < ii
|
||||
)
|
||||
}
|
||||
|
||||
from Import i
|
||||
where isStdLibImport(i, _) and exists(importBefore(i))
|
||||
select i, "This import may cause reevaluation to occur, as there are other imports preceding it"
|
||||
165
ql/src/queries/performance/TransitiveStep.ql
Normal file
165
ql/src/queries/performance/TransitiveStep.ql
Normal file
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* @name Transitively closed recursive delta
|
||||
* @description Using a transitively closed relation as the step in a recursive
|
||||
* delta can perform poorly as it is inherently quadratic and may
|
||||
* force materialization of a fastTC. The transitively closed delta
|
||||
* can usually just be replaced by the underlying step relation as
|
||||
* the recursive context will provide transitive closure.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id ql/transitive-step
|
||||
* @tags performance
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
Expr getArg(Call c, int i) {
|
||||
result = c.getArgument(i)
|
||||
or
|
||||
result = c.(MemberCall).getBase() and i = -1
|
||||
or
|
||||
exists(c.getType()) and result = c and i = -2
|
||||
}
|
||||
|
||||
newtype TParameter =
|
||||
TThisParam(ClassPredicate p) or
|
||||
TResultParam(Predicate p) { exists(p.getReturnType()) } or
|
||||
TVarParam(VarDecl v) { any(Predicate p).getParameter(_) = v }
|
||||
|
||||
class Parameter extends TParameter {
|
||||
string toString() {
|
||||
this instanceof TThisParam and result = "this"
|
||||
or
|
||||
this instanceof TResultParam and result = "result"
|
||||
or
|
||||
exists(VarDecl v | this = TVarParam(v) and result = v.toString())
|
||||
}
|
||||
|
||||
Expr getAnAccess() {
|
||||
result instanceof ThisAccess and this = TThisParam(result.getEnclosingPredicate())
|
||||
or
|
||||
result instanceof ResultAccess and this = TResultParam(result.getEnclosingPredicate())
|
||||
or
|
||||
this = TVarParam(result.(VarAccess).getDeclaration())
|
||||
}
|
||||
|
||||
predicate isParameterOf(Predicate p, int i) {
|
||||
this = TThisParam(p) and i = -1
|
||||
or
|
||||
this = TResultParam(p) and i = -2
|
||||
or
|
||||
this = TVarParam(p.getParameter(i))
|
||||
}
|
||||
}
|
||||
|
||||
predicate hasTwoArgs(Call c, Expr arg1, Expr arg2) {
|
||||
exists(int i1, int i2 |
|
||||
arg1 = getArg(c, i1) and
|
||||
arg2 = getArg(c, i2) and
|
||||
i1 != i2 and
|
||||
strictcount(getArg(c, _)) = 2
|
||||
)
|
||||
}
|
||||
|
||||
predicate transitivePred(Predicate p, AstNode tc) {
|
||||
exists(PredicateExpr pe |
|
||||
p.(ClasslessPredicate).getAlias() = pe and
|
||||
transitivePred(pe.getResolvedPredicate(), tc)
|
||||
)
|
||||
or
|
||||
p.(ClasslessPredicate).getAlias().(HigherOrderFormula).getName() = "fastTC" and
|
||||
tc = p
|
||||
or
|
||||
strictcount(Parameter par | par.isParameterOf(p, _)) = 2 and
|
||||
exists(Formula body | p.getBody() = body |
|
||||
transitiveCall(body, tc) and
|
||||
hasTwoArgs(body, any(Identifier i1), any(Identifier i2))
|
||||
or
|
||||
exists(ComparisonFormula eq, Call c |
|
||||
body = eq and
|
||||
eq.getSymbol() = "=" and
|
||||
transitiveCall(c, tc) and
|
||||
getArg(c, _) instanceof Identifier and
|
||||
eq.getAnOperand() = c and
|
||||
eq.getAnOperand() instanceof Identifier
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate transitiveCall(Call c, AstNode tc) {
|
||||
c.isClosure(_) and tc = c
|
||||
or
|
||||
transitivePred(c.getTarget(), tc)
|
||||
}
|
||||
|
||||
class TransitivelyClosedCall extends Call {
|
||||
TransitivelyClosedCall() { transitiveCall(this, _) }
|
||||
|
||||
predicate hasArgs(Expr arg1, Expr arg2) { hasTwoArgs(this, arg1, arg2) }
|
||||
|
||||
AstNode getReason() { transitiveCall(this, result) }
|
||||
}
|
||||
|
||||
AstNode getParentOfExpr(Expr e) { result = e.getParent() }
|
||||
|
||||
Formula getEnclosing(Expr e) { result = getParentOfExpr+(e) }
|
||||
|
||||
Formula enlargeScopeStep(Formula f) { result.(Conjunction).getAnOperand() = f }
|
||||
|
||||
Formula enlargeScope(Formula f) {
|
||||
result = enlargeScopeStep*(f) and not exists(enlargeScopeStep(result))
|
||||
}
|
||||
|
||||
predicate varaccesValue(VarAccess va, VarDecl v, Formula scope) {
|
||||
va.getDeclaration() = v and
|
||||
scope = enlargeScope(getEnclosing(va))
|
||||
}
|
||||
|
||||
predicate thisValue(ThisAccess ta, Formula scope) { scope = enlargeScope(getEnclosing(ta)) }
|
||||
|
||||
predicate resultValue(ResultAccess ra, Formula scope) { scope = enlargeScope(getEnclosing(ra)) }
|
||||
|
||||
predicate valueStep(Expr e1, Expr e2) {
|
||||
exists(VarDecl v, Formula scope |
|
||||
varaccesValue(e1, v, scope) and
|
||||
varaccesValue(e2, v, scope)
|
||||
)
|
||||
or
|
||||
exists(Formula scope |
|
||||
thisValue(e1, scope) and
|
||||
thisValue(e2, scope)
|
||||
or
|
||||
resultValue(e1, scope) and
|
||||
resultValue(e2, scope)
|
||||
)
|
||||
or
|
||||
exists(InlineCast c |
|
||||
e1 = c and e2 = c.getBase()
|
||||
or
|
||||
e2 = c and e1 = c.getBase()
|
||||
)
|
||||
or
|
||||
exists(ComparisonFormula eq |
|
||||
eq.getSymbol() = "=" and
|
||||
eq.getAnOperand() = e1 and
|
||||
eq.getAnOperand() = e2 and
|
||||
e1 != e2
|
||||
)
|
||||
}
|
||||
|
||||
predicate transitiveDelta(Call rec, TransitivelyClosedCall tc) {
|
||||
exists(Expr recarg, int i, Expr tcarg, Predicate pred, Parameter p |
|
||||
rec.getTarget() = pred and
|
||||
pred = rec.getEnclosingPredicate() and
|
||||
recarg = getArg(rec, i) and
|
||||
valueStep*(recarg, tcarg) and
|
||||
tc.hasArgs(tcarg, p.getAnAccess()) and
|
||||
p.isParameterOf(pred, i)
|
||||
)
|
||||
}
|
||||
|
||||
from Call rec, TransitivelyClosedCall tc, AstNode reason
|
||||
where transitiveDelta(rec, tc) and reason = tc.getReason()
|
||||
select tc, "This recursive delta is transively closed $@, which may be a performance problem.",
|
||||
reason, "here"
|
||||
96
ql/src/queries/style/SuperfluousExists.ql
Normal file
96
ql/src/queries/style/SuperfluousExists.ql
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @name Superfluous 'exists' conjunct.
|
||||
* @description Writing 'exists(x)' when the existence of X is implied by another conjunct is bad practice.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id ql/superfluous-exists
|
||||
* @tags maintainability
|
||||
*/
|
||||
|
||||
import ql
|
||||
import codeql.GlobalValueNumbering
|
||||
|
||||
/**
|
||||
* Gets an operand of this conjunction (we need the restriction
|
||||
* to `Conjunction` to get the correct transitive closure).
|
||||
*/
|
||||
Formula getAConjOperand(Conjunction conj) { result = conj.getAnOperand() }
|
||||
|
||||
/** A conjunction that is not a operand of another conjunction. */
|
||||
class TopLevelConjunction extends Conjunction {
|
||||
TopLevelConjunction() { not this = getAConjOperand(_) }
|
||||
|
||||
/** Gets a formula within this conjunction that is not itself a conjunction. */
|
||||
Formula getAnAtom() {
|
||||
not result instanceof Conjunction and
|
||||
result = getAConjOperand*(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the existence of `e` implies the existence of `vn`. For instance, the existence of
|
||||
* `1 + x` implies the existence of a value number `vn` such that `vn.getAnExpr() = x`.
|
||||
*/
|
||||
predicate exprImpliesExists(ValueNumber vn, Expr e) {
|
||||
vn.getAnExpr() = e
|
||||
or
|
||||
exprImpliesExists(vn, e.(BinOpExpr).getAnOperand())
|
||||
or
|
||||
exprImpliesExists(vn, e.(InlineCast).getBase())
|
||||
or
|
||||
exprImpliesExists(vn, e.(PredicateCall).getAnArgument())
|
||||
or
|
||||
exprImpliesExists(vn, [e.(MemberCall).getAnArgument(), e.(MemberCall).getBase()])
|
||||
or
|
||||
exprImpliesExists(vn, e.(UnaryExpr).getOperand())
|
||||
or
|
||||
exprImpliesExists(vn, e.(ExprAnnotation).getExpression())
|
||||
or
|
||||
forex(Formula child | child = e.(Set).getAnElement() | exprImpliesExists(vn, child))
|
||||
or
|
||||
exprImpliesExists(vn, e.(AsExpr).getInnerExpr())
|
||||
or
|
||||
exists(ExprAggregate agg |
|
||||
agg = e and
|
||||
agg.getKind().matches(["strict%", "unique"]) and
|
||||
exprImpliesExists(vn, agg.getExpr(0))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the satisfiability of `f` implies the existence of `vn`. For instance, if `x.foo()` is
|
||||
* satisfied, the value number `vn` such that `vn.getAnExpr() = x` exists.
|
||||
*/
|
||||
predicate formulaImpliesExists(ValueNumber vn, Formula f) {
|
||||
forex(Formula child | child = f.(Disjunction).getAnOperand() | formulaImpliesExists(vn, child))
|
||||
or
|
||||
formulaImpliesExists(vn, f.(Conjunction).getAnOperand())
|
||||
or
|
||||
exprImpliesExists(vn, f.(ComparisonFormula).getAnOperand())
|
||||
or
|
||||
exists(IfFormula ifFormula |
|
||||
ifFormula = f and
|
||||
formulaImpliesExists(vn, ifFormula.getThenPart()) and
|
||||
formulaImpliesExists(vn, ifFormula.getElsePart())
|
||||
)
|
||||
or
|
||||
exprImpliesExists(vn, f.(InstanceOf).getExpr())
|
||||
or
|
||||
exprImpliesExists(vn, f.(PredicateCall).getAnArgument())
|
||||
or
|
||||
exprImpliesExists(vn, [f.(MemberCall).getAnArgument(), f.(MemberCall).getBase()])
|
||||
or
|
||||
exists(InFormula inFormula | inFormula = f |
|
||||
exprImpliesExists(vn, [inFormula.getExpr(), inFormula.getRange()])
|
||||
)
|
||||
}
|
||||
|
||||
from TopLevelConjunction toplevel, Exists existsFormula, ValueNumber vn, Formula conjunct
|
||||
where
|
||||
existsFormula = toplevel.getAnAtom() and
|
||||
vn.getAnExpr() = existsFormula.getExpr() and
|
||||
conjunct = toplevel.getAnAtom() and
|
||||
formulaImpliesExists(vn, conjunct)
|
||||
select existsFormula, "This conjunct is superfluous as the existence is implied by $@.", conjunct,
|
||||
"this conjunct"
|
||||
129
ql/src/queries/style/UseSetLiteral.ql
Normal file
129
ql/src/queries/style/UseSetLiteral.ql
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @name Use a set literal in place of `or`
|
||||
* @description A chain of `or`s can be replaced with a set literal, improving readability.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id ql/use-set-literal
|
||||
* @tags maintainability
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
/**
|
||||
* A chain of disjunctions treated as one object. For example the following is
|
||||
* a chain of disjunctions with three operands:
|
||||
* ```
|
||||
* a or b or c
|
||||
* ```
|
||||
*/
|
||||
class DisjunctionChain extends Disjunction {
|
||||
DisjunctionChain() { not exists(Disjunction parent | parent.getAnOperand() = this) }
|
||||
|
||||
/**
|
||||
* Gets any operand of the chain.
|
||||
*/
|
||||
Formula getAnOperandRec() {
|
||||
result = getAnOperand*() and
|
||||
not result instanceof Disjunction
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An equality comparison with a `Literal`. For example:
|
||||
* ```
|
||||
* x = 4
|
||||
* ```
|
||||
*/
|
||||
class EqualsLiteral extends ComparisonFormula {
|
||||
EqualsLiteral() {
|
||||
getSymbol() = "=" and
|
||||
getAnOperand() instanceof Literal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A chain of disjunctions where each operand is an equality comparison between
|
||||
* the same thing and various `Literal`s. For example:
|
||||
* ```
|
||||
* x = 4 or
|
||||
* x = 5 or
|
||||
* x = 6
|
||||
* ```
|
||||
*/
|
||||
class DisjunctionEqualsLiteral extends DisjunctionChain {
|
||||
DisjunctionEqualsLiteral() {
|
||||
// VarAccess on the same variable
|
||||
exists(VarDef v |
|
||||
forex(Formula f | f = getAnOperandRec() |
|
||||
f.(EqualsLiteral).getAnOperand().(VarAccess).getDeclaration() = v
|
||||
)
|
||||
)
|
||||
or
|
||||
// FieldAccess on the same variable
|
||||
exists(VarDecl v |
|
||||
forex(Formula f | f = getAnOperandRec() |
|
||||
f.(EqualsLiteral).getAnOperand().(FieldAccess).getDeclaration() = v
|
||||
)
|
||||
)
|
||||
or
|
||||
// ThisAccess
|
||||
forex(Formula f | f = getAnOperandRec() |
|
||||
f.(EqualsLiteral).getAnOperand() instanceof ThisAccess
|
||||
)
|
||||
or
|
||||
// ResultAccess
|
||||
forex(Formula f | f = getAnOperandRec() |
|
||||
f.(EqualsLiteral).getAnOperand() instanceof ResultAccess
|
||||
)
|
||||
// (in principle something like GlobalValueNumbering could be used to generalize this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call with a single `Literal` argument. For example:
|
||||
* ```
|
||||
* myPredicate(4)
|
||||
* ```
|
||||
*/
|
||||
class CallLiteral extends Call {
|
||||
CallLiteral() {
|
||||
getNumberOfArguments() = 1 and
|
||||
getArgument(0) instanceof Literal
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A chain of disjunctions where each operand is a call to the same predicate
|
||||
* using various `Literal`s. For example:
|
||||
* ```
|
||||
* myPredicate(4) or
|
||||
* myPredicate(5) or
|
||||
* myPredicate(6)
|
||||
* ```
|
||||
*/
|
||||
class DisjunctionPredicateLiteral extends DisjunctionChain {
|
||||
DisjunctionPredicateLiteral() {
|
||||
// Call to the same target
|
||||
exists(PredicateOrBuiltin target |
|
||||
forex(Formula f | f = getAnOperandRec() | f.(CallLiteral).getTarget() = target)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DisjunctionChain d, string msg, int c
|
||||
where
|
||||
(
|
||||
d instanceof DisjunctionEqualsLiteral and
|
||||
msg =
|
||||
"This formula of " + c.toString() +
|
||||
" comparisons can be replaced with a single equality on a set literal, improving readability."
|
||||
or
|
||||
d instanceof DisjunctionPredicateLiteral and
|
||||
msg =
|
||||
"This formula of " + c.toString() +
|
||||
" predicate calls can be replaced with a single call on a set literal, improving readability."
|
||||
) and
|
||||
c = count(d.getAnOperandRec()) and
|
||||
c >= 4
|
||||
select d, msg
|
||||
26
ql/src/queries/style/docs/ClassDocs.ql
Normal file
26
ql/src/queries/style/docs/ClassDocs.ql
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @name Class QLDoc style.
|
||||
* @description The QLDoc for a class should start with "A", "An", or "The".
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id ql/class-doc-style
|
||||
* @tags maintainability
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
bindingset[s]
|
||||
predicate badStyle(string s) {
|
||||
not s.replaceAll("/**", "")
|
||||
.replaceAll("*", "")
|
||||
.splitAt("\n")
|
||||
.trim()
|
||||
.matches(["A %", "An %", "The %", "INTERNAL%", "DEPRECATED%"])
|
||||
}
|
||||
|
||||
from Class c
|
||||
where
|
||||
badStyle(c.getQLDoc().getContents()) and
|
||||
not c.isPrivate()
|
||||
select c.getQLDoc(), "The QLDoc for a class should start with 'A', 'An', or 'The'."
|
||||
25
ql/src/queries/style/docs/MissingQLDoc.ql
Normal file
25
ql/src/queries/style/docs/MissingQLDoc.ql
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @name Missing QLDoc.
|
||||
* @description Library classes should have QLDoc.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @id ql/missing-qldoc
|
||||
* @tags maintainability
|
||||
* @precision high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
from File f, Class c
|
||||
where
|
||||
f = c.getLocation().getFile() and
|
||||
not exists(c.getQLDoc()) and // no QLDoc
|
||||
f.getExtension() = "qll" and // in a library
|
||||
not c.isPrivate() and // class is public
|
||||
not exists(Module m |
|
||||
m.getAMember*() = c and
|
||||
m.isPrivate() // modules containing the class are public
|
||||
) and
|
||||
not exists(c.getAliasType()) and // class is not just an alias
|
||||
not f.getParentContainer*().getBaseName().toLowerCase() = ["internal", "experimental", "test"] // exclusions
|
||||
select c, "This library class should have QLDoc."
|
||||
38
ql/src/queries/style/docs/NonUSSpelling.ql
Normal file
38
ql/src/queries/style/docs/NonUSSpelling.ql
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @name Non US spelling
|
||||
* @description QLDocs shold use US spelling.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @id ql/non-us-spelling
|
||||
* @tags maintainability
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import ql
|
||||
|
||||
predicate non_us_word(string wrong, string right) {
|
||||
exists(string s |
|
||||
wrong = s.splitAt("/", 0) and
|
||||
right = s.splitAt("/", 1) and
|
||||
s = ["colour/color", "authorise/authorize", "analyse/analyze"]
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
predicate contains_non_us_spelling(string s, string wrong, string right) {
|
||||
non_us_word(wrong, right) and
|
||||
(
|
||||
s.matches("%" + wrong + "%") and
|
||||
wrong != "analyse"
|
||||
or
|
||||
// analyses (as a noun) is fine
|
||||
s.regexpMatch(".*analyse[^s].*") and
|
||||
wrong = "analyse"
|
||||
)
|
||||
}
|
||||
|
||||
from QLDoc doc, string wrong, string right
|
||||
where contains_non_us_spelling(doc.getContents().toLowerCase(), wrong, right)
|
||||
select doc,
|
||||
"This QLDoc comment contains the non-US spelling '" + wrong + "', which should instead be '" +
|
||||
right + "'."
|
||||
@@ -31,3 +31,9 @@ module Aliases {
|
||||
alias0() // <- works
|
||||
}
|
||||
}
|
||||
|
||||
module Buildins {
|
||||
predicate replaceAll(string s) { "foo".replaceAll("foo", "bar") = s }
|
||||
|
||||
predicate regexpCapture(string s) { "foo".regexpCapture("\\w", 1) = s }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
getTarget
|
||||
| Foo.qll:5:26:5:30 | PredicateCall | Foo.qll:3:1:3:26 | ClasslessPredicate foo |
|
||||
| Foo.qll:10:21:10:25 | PredicateCall | Foo.qll:8:3:8:28 | ClassPredicate bar |
|
||||
| Foo.qll:14:30:14:40 | MemberCall | Foo.qll:10:3:10:27 | ClassPredicate baz |
|
||||
@@ -6,6 +7,8 @@
|
||||
| Foo.qll:29:5:29:16 | PredicateCall | Foo.qll:26:3:26:32 | ClasslessPredicate alias2 |
|
||||
| Foo.qll:31:5:31:12 | PredicateCall | Foo.qll:22:3:22:32 | ClasslessPredicate myThing0 |
|
||||
| Foo.qll:31:5:31:12 | PredicateCall | Foo.qll:24:3:24:32 | ClasslessPredicate alias0 |
|
||||
| Foo.qll:36:36:36:65 | MemberCall | file://:0:0:0:0 | replaceAll |
|
||||
| Foo.qll:38:39:38:67 | MemberCall | file://:0:0:0:0 | regexpCapture |
|
||||
| Overrides.qll:8:30:8:39 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar |
|
||||
| Overrides.qll:16:39:16:48 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar |
|
||||
| Overrides.qll:16:39:16:48 | MemberCall | Overrides.qll:14:12:14:43 | ClassPredicate bar |
|
||||
@@ -13,3 +16,7 @@
|
||||
| Overrides.qll:24:39:24:48 | MemberCall | Overrides.qll:22:12:22:44 | ClassPredicate bar |
|
||||
| Overrides.qll:28:3:28:9 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar |
|
||||
| Overrides.qll:29:3:29:10 | MemberCall | Overrides.qll:8:3:8:41 | ClassPredicate baz |
|
||||
| packs/src/SrcThing.qll:4:3:4:8 | PredicateCall | packs/lib/LibThing/Foo.qll:1:1:1:30 | ClasslessPredicate foo |
|
||||
| packs/src/SrcThing.qll:5:3:5:8 | PredicateCall | packs/src/SrcThing.qll:8:1:8:30 | ClasslessPredicate bar |
|
||||
dependsOn
|
||||
| packs/src/qlpack.yml:1:1:1:4 | ql-testing-src-pack | packs/lib/qlpack.yml:1:1:1:4 | ql-testing-lib-pack |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import ql
|
||||
|
||||
query AstNode getTarget(Call call) { result = call.getTarget().getDeclaration() }
|
||||
query AstNode getTarget(Call call) { result = call.getTarget() }
|
||||
|
||||
query YAML::QLPack dependsOn(YAML::QLPack pack) { result = pack.getADependency() }
|
||||
|
||||
1
ql/test/callgraph/packs/lib/LibThing/Foo.qll
Normal file
1
ql/test/callgraph/packs/lib/LibThing/Foo.qll
Normal file
@@ -0,0 +1 @@
|
||||
predicate foo(int i) { i = 3 }
|
||||
3
ql/test/callgraph/packs/lib/qlpack.yml
Normal file
3
ql/test/callgraph/packs/lib/qlpack.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
name: ql-testing-lib-pack
|
||||
version: 0.1.0
|
||||
extractor: ql-test-stuff
|
||||
8
ql/test/callgraph/packs/src/SrcThing.qll
Normal file
8
ql/test/callgraph/packs/src/SrcThing.qll
Normal file
@@ -0,0 +1,8 @@
|
||||
import LibThing.Foo
|
||||
|
||||
query predicate test(int i) {
|
||||
foo(i) and
|
||||
bar(i)
|
||||
}
|
||||
|
||||
predicate bar(int i) { i = 4 }
|
||||
4
ql/test/callgraph/packs/src/qlpack.yml
Normal file
4
ql/test/callgraph/packs/src/qlpack.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
name: ql-testing-src-pack
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
ql-testing-lib-pack: "*"
|
||||
@@ -29,159 +29,241 @@ nodes
|
||||
| Foo.qll:6:30:6:30 | ComparisonOp | semmle.order | 14 |
|
||||
| Foo.qll:6:32:6:36 | String | semmle.label | [String] String |
|
||||
| Foo.qll:6:32:6:36 | String | semmle.order | 15 |
|
||||
| Foo.qll:9:1:9:5 | annotation | semmle.label | [Annotation] annotation |
|
||||
| Foo.qll:9:1:9:5 | annotation | semmle.order | 16 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.label | [ClasslessPredicate] ClasslessPredicate foo |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.order | 16 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.order | 17 |
|
||||
| Foo.qll:9:21:9:23 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 17 |
|
||||
| Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 18 |
|
||||
| Foo.qll:9:21:9:25 | f | semmle.label | [VarDecl] f |
|
||||
| Foo.qll:9:21:9:25 | f | semmle.order | 17 |
|
||||
| Foo.qll:9:21:9:25 | f | semmle.order | 18 |
|
||||
| Foo.qll:10:3:10:3 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:10:3:10:3 | f | semmle.order | 19 |
|
||||
| Foo.qll:10:3:10:3 | f | semmle.order | 20 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 19 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 20 |
|
||||
| Foo.qll:10:5:10:5 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:10:5:10:5 | ComparisonOp | semmle.order | 21 |
|
||||
| Foo.qll:10:5:10:5 | ComparisonOp | semmle.order | 22 |
|
||||
| Foo.qll:10:7:10:85 | Rank | semmle.label | [Rank] Rank |
|
||||
| Foo.qll:10:7:10:85 | Rank | semmle.order | 22 |
|
||||
| Foo.qll:10:7:10:85 | Rank | semmle.order | 23 |
|
||||
| Foo.qll:10:12:10:12 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:10:12:10:12 | Integer | semmle.order | 23 |
|
||||
| Foo.qll:10:12:10:12 | Integer | semmle.order | 24 |
|
||||
| Foo.qll:10:15:10:17 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 24 |
|
||||
| Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 25 |
|
||||
| Foo.qll:10:15:10:23 | inner | semmle.label | [VarDecl] inner |
|
||||
| Foo.qll:10:15:10:23 | inner | semmle.order | 24 |
|
||||
| Foo.qll:10:15:10:23 | inner | semmle.order | 25 |
|
||||
| Foo.qll:10:27:10:31 | inner | semmle.label | [VarAccess] inner |
|
||||
| Foo.qll:10:27:10:31 | inner | semmle.order | 26 |
|
||||
| Foo.qll:10:27:10:31 | inner | semmle.order | 27 |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | semmle.label | [MemberCall] MemberCall |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | semmle.order | 26 |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | semmle.order | 27 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | semmle.order | 26 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | semmle.order | 27 |
|
||||
| Foo.qll:10:44:10:44 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:10:44:10:44 | ComparisonOp | semmle.order | 29 |
|
||||
| Foo.qll:10:44:10:44 | ComparisonOp | semmle.order | 30 |
|
||||
| Foo.qll:10:46:10:50 | String | semmle.label | [String] String |
|
||||
| Foo.qll:10:46:10:50 | String | semmle.order | 30 |
|
||||
| Foo.qll:10:46:10:50 | String | semmle.order | 31 |
|
||||
| Foo.qll:10:54:10:58 | inner | semmle.label | [VarAccess] inner |
|
||||
| Foo.qll:10:54:10:58 | inner | semmle.order | 31 |
|
||||
| Foo.qll:10:54:10:58 | inner | semmle.order | 32 |
|
||||
| Foo.qll:10:69:10:73 | inner | semmle.label | [VarAccess] inner |
|
||||
| Foo.qll:10:69:10:73 | inner | semmle.order | 32 |
|
||||
| Foo.qll:10:69:10:73 | inner | semmle.order | 33 |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | semmle.label | [MemberCall] MemberCall |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | semmle.order | 32 |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | semmle.order | 33 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.label | [ClasslessPredicate] ClasslessPredicate calls |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.order | 34 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.order | 35 |
|
||||
| Foo.qll:13:17:13:19 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 35 |
|
||||
| Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 36 |
|
||||
| Foo.qll:13:17:13:21 | f | semmle.label | [VarDecl] f |
|
||||
| Foo.qll:13:17:13:21 | f | semmle.order | 35 |
|
||||
| Foo.qll:13:17:13:21 | f | semmle.order | 36 |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | semmle.label | [PredicateCall] PredicateCall |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 37 |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 38 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | semmle.label | [Disjunction] Disjunction |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:9:14:9 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:14:9:14:9 | f | semmle.order | 44 |
|
||||
| Foo.qll:14:9:14:9 | f | semmle.order | 45 |
|
||||
| Foo.qll:16:3:16:7 | String | semmle.label | [String] String |
|
||||
| Foo.qll:16:3:16:7 | String | semmle.order | 45 |
|
||||
| Foo.qll:16:3:16:7 | String | semmle.order | 46 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | semmle.order | 45 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | semmle.order | 46 |
|
||||
| Foo.qll:16:9:16:9 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 47 |
|
||||
| Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 48 |
|
||||
| Foo.qll:16:11:16:11 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:16:11:16:11 | f | semmle.order | 48 |
|
||||
| Foo.qll:16:11:16:11 | f | semmle.order | 49 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | semmle.label | [MemberCall] MemberCall |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | semmle.order | 48 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | semmle.order | 49 |
|
||||
| Foo.qll:16:22:16:22 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:16:22:16:22 | Integer | semmle.order | 50 |
|
||||
| Foo.qll:16:22:16:22 | Integer | semmle.order | 51 |
|
||||
| Foo.qll:16:25:16:25 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:16:25:16:25 | Integer | semmle.order | 51 |
|
||||
| Foo.qll:16:25:16:25 | Integer | semmle.order | 52 |
|
||||
| Foo.qll:16:28:16:28 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:16:28:16:28 | Integer | semmle.order | 52 |
|
||||
| Foo.qll:16:28:16:28 | Integer | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:3 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:18:3:18:3 | f | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:3 | f | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | semmle.label | [InlineCast] InlineCast |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | semmle.label | [MemberCall] MemberCall |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | semmle.order | 54 |
|
||||
| Foo.qll:18:6:18:8 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:18:6:18:8 | TypeExpr | semmle.order | 57 |
|
||||
| Foo.qll:18:6:18:8 | TypeExpr | semmle.order | 58 |
|
||||
| Foo.qll:18:22:18:22 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 58 |
|
||||
| Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 59 |
|
||||
| Foo.qll:18:24:18:28 | String | semmle.label | [String] String |
|
||||
| Foo.qll:18:24:18:28 | String | semmle.order | 59 |
|
||||
| Foo.qll:18:24:18:28 | String | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:3 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:20:3:20:3 | f | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:3 | f | semmle.order | 61 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | semmle.label | [InlineCast] InlineCast |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | semmle.order | 61 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | semmle.order | 61 |
|
||||
| Foo.qll:20:6:20:8 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 63 |
|
||||
| Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 64 |
|
||||
| Foo.qll:20:11:20:11 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 64 |
|
||||
| Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 65 |
|
||||
| Foo.qll:20:13:20:13 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:20:13:20:13 | f | semmle.order | 65 |
|
||||
| Foo.qll:20:13:20:13 | f | semmle.order | 66 |
|
||||
| Foo.qll:22:3:22:3 | f | semmle.label | [VarAccess] f |
|
||||
| Foo.qll:22:3:22:3 | f | semmle.order | 66 |
|
||||
| Foo.qll:22:3:22:3 | f | semmle.order | 67 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 66 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 67 |
|
||||
| Foo.qll:22:5:22:5 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:22:5:22:5 | ComparisonOp | semmle.order | 68 |
|
||||
| Foo.qll:22:5:22:5 | ComparisonOp | semmle.order | 69 |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | [FullAggregate[any]] FullAggregate[any] |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 69 |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 70 |
|
||||
| Foo.qll:22:11:22:13 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
|
||||
| Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 70 |
|
||||
| Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 71 |
|
||||
| Foo.qll:22:11:22:15 | f | semmle.label | [VarDecl] f |
|
||||
| Foo.qll:22:11:22:15 | f | semmle.order | 70 |
|
||||
| Foo.qll:22:11:22:15 | f | semmle.order | 71 |
|
||||
| Foo.qll:24:3:24:3 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:24:3:24:3 | Integer | semmle.order | 72 |
|
||||
| Foo.qll:24:3:24:3 | Integer | semmle.order | 73 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | semmle.order | 72 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | semmle.order | 73 |
|
||||
| Foo.qll:24:5:24:5 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:24:5:24:5 | ComparisonOp | semmle.order | 74 |
|
||||
| Foo.qll:24:5:24:5 | ComparisonOp | semmle.order | 75 |
|
||||
| Foo.qll:24:7:24:7 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:24:7:24:7 | Integer | semmle.order | 75 |
|
||||
| Foo.qll:24:7:24:7 | Integer | semmle.order | 76 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | semmle.label | [AddExpr] AddExpr |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | semmle.order | 75 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | semmle.order | 76 |
|
||||
| Foo.qll:24:12:24:12 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:24:12:24:12 | Integer | semmle.order | 77 |
|
||||
| Foo.qll:24:12:24:12 | Integer | semmle.order | 78 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | semmle.label | [AddExpr] AddExpr |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | semmle.order | 77 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | semmle.order | 78 |
|
||||
| Foo.qll:24:17:24:17 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:24:17:24:17 | Integer | semmle.order | 79 |
|
||||
| Foo.qll:24:17:24:17 | Integer | semmle.order | 80 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | semmle.label | [AddExpr] AddExpr |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | semmle.order | 79 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | semmle.order | 80 |
|
||||
| Foo.qll:24:21:24:21 | Integer | semmle.label | [Integer] Integer |
|
||||
| Foo.qll:24:21:24:21 | Integer | semmle.order | 81 |
|
||||
| Foo.qll:24:21:24:21 | Integer | semmle.order | 82 |
|
||||
| Foo.qll:26:3:26:6 | Boolean | semmle.label | [Boolean] Boolean |
|
||||
| Foo.qll:26:3:26:6 | Boolean | semmle.order | 82 |
|
||||
| Foo.qll:26:3:26:6 | Boolean | semmle.order | 83 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | semmle.order | 82 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | semmle.order | 83 |
|
||||
| Foo.qll:26:8:26:8 | ComparisonOp | semmle.label | [ComparisonOp] ComparisonOp |
|
||||
| Foo.qll:26:8:26:8 | ComparisonOp | semmle.order | 84 |
|
||||
| Foo.qll:26:8:26:8 | ComparisonOp | semmle.order | 85 |
|
||||
| Foo.qll:26:10:26:14 | Boolean | semmle.label | [Boolean] Boolean |
|
||||
| Foo.qll:26:10:26:14 | Boolean | semmle.order | 85 |
|
||||
| Foo.qll:26:10:26:14 | Boolean | semmle.order | 86 |
|
||||
| file://:0:0:0:0 | abs | semmle.label | [BuiltinPredicate] abs |
|
||||
| file://:0:0:0:0 | abs | semmle.label | [BuiltinPredicate] abs |
|
||||
| file://:0:0:0:0 | acos | semmle.label | [BuiltinPredicate] acos |
|
||||
| file://:0:0:0:0 | any | semmle.label | [BuiltinPredicate] any |
|
||||
| file://:0:0:0:0 | atan | semmle.label | [BuiltinPredicate] atan |
|
||||
| file://:0:0:0:0 | bitAnd | semmle.label | [BuiltinPredicate] bitAnd |
|
||||
| file://:0:0:0:0 | bitNot | semmle.label | [BuiltinPredicate] bitNot |
|
||||
| file://:0:0:0:0 | bitOr | semmle.label | [BuiltinPredicate] bitOr |
|
||||
| file://:0:0:0:0 | bitShiftLeft | semmle.label | [BuiltinPredicate] bitShiftLeft |
|
||||
| file://:0:0:0:0 | bitShiftRight | semmle.label | [BuiltinPredicate] bitShiftRight |
|
||||
| file://:0:0:0:0 | bitShiftRightSigned | semmle.label | [BuiltinPredicate] bitShiftRightSigned |
|
||||
| file://:0:0:0:0 | bitXor | semmle.label | [BuiltinPredicate] bitXor |
|
||||
| file://:0:0:0:0 | booleanAnd | semmle.label | [BuiltinPredicate] booleanAnd |
|
||||
| file://:0:0:0:0 | booleanNot | semmle.label | [BuiltinPredicate] booleanNot |
|
||||
| file://:0:0:0:0 | booleanOr | semmle.label | [BuiltinPredicate] booleanOr |
|
||||
| file://:0:0:0:0 | booleanXor | semmle.label | [BuiltinPredicate] booleanXor |
|
||||
| file://:0:0:0:0 | ceil | semmle.label | [BuiltinPredicate] ceil |
|
||||
| file://:0:0:0:0 | charAt | semmle.label | [BuiltinPredicate] charAt |
|
||||
| file://:0:0:0:0 | copySign | semmle.label | [BuiltinPredicate] copySign |
|
||||
| file://:0:0:0:0 | cos | semmle.label | [BuiltinPredicate] cos |
|
||||
| file://:0:0:0:0 | cosh | semmle.label | [BuiltinPredicate] cosh |
|
||||
| file://:0:0:0:0 | daysTo | semmle.label | [BuiltinPredicate] daysTo |
|
||||
| file://:0:0:0:0 | exp | semmle.label | [BuiltinPredicate] exp |
|
||||
| file://:0:0:0:0 | floor | semmle.label | [BuiltinPredicate] floor |
|
||||
| file://:0:0:0:0 | gcd | semmle.label | [BuiltinPredicate] gcd |
|
||||
| file://:0:0:0:0 | getDay | semmle.label | [BuiltinPredicate] getDay |
|
||||
| file://:0:0:0:0 | getHours | semmle.label | [BuiltinPredicate] getHours |
|
||||
| file://:0:0:0:0 | getMinutes | semmle.label | [BuiltinPredicate] getMinutes |
|
||||
| file://:0:0:0:0 | getMonth | semmle.label | [BuiltinPredicate] getMonth |
|
||||
| file://:0:0:0:0 | getSeconds | semmle.label | [BuiltinPredicate] getSeconds |
|
||||
| file://:0:0:0:0 | getYear | semmle.label | [BuiltinPredicate] getYear |
|
||||
| file://:0:0:0:0 | indexOf | semmle.label | [BuiltinPredicate] indexOf |
|
||||
| file://:0:0:0:0 | indexOf | semmle.label | [BuiltinPredicate] indexOf |
|
||||
| file://:0:0:0:0 | isLowercase | semmle.label | [BuiltinPredicate] isLowercase |
|
||||
| file://:0:0:0:0 | isUppercase | semmle.label | [BuiltinPredicate] isUppercase |
|
||||
| file://:0:0:0:0 | length | semmle.label | [BuiltinPredicate] length |
|
||||
| file://:0:0:0:0 | log | semmle.label | [BuiltinPredicate] log |
|
||||
| file://:0:0:0:0 | log | semmle.label | [BuiltinPredicate] log |
|
||||
| file://:0:0:0:0 | log2 | semmle.label | [BuiltinPredicate] log2 |
|
||||
| file://:0:0:0:0 | log10 | semmle.label | [BuiltinPredicate] log10 |
|
||||
| file://:0:0:0:0 | matches | semmle.label | [BuiltinPredicate] matches |
|
||||
| file://:0:0:0:0 | maximum | semmle.label | [BuiltinPredicate] maximum |
|
||||
| file://:0:0:0:0 | minimum | semmle.label | [BuiltinPredicate] minimum |
|
||||
| file://:0:0:0:0 | nextAfter | semmle.label | [BuiltinPredicate] nextAfter |
|
||||
| file://:0:0:0:0 | nextDown | semmle.label | [BuiltinPredicate] nextDown |
|
||||
| file://:0:0:0:0 | nextUp | semmle.label | [BuiltinPredicate] nextUp |
|
||||
| file://:0:0:0:0 | none | semmle.label | [BuiltinPredicate] none |
|
||||
| file://:0:0:0:0 | pow | semmle.label | [BuiltinPredicate] pow |
|
||||
| file://:0:0:0:0 | prefix | semmle.label | [BuiltinPredicate] prefix |
|
||||
| file://:0:0:0:0 | regexpCapture | semmle.label | [BuiltinPredicate] regexpCapture |
|
||||
| file://:0:0:0:0 | regexpFind | semmle.label | [BuiltinPredicate] regexpFind |
|
||||
| file://:0:0:0:0 | regexpMatch | semmle.label | [BuiltinPredicate] regexpMatch |
|
||||
| file://:0:0:0:0 | regexpReplaceAll | semmle.label | [BuiltinPredicate] regexpReplaceAll |
|
||||
| file://:0:0:0:0 | replaceAll | semmle.label | [BuiltinPredicate] replaceAll |
|
||||
| file://:0:0:0:0 | signum | semmle.label | [BuiltinPredicate] signum |
|
||||
| file://:0:0:0:0 | sin | semmle.label | [BuiltinPredicate] sin |
|
||||
| file://:0:0:0:0 | sinh | semmle.label | [BuiltinPredicate] sinh |
|
||||
| file://:0:0:0:0 | splitAt | semmle.label | [BuiltinPredicate] splitAt |
|
||||
| file://:0:0:0:0 | splitAt | semmle.label | [BuiltinPredicate] splitAt |
|
||||
| file://:0:0:0:0 | sqrt | semmle.label | [BuiltinPredicate] sqrt |
|
||||
| file://:0:0:0:0 | substring | semmle.label | [BuiltinPredicate] substring |
|
||||
| file://:0:0:0:0 | suffix | semmle.label | [BuiltinPredicate] suffix |
|
||||
| file://:0:0:0:0 | tan | semmle.label | [BuiltinPredicate] tan |
|
||||
| file://:0:0:0:0 | tanh | semmle.label | [BuiltinPredicate] tanh |
|
||||
| file://:0:0:0:0 | toDate | semmle.label | [BuiltinPredicate] toDate |
|
||||
| file://:0:0:0:0 | toFloat | semmle.label | [BuiltinPredicate] toFloat |
|
||||
| file://:0:0:0:0 | toISO | semmle.label | [BuiltinPredicate] toISO |
|
||||
| file://:0:0:0:0 | toInt | semmle.label | [BuiltinPredicate] toInt |
|
||||
| file://:0:0:0:0 | toLowerCase | semmle.label | [BuiltinPredicate] toLowerCase |
|
||||
| file://:0:0:0:0 | toString | semmle.label | [BuiltinPredicate] toString |
|
||||
| file://:0:0:0:0 | toString | semmle.label | [BuiltinPredicate] toString |
|
||||
| file://:0:0:0:0 | toString | semmle.label | [BuiltinPredicate] toString |
|
||||
| file://:0:0:0:0 | toString | semmle.label | [BuiltinPredicate] toString |
|
||||
| file://:0:0:0:0 | toString | semmle.label | [BuiltinPredicate] toString |
|
||||
| file://:0:0:0:0 | toUnicode | semmle.label | [BuiltinPredicate] toUnicode |
|
||||
| file://:0:0:0:0 | toUpperCase | semmle.label | [BuiltinPredicate] toUpperCase |
|
||||
| file://:0:0:0:0 | toUrl | semmle.label | [BuiltinPredicate] toUrl |
|
||||
| file://:0:0:0:0 | toUrl | semmle.label | [BuiltinPredicate] toUrl |
|
||||
| file://:0:0:0:0 | trim | semmle.label | [BuiltinPredicate] trim |
|
||||
| file://:0:0:0:0 | ulp | semmle.label | [BuiltinPredicate] ulp |
|
||||
| printAst.ql:1:1:1:28 | Import | semmle.label | [Import] Import |
|
||||
| printAst.ql:1:1:1:28 | Import | semmle.order | 86 |
|
||||
| printAst.ql:1:1:1:28 | Import | semmle.order | 87 |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | semmle.label | [TopLevel] TopLevel |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | semmle.order | 86 |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | semmle.order | 87 |
|
||||
edges
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:1:1:1:17 | Import | semmle.label | getAnImport() |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:1:1:1:17 | Import | semmle.order | 1 |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:3:1:7:1 | Class Foo | semmle.label | getAClass() |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:3:1:7:1 | Class Foo | semmle.order | 3 |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.label | getAPredicate() |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.order | 16 |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:9:7:11:1 | ClasslessPredicate foo | semmle.order | 17 |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.label | getAPredicate() |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.order | 34 |
|
||||
| Foo.qll:1:1:27:2 | TopLevel | Foo.qll:13:1:27:1 | ClasslessPredicate calls | semmle.order | 35 |
|
||||
| Foo.qll:3:1:7:1 | Class Foo | Foo.qll:3:19:3:22 | TypeExpr | semmle.label | getASuperType() |
|
||||
| Foo.qll:3:1:7:1 | Class Foo | Foo.qll:3:19:3:22 | TypeExpr | semmle.order | 4 |
|
||||
| Foo.qll:3:1:7:1 | Class Foo | Foo.qll:4:3:4:17 | CharPred Foo | semmle.label | getCharPred() |
|
||||
@@ -207,142 +289,142 @@ edges
|
||||
| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.label | getRightOperand() |
|
||||
| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.order | 15 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:21:9:25 | f | semmle.label | getParameter(_) |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:21:9:25 | f | semmle.order | 17 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:21:9:25 | f | semmle.order | 18 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | getBody() |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 19 |
|
||||
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.order | 20 |
|
||||
| Foo.qll:9:21:9:25 | f | Foo.qll:9:21:9:23 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:9:21:9:25 | f | Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 17 |
|
||||
| Foo.qll:9:21:9:25 | f | Foo.qll:9:21:9:23 | TypeExpr | semmle.order | 18 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | f | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | f | semmle.order | 19 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:3:10:3 | f | semmle.order | 20 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:5:10:5 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:5:10:5 | ComparisonOp | semmle.order | 21 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:5:10:5 | ComparisonOp | semmle.order | 22 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:7:10:85 | Rank | semmle.label | getRightOperand() |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:7:10:85 | Rank | semmle.order | 22 |
|
||||
| Foo.qll:10:3:10:85 | ComparisonFormula | Foo.qll:10:7:10:85 | Rank | semmle.order | 23 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:12:10:12 | Integer | semmle.label | getRankExpr() |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:12:10:12 | Integer | semmle.order | 23 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:12:10:12 | Integer | semmle.order | 24 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | inner | semmle.label | getArgument(_) |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | inner | semmle.order | 24 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:15:10:23 | inner | semmle.order | 25 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.label | getRange() |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.order | 26 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:27:10:50 | ComparisonFormula | semmle.order | 27 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:54:10:58 | inner | semmle.label | getExpr(_) |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:54:10:58 | inner | semmle.order | 31 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:54:10:58 | inner | semmle.order | 32 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:69:10:84 | MemberCall | semmle.label | getOrderBy(_) |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:69:10:84 | MemberCall | semmle.order | 32 |
|
||||
| Foo.qll:10:7:10:85 | Rank | Foo.qll:10:69:10:84 | MemberCall | semmle.order | 33 |
|
||||
| Foo.qll:10:15:10:23 | inner | Foo.qll:10:15:10:17 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:10:15:10:23 | inner | Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 24 |
|
||||
| Foo.qll:10:15:10:23 | inner | Foo.qll:10:15:10:17 | TypeExpr | semmle.order | 25 |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | inner | semmle.label | getBase() |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | inner | semmle.order | 26 |
|
||||
| Foo.qll:10:27:10:42 | MemberCall | Foo.qll:10:27:10:31 | inner | semmle.order | 27 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:27:10:42 | MemberCall | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:27:10:42 | MemberCall | semmle.order | 26 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:27:10:42 | MemberCall | semmle.order | 27 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:44:10:44 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:44:10:44 | ComparisonOp | semmle.order | 29 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:44:10:44 | ComparisonOp | semmle.order | 30 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:46:10:50 | String | semmle.label | getRightOperand() |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:46:10:50 | String | semmle.order | 30 |
|
||||
| Foo.qll:10:27:10:50 | ComparisonFormula | Foo.qll:10:46:10:50 | String | semmle.order | 31 |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | inner | semmle.label | getBase() |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | inner | semmle.order | 32 |
|
||||
| Foo.qll:10:69:10:84 | MemberCall | Foo.qll:10:69:10:73 | inner | semmle.order | 33 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:13:17:13:21 | f | semmle.label | getParameter(_) |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:13:17:13:21 | f | semmle.order | 35 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:13:17:13:21 | f | semmle.order | 36 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:14:3:26:14 | Disjunction | semmle.label | getBody() |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:14:3:26:14 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:13:1:27:1 | ClasslessPredicate calls | Foo.qll:14:3:26:14 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:13:17:13:21 | f | Foo.qll:13:17:13:19 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:13:17:13:21 | f | Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 35 |
|
||||
| Foo.qll:13:17:13:21 | f | Foo.qll:13:17:13:19 | TypeExpr | semmle.order | 36 |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | f | semmle.label | getArgument(_) |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | f | semmle.order | 44 |
|
||||
| Foo.qll:14:3:14:10 | PredicateCall | Foo.qll:14:9:14:9 | f | semmle.order | 45 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:14:3:14:10 | PredicateCall | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 37 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:14:3:14:10 | PredicateCall | semmle.order | 38 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.order | 45 |
|
||||
| Foo.qll:14:3:16:29 | Disjunction | Foo.qll:16:3:16:29 | ComparisonFormula | semmle.order | 46 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:14:3:16:29 | Disjunction | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:14:3:16:29 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:14:3:16:29 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:18:3:18:28 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:18:3:18:28 | ComparisonFormula | semmle.order | 53 |
|
||||
| Foo.qll:14:3:18:28 | Disjunction | Foo.qll:18:3:18:28 | ComparisonFormula | semmle.order | 54 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:14:3:18:28 | Disjunction | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:14:3:18:28 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:14:3:18:28 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:20:3:20:13 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:20:3:20:13 | ComparisonFormula | semmle.order | 60 |
|
||||
| Foo.qll:14:3:20:13 | Disjunction | Foo.qll:20:3:20:13 | ComparisonFormula | semmle.order | 61 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:14:3:20:13 | Disjunction | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:14:3:20:13 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:14:3:20:13 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:22:3:22:16 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 66 |
|
||||
| Foo.qll:14:3:22:16 | Disjunction | Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 67 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:14:3:22:16 | Disjunction | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:14:3:22:16 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:14:3:22:16 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:24:3:24:23 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:24:3:24:23 | ComparisonFormula | semmle.order | 72 |
|
||||
| Foo.qll:14:3:24:23 | Disjunction | Foo.qll:24:3:24:23 | ComparisonFormula | semmle.order | 73 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:14:3:24:23 | Disjunction | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:14:3:24:23 | Disjunction | semmle.order | 37 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:14:3:24:23 | Disjunction | semmle.order | 38 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:26:3:26:14 | ComparisonFormula | semmle.label | getAnOperand() |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:26:3:26:14 | ComparisonFormula | semmle.order | 82 |
|
||||
| Foo.qll:14:3:26:14 | Disjunction | Foo.qll:26:3:26:14 | ComparisonFormula | semmle.order | 83 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:3:16:7 | String | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:3:16:7 | String | semmle.order | 45 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:3:16:7 | String | semmle.order | 46 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:9:16:9 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 47 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:9:16:9 | ComparisonOp | semmle.order | 48 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:11:16:29 | MemberCall | semmle.label | getRightOperand() |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:11:16:29 | MemberCall | semmle.order | 48 |
|
||||
| Foo.qll:16:3:16:29 | ComparisonFormula | Foo.qll:16:11:16:29 | MemberCall | semmle.order | 49 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | f | semmle.label | getBase() |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | f | semmle.order | 48 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:11:16:11 | f | semmle.order | 49 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:22:16:22 | Integer | semmle.label | getArgument(_) |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:22:16:22 | Integer | semmle.order | 50 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:22:16:22 | Integer | semmle.order | 51 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:25:16:25 | Integer | semmle.label | getArgument(_) |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:25:16:25 | Integer | semmle.order | 51 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:25:16:25 | Integer | semmle.order | 52 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:28:16:28 | Integer | semmle.label | getArgument(_) |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:28:16:28 | Integer | semmle.order | 52 |
|
||||
| Foo.qll:16:11:16:29 | MemberCall | Foo.qll:16:28:16:28 | Integer | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | f | semmle.label | getBase() |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | f | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:3:18:3 | f | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:6:18:8 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:6:18:8 | TypeExpr | semmle.order | 57 |
|
||||
| Foo.qll:18:3:18:9 | InlineCast | Foo.qll:18:6:18:8 | TypeExpr | semmle.order | 58 |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | Foo.qll:18:3:18:9 | InlineCast | semmle.label | getBase() |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | Foo.qll:18:3:18:9 | InlineCast | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:20 | MemberCall | Foo.qll:18:3:18:9 | InlineCast | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:3:18:20 | MemberCall | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:3:18:20 | MemberCall | semmle.order | 53 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:3:18:20 | MemberCall | semmle.order | 54 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:22:18:22 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 58 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:22:18:22 | ComparisonOp | semmle.order | 59 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:24:18:28 | String | semmle.label | getRightOperand() |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:24:18:28 | String | semmle.order | 59 |
|
||||
| Foo.qll:18:3:18:28 | ComparisonFormula | Foo.qll:18:24:18:28 | String | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | f | semmle.label | getBase() |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | f | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:3:20:3 | f | semmle.order | 61 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:6:20:8 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 63 |
|
||||
| Foo.qll:20:3:20:9 | InlineCast | Foo.qll:20:6:20:8 | TypeExpr | semmle.order | 64 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:3:20:9 | InlineCast | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:3:20:9 | InlineCast | semmle.order | 60 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:3:20:9 | InlineCast | semmle.order | 61 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:11:20:11 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 64 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:11:20:11 | ComparisonOp | semmle.order | 65 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.label | getRightOperand() |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.order | 65 |
|
||||
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.order | 66 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.order | 66 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.order | 67 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:5:22:5 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:5:22:5 | ComparisonOp | semmle.order | 68 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:5:22:5 | ComparisonOp | semmle.order | 69 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | getRightOperand() |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 69 |
|
||||
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 70 |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.label | getArgument(_) |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.order | 70 |
|
||||
| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.order | 71 |
|
||||
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | getTypeExpr() |
|
||||
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 70 |
|
||||
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 71 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.order | 72 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.order | 73 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:5:24:5 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:5:24:5 | ComparisonOp | semmle.order | 74 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:5:24:5 | ComparisonOp | semmle.order | 75 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:7:24:23 | AddExpr | semmle.label | getRightOperand() |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:7:24:23 | AddExpr | semmle.order | 75 |
|
||||
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:7:24:23 | AddExpr | semmle.order | 76 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:7:24:7 | Integer | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:7:24:7 | Integer | semmle.order | 75 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:7:24:7 | Integer | semmle.order | 76 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:12:24:22 | AddExpr | semmle.label | getRightOperand() |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:12:24:22 | AddExpr | semmle.order | 77 |
|
||||
| Foo.qll:24:7:24:23 | AddExpr | Foo.qll:24:12:24:22 | AddExpr | semmle.order | 78 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:12:24:12 | Integer | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:12:24:12 | Integer | semmle.order | 77 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:12:24:12 | Integer | semmle.order | 78 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:17:24:21 | AddExpr | semmle.label | getRightOperand() |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:17:24:21 | AddExpr | semmle.order | 79 |
|
||||
| Foo.qll:24:12:24:22 | AddExpr | Foo.qll:24:17:24:21 | AddExpr | semmle.order | 80 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:17:24:17 | Integer | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:17:24:17 | Integer | semmle.order | 79 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:17:24:17 | Integer | semmle.order | 80 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:21:24:21 | Integer | semmle.label | getRightOperand() |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:21:24:21 | Integer | semmle.order | 81 |
|
||||
| Foo.qll:24:17:24:21 | AddExpr | Foo.qll:24:21:24:21 | Integer | semmle.order | 82 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:3:26:6 | Boolean | semmle.label | getLeftOperand() |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:3:26:6 | Boolean | semmle.order | 82 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:3:26:6 | Boolean | semmle.order | 83 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:8:26:8 | ComparisonOp | semmle.label | getOperator() |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:8:26:8 | ComparisonOp | semmle.order | 84 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:8:26:8 | ComparisonOp | semmle.order | 85 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:10:26:14 | Boolean | semmle.label | getRightOperand() |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:10:26:14 | Boolean | semmle.order | 85 |
|
||||
| Foo.qll:26:3:26:14 | ComparisonFormula | Foo.qll:26:10:26:14 | Boolean | semmle.order | 86 |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | printAst.ql:1:1:1:28 | Import | semmle.label | getAnImport() |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | printAst.ql:1:1:1:28 | Import | semmle.order | 86 |
|
||||
| printAst.ql:1:1:1:29 | TopLevel | printAst.ql:1:1:1:28 | Import | semmle.order | 87 |
|
||||
graphProperties
|
||||
| semmle.graphKind | tree |
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
| test.qll:4:3:7:7 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
| test.qll:30:3:33:10 | Disjunction | This formula of 4 predicate calls can be replaced with a single call on a set literal, improving readability. |
|
||||
| test.qll:44:3:47:12 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
| test.qll:62:7:65:14 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
| test.qll:68:7:71:13 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
| test.qll:74:7:77:13 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
| test.qll:87:3:90:9 | Disjunction | This formula of 4 predicate calls can be replaced with a single call on a set literal, improving readability. |
|
||||
| test.qll:128:3:134:3 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. |
|
||||
1
ql/test/queries/style/UseSetLiteral/UseSetLiteral.qlref
Normal file
1
ql/test/queries/style/UseSetLiteral/UseSetLiteral.qlref
Normal file
@@ -0,0 +1 @@
|
||||
queries/style/UseSetLiteral.ql
|
||||
135
ql/test/queries/style/UseSetLiteral/test.qll
Normal file
135
ql/test/queries/style/UseSetLiteral/test.qll
Normal file
@@ -0,0 +1,135 @@
|
||||
import ql
|
||||
|
||||
predicate test1(int a) {
|
||||
a = 1 or // BAD
|
||||
a = 2 or
|
||||
a = 3 or
|
||||
a = 4
|
||||
}
|
||||
|
||||
predicate test2(int a) {
|
||||
a = [1, 2, 3, 4] // GOOD
|
||||
}
|
||||
|
||||
predicate test3(int a) {
|
||||
a = 1 and // GOOD (for the purposes of this query)
|
||||
a = 2 and
|
||||
a = 3 and
|
||||
a = 4
|
||||
}
|
||||
|
||||
bindingset[a]
|
||||
predicate test4(int a) {
|
||||
a < 1 or // GOOD (for the purposes of this query)
|
||||
a = 2 or
|
||||
a >= 3 or
|
||||
a > 4
|
||||
}
|
||||
|
||||
predicate test5() {
|
||||
test1(1) or // BAD
|
||||
test1(2) or
|
||||
test1(3) or
|
||||
test1(4)
|
||||
}
|
||||
|
||||
predicate test6() {
|
||||
test1(1) or // GOOD
|
||||
test2(2) or
|
||||
test3(3) or
|
||||
test4(4)
|
||||
}
|
||||
|
||||
int test7() {
|
||||
1 = result or // BAD
|
||||
2 = result or
|
||||
3 = result or
|
||||
4 = result
|
||||
}
|
||||
|
||||
predicate test8() {
|
||||
test7() = 1 or // BAD [NOT DETECTED]
|
||||
test7() = 2 or
|
||||
test7() = 3 or
|
||||
test7() = 4
|
||||
}
|
||||
|
||||
class MyTest8Class extends int {
|
||||
string s;
|
||||
|
||||
MyTest8Class() {
|
||||
(
|
||||
this = 1 or // BAD
|
||||
this = 2 or
|
||||
this = 3 or
|
||||
this = 4
|
||||
) and
|
||||
(
|
||||
s = "1" or // BAD
|
||||
s = "2" or
|
||||
s = "3" or
|
||||
s = "4"
|
||||
) and
|
||||
exists(float f |
|
||||
f = 1.0 or // BAD
|
||||
f = 1.5 or
|
||||
f = 2.0 or
|
||||
f = 2.5
|
||||
)
|
||||
}
|
||||
|
||||
predicate is(int x) { x = this }
|
||||
|
||||
int get() { result = this }
|
||||
}
|
||||
|
||||
predicate test9(MyTest8Class c) {
|
||||
c.is(1) or // BAD
|
||||
c.is(2) or
|
||||
c.is(3) or
|
||||
c.is(4)
|
||||
}
|
||||
|
||||
predicate test10(MyTest8Class c) {
|
||||
c.get() = 1 or // BAD [NOT DETECTED]
|
||||
c.get() = 2 or
|
||||
c.get() = 3 or
|
||||
c.get() = 4
|
||||
}
|
||||
|
||||
bindingset[a, b, c, d]
|
||||
predicate test11(int a, int b, int c, int d) {
|
||||
a = 1 or // GOOD
|
||||
b = 2 or
|
||||
c = 3 or
|
||||
d = 4
|
||||
}
|
||||
|
||||
bindingset[a, b]
|
||||
predicate test12(int a, int b) {
|
||||
a = 1 or // BAD [NOT DETECTED]
|
||||
a = 2 or
|
||||
a = 3 or
|
||||
a = 4 or
|
||||
b = 0
|
||||
}
|
||||
|
||||
predicate test13(int a, int b) {
|
||||
a = 1 and b = 1 // GOOD
|
||||
or
|
||||
a = 2 and b = 4
|
||||
or
|
||||
a = 3 and b = 9
|
||||
or
|
||||
a = 4 and b = 16
|
||||
}
|
||||
|
||||
predicate test14(int a) {
|
||||
a = 1 // BAD
|
||||
or
|
||||
(
|
||||
(a = 2 or a = 3)
|
||||
or
|
||||
a = 4
|
||||
)
|
||||
}
|
||||
@@ -4,6 +4,8 @@ type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^
|
||||
--prune=**/*.testproj ^
|
||||
--include-extension=.ql ^
|
||||
--include-extension=.qll ^
|
||||
--include-extension=.dbscheme ^
|
||||
--include-extension=.yml ^
|
||||
--size-limit=5m ^
|
||||
--language=ql ^
|
||||
"%CODEQL_EXTRACTOR_QL_WIP_DATABASE%"
|
||||
|
||||
@@ -6,6 +6,8 @@ exec "${CODEQL_DIST}/codeql" database index-files \
|
||||
--prune="**/*.testproj" \
|
||||
--include-extension=.ql \
|
||||
--include-extension=.qll \
|
||||
--include-extension=.dbscheme \
|
||||
--include-extension=.yml \
|
||||
--size-limit=5m \
|
||||
--language=ql \
|
||||
--working-dir=.\
|
||||
|
||||
Reference in New Issue
Block a user