diff --git a/cpp/ql/lib/semmle/code/cpp/Class.qll b/cpp/ql/lib/semmle/code/cpp/Class.qll index a91cedb9a0b..f139f67c70a 100644 --- a/cpp/ql/lib/semmle/code/cpp/Class.qll +++ b/cpp/ql/lib/semmle/code/cpp/Class.qll @@ -404,7 +404,10 @@ class Class extends UserType { * compiled for. For this reason, the `is_pod_class` predicate is * generated by the extractor. */ - predicate isPOD() { is_pod_class(underlyingElement(this)) } + predicate isPod() { is_pod_class(underlyingElement(this)) } + + /** DEPRECATED: Alias for isPod */ + deprecated predicate isPOD() { this.isPod() } /** * Holds if this class, struct or union is a standard-layout class diff --git a/cpp/ql/lib/semmle/code/cpp/PODType03.qll b/cpp/ql/lib/semmle/code/cpp/PODType03.qll index 88c9a1203aa..4d6e5262213 100644 --- a/cpp/ql/lib/semmle/code/cpp/PODType03.qll +++ b/cpp/ql/lib/semmle/code/cpp/PODType03.qll @@ -79,17 +79,17 @@ predicate isAggregateType03(Type t) { * user-defined copy assignment operator and no user-defined destructor. * A POD class is a class that is either a POD-struct or a POD-union. */ -predicate isPODClass03(Class c) { +predicate isPodClass03(Class c) { isAggregateClass03(c) and not exists(Variable v | v.getDeclaringType() = c and not v.isStatic() | - not isPODType03(v.getType()) + not isPodType03(v.getType()) or exists(ArrayType at | at = v.getType() and - not isPODType03(at.getBaseType()) + not isPodType03(at.getBaseType()) ) or v.getType() instanceof ReferenceType @@ -104,6 +104,9 @@ predicate isPODClass03(Class c) { ) } +/** DEPRECATED: Alias for isPodClass03 */ +deprecated predicate isPODClass03 = isPodClass03/1; + /** * Holds if `t` is a POD type, according to the rules specified in * C++03 3.9(10): @@ -112,14 +115,17 @@ predicate isPODClass03(Class c) { * such types and cv-qualified versions of these types (3.9.3) are * collectively called POD types. */ -predicate isPODType03(Type t) { +predicate isPodType03(Type t) { exists(Type ut | ut = t.getUnderlyingType() | isScalarType03(ut) or - isPODClass03(ut) + isPodClass03(ut) or - exists(ArrayType at | at = ut and isPODType03(at.getBaseType())) + exists(ArrayType at | at = ut and isPodType03(at.getBaseType())) or - isPODType03(ut.(SpecifiedType).getUnspecifiedType()) + isPodType03(ut.(SpecifiedType).getUnspecifiedType()) ) } + +/** DEPRECATED: Alias for isPodType03 */ +deprecated predicate isPODType03 = isPodType03/1; diff --git a/cpp/ql/lib/semmle/code/cpp/XML.qll b/cpp/ql/lib/semmle/code/cpp/XML.qll old mode 100755 new mode 100644 diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll b/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll index ec95b29177b..e7169d6917f 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Dependency.qll @@ -238,7 +238,7 @@ predicate dependsOnTransitive(DependsSource src, Element dest) { /** * A dependency that targets a TypeDeclarationEntry. */ -private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) { +private predicate dependsOnTde(Element src, Type t, TypeDeclarationEntry dest) { dependsOnTransitive(src, t) and getDeclarationEntries(t, dest) } @@ -247,8 +247,8 @@ private predicate dependsOnTDE(Element src, Type t, TypeDeclarationEntry dest) { * A dependency that targets a visible TypeDeclarationEntry. */ pragma[noopt] -private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry dest) { - dependsOnTDE(src, t, dest) and +private predicate dependsOnVisibleTde(Element src, Type t, TypeDeclarationEntry dest) { + dependsOnTde(src, t, dest) and exists(File g | g = dest.getFile() | exists(File f | f = src.getFile() | f.getAnIncludedFile*() = g) ) @@ -260,8 +260,8 @@ private predicate dependsOnVisibleTDE(Element src, Type t, TypeDeclarationEntry private predicate dependsOnDeclarationEntry(Element src, DeclarationEntry dest) { exists(Type t | // dependency from a Type use -> unique visible TDE - dependsOnVisibleTDE(src, t, dest) and - strictcount(TypeDeclarationEntry alt | dependsOnVisibleTDE(src, t, alt)) = 1 + dependsOnVisibleTde(src, t, dest) and + strictcount(TypeDeclarationEntry alt | dependsOnVisibleTde(src, t, alt)) = 1 ) or exists(TypedefType mid | diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NULL.qll b/cpp/ql/lib/semmle/code/cpp/commons/NULL.qll index fa6008f1379..54981548245 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NULL.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NULL.qll @@ -1,11 +1,14 @@ import semmle.code.cpp.Macro /** A macro defining NULL. */ -class NULLMacro extends Macro { - NULLMacro() { this.getHead() = "NULL" } +class NullMacro extends Macro { + NullMacro() { this.getHead() = "NULL" } } +/** DEPRECATED: Alias for NullMacro */ +deprecated class NULLMacro = NullMacro; + /** A use of the NULL macro. */ class NULL extends Literal { - NULL() { exists(NULLMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) } + NULL() { exists(NullMacro nm | this = nm.getAnInvocation().getAnExpandedElement()) } } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll index 34b2ef5aaf9..ee76e9aa671 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -474,7 +474,7 @@ module FlowVar_internal { } /** Type-specialized version of `getEnclosingElement`. */ - private ControlFlowNode getCFNParent(ControlFlowNode node) { result = node.getEnclosingElement() } + private ControlFlowNode getCfnParent(ControlFlowNode node) { result = node.getEnclosingElement() } /** * A for-loop or while-loop whose condition is always true upon entry but not @@ -526,7 +526,7 @@ module FlowVar_internal { } private predicate bbInLoopCondition(BasicBlock bb) { - getCFNParent*(bb.getANode()) = this.(Loop).getCondition() + getCfnParent*(bb.getANode()) = this.(Loop).getCondition() } private predicate bbInLoop(BasicBlock bb) { diff --git a/cpp/ql/lib/semmle/code/cpp/valuenumbering/GlobalValueNumberingImpl.qll b/cpp/ql/lib/semmle/code/cpp/valuenumbering/GlobalValueNumberingImpl.qll index d5e69d31254..7dd55dbfde3 100644 --- a/cpp/ql/lib/semmle/code/cpp/valuenumbering/GlobalValueNumberingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/valuenumbering/GlobalValueNumberingImpl.qll @@ -165,7 +165,7 @@ private ControlFlowNode mostRecentSideEffect(ControlFlowNode node) { /** Used to represent the "global value number" of an expression. */ cached -private newtype GVNBase = +private newtype GvnBase = GVN_IntConst(int val, Type t) { mk_IntConst(val, t, _) } or GVN_FloatConst(float val, Type t) { mk_FloatConst(val, t, _) } or // If the local variable does not have a defining value, then @@ -221,8 +221,8 @@ private newtype GVNBase = * expression with this `GVN` and using its `toString` and `getLocation` * methods. */ -class GVN extends GVNBase { - GVN() { this instanceof GVNBase } +class GVN extends GvnBase { + GVN() { this instanceof GvnBase } /** Gets an expression that has this GVN. */ Expr getAnExpr() { this = globalValueNumber(result) } diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql index a5f46595f6c..e7d95091d3d 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.ql @@ -63,17 +63,17 @@ class VariableDeclarationLine extends TVariableDeclarationInfo { /** * Gets a `VariableDeclarationEntry` on this line. */ - VariableDeclarationEntry getAVDE() { vdeInfo(result, c, f, line) } + VariableDeclarationEntry getAVde() { vdeInfo(result, c, f, line) } /** * Gets the start column of the first `VariableDeclarationEntry` on this line. */ - int getStartColumn() { result = min(this.getAVDE().getLocation().getStartColumn()) } + int getStartColumn() { result = min(this.getAVde().getLocation().getStartColumn()) } /** * Gets the end column of the last `VariableDeclarationEntry` on this line. */ - int getEndColumn() { result = max(this.getAVDE().getLocation().getEndColumn()) } + int getEndColumn() { result = max(this.getAVde().getLocation().getEndColumn()) } /** * Gets the rank of this `VariableDeclarationLine` in its file and class @@ -134,13 +134,13 @@ class VariableDeclarationGroup extends VariableDeclarationLine { count(VariableDeclarationLine l | l = this.getProximateNext*() | - l.getAVDE().getVariable().getName() + l.getAVde().getVariable().getName() ) } override string toString() { this.getCount() = 1 and - result = "declaration of " + this.getAVDE().getVariable().getName() + result = "declaration of " + this.getAVde().getVariable().getName() or this.getCount() > 1 and result = "group of " + this.getCount() + " fields here" diff --git a/cpp/ql/src/Best Practices/BlockWithTooManyStatements.ql b/cpp/ql/src/Best Practices/BlockWithTooManyStatements.ql index 97481bc8b03..be175660bd9 100644 --- a/cpp/ql/src/Best Practices/BlockWithTooManyStatements.ql +++ b/cpp/ql/src/Best Practices/BlockWithTooManyStatements.ql @@ -29,7 +29,4 @@ where n = strictcount(ComplexStmt s | s = b.getAStmt()) and n > 3 and complexStmt = b.getAStmt() -select b, - "Block with too many statements (" + n.toString() + - " complex statements in the block). Complex statements at: $@", complexStmt, - complexStmt.toString() +select b, "Block with too many statements (" + n.toString() + " complex statements in the block)." diff --git a/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql b/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql index 6e434c85c95..055fbf29f7c 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql @@ -110,4 +110,4 @@ where emptyBlock(s, eb) and not emptyBlockContainsNonchild(eb) and not lineComment(eb) -select eb, "Empty block without comment" +select eb, "Empty block without comment." diff --git a/cpp/ql/src/Best Practices/UseOfGoto.ql b/cpp/ql/src/Best Practices/UseOfGoto.ql index a1dcddc0123..26d72d69a0a 100644 --- a/cpp/ql/src/Best Practices/UseOfGoto.ql +++ b/cpp/ql/src/Best Practices/UseOfGoto.ql @@ -16,7 +16,7 @@ import cpp class JumpTarget extends Stmt { JumpTarget() { exists(GotoStmt g | g.getTarget() = this) } - FunctionDeclarationEntry getFDE() { result.getBlock() = this.getParentStmt+() } + FunctionDeclarationEntry getFde() { result.getBlock() = this.getParentStmt+() } predicate isForward() { exists(GotoStmt g | g.getTarget() = this | @@ -33,8 +33,8 @@ class JumpTarget extends Stmt { from FunctionDeclarationEntry fde, int nforward, int nbackward where - nforward = strictcount(JumpTarget t | t.getFDE() = fde and t.isForward()) and - nbackward = strictcount(JumpTarget t | t.getFDE() = fde and t.isBackward()) and + nforward = strictcount(JumpTarget t | t.getFde() = fde and t.isForward()) and + nbackward = strictcount(JumpTarget t | t.getFde() = fde and t.isBackward()) and nforward != 1 and nbackward != 1 select fde, diff --git a/cpp/ql/src/Documentation/CommentedOutCode.ql b/cpp/ql/src/Documentation/CommentedOutCode.ql index 89411738178..1fe70ac4c94 100644 --- a/cpp/ql/src/Documentation/CommentedOutCode.ql +++ b/cpp/ql/src/Documentation/CommentedOutCode.ql @@ -12,4 +12,4 @@ import CommentedOutCode from CommentedOutCode comment -select comment, "This comment appears to contain commented-out code" +select comment, "This comment appears to contain commented-out code." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql index fe1b2640058..dd27e4b7aee 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/BitwiseSignCheck.ql @@ -1,7 +1,6 @@ /** * @name Sign check of bitwise operation - * @description Checking the sign of a bitwise operation often has surprising - * edge cases. + * @description Checking the sign of the result of a bitwise operation may yield unexpected results. * @kind problem * @problem.severity warning * @precision high @@ -26,4 +25,4 @@ where forall(int op | op = lhs.(BitwiseAndExpr).getAnOperand().getValue().toInt() | op < 0) and // exception for cases involving macros not e.isAffectedByMacro() -select e, "Potential unsafe sign check of a bitwise operation." +select e, "Potentially unsafe sign check of a bitwise operation." diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql index 5233f567fa5..5a2180bfaf3 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/FloatComparison.ql @@ -21,4 +21,4 @@ where FloatingPointType and not ro.getAnOperand().isConstant() and // comparisons to constants generate too many false positives not left.(VariableAccess).getTarget() = right.(VariableAccess).getTarget() // skip self comparison -select ro, "Equality test on floating point values may not behave as expected." +select ro, "Equality checks on floating point values can yield unexpected results." diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql index 554937127c0..86e419f22ac 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.ql @@ -13,10 +13,11 @@ import cpp -from EnumSwitch es, float missing, float total +from EnumSwitch es, float missing, float total, EnumConstant case where not es.hasDefaultCase() and missing = count(es.getAMissingCase()) and total = missing + count(es.getASwitchCase()) and - missing / total < 0.3 -select es, "Switch statement is missing case for " + es.getAMissingCase().getName() + missing / total < 0.3 and + case = es.getAMissingCase() +select es, "Switch statement does not have a case for $@.", case, case.getName() diff --git a/cpp/ql/src/Microsoft/CallWithNullSAL.ql b/cpp/ql/src/Microsoft/CallWithNullSAL.ql index d5c74547c3e..dcf47fcbf5d 100644 --- a/cpp/ql/src/Microsoft/CallWithNullSAL.ql +++ b/cpp/ql/src/Microsoft/CallWithNullSAL.ql @@ -13,7 +13,7 @@ import SAL from Parameter p, Call c, Expr arg where - any(SALNotNull a).getDeclaration() = p and + any(SalNotNull a).getDeclaration() = p and c.getTarget() = p.getFunction() and arg = c.getArgument(p.getIndex()) and nullValue(arg) diff --git a/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql b/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql index bf52b2bb615..8202b2d4b05 100644 --- a/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql +++ b/cpp/ql/src/Microsoft/IgnoreReturnValueSAL.ql @@ -18,7 +18,7 @@ from Function f, FunctionCall call where call.getTarget() = f and call instanceof ExprInVoidContext and - any(SALCheckReturn a).getDeclaration() = f and + any(SalCheckReturn a).getDeclaration() = f and not getOptions().okToIgnoreReturnValue(call) select call, "Return value of $@ discarded although a SAL annotation " + "requires inspecting it.", f, f.getName() diff --git a/cpp/ql/src/Microsoft/InconsistentSAL.ql b/cpp/ql/src/Microsoft/InconsistentSAL.ql index e5965e62b49..fcda9e40f45 100644 --- a/cpp/ql/src/Microsoft/InconsistentSAL.ql +++ b/cpp/ql/src/Microsoft/InconsistentSAL.ql @@ -11,7 +11,7 @@ import SAL /** Holds if `e` has SAL annotation `name`. */ predicate hasAnnotation(DeclarationEntry e, string name) { - exists(SALAnnotation a | + exists(SalAnnotation a | a.getMacro().getName() = name and a.getDeclarationEntry() = e ) @@ -21,7 +21,7 @@ predicate hasAnnotation(DeclarationEntry e, string name) { predicate inheritsDeclAnnotations(DeclarationEntry e) { // Is directly annotated e.isDefinition() and - exists(SALAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" | + exists(SalAnnotation a | a.getMacro().getName() = "_Use_decl_annotations_" | a.getDeclarationEntry() = e ) or diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index 46fedbb5d80..99102755b2d 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -8,8 +8,8 @@ import cpp /** * A SAL macro defined in `sal.h` or a similar header file. */ -class SALMacro extends Macro { - SALMacro() { +class SalMacro extends Macro { + SalMacro() { this.getFile().getBaseName() = ["sal.h", "specstrings_strict.h", "specstrings.h", "w32p.h", "minwindef.h"] and ( @@ -22,15 +22,18 @@ class SALMacro extends Macro { } } +/** DEPRECATED: Alias for SalMacro */ +deprecated class SALMacro = SalMacro; + pragma[noinline] private predicate isTopLevelMacroAccess(MacroAccess ma) { not exists(ma.getParentInvocation()) } /** * An invocation of a SAL macro (excluding invocations inside other macros). */ -class SALAnnotation extends MacroInvocation { - SALAnnotation() { - this.getMacro() instanceof SALMacro and +class SalAnnotation extends MacroInvocation { + SalAnnotation() { + this.getMacro() instanceof SalMacro and isTopLevelMacroAccess(this) } @@ -47,23 +50,29 @@ class SALAnnotation extends MacroInvocation { } } +/** DEPRECATED: Alias for SalAnnotation */ +deprecated class SALAnnotation = SalAnnotation; + /** * A SAL macro indicating that the return value of a function should always be * checked. */ -class SALCheckReturn extends SALAnnotation { - SALCheckReturn() { - this.getMacro().(SALMacro).getName() = ["_Check_return_", "_Must_inspect_result_"] +class SalCheckReturn extends SalAnnotation { + SalCheckReturn() { + this.getMacro().(SalMacro).getName() = ["_Check_return_", "_Must_inspect_result_"] } } +/** DEPRECATED: Alias for SalCheckReturn */ +deprecated class SALCheckReturn = SalCheckReturn; + /** * A SAL macro indicating that a pointer variable or return value should not be * `NULL`. */ -class SALNotNull extends SALAnnotation { - SALNotNull() { - exists(SALMacro m | m = this.getMacro() | +class SalNotNull extends SalAnnotation { + SalNotNull() { + exists(SalMacro m | m = this.getMacro() | not m.getName().matches("%\\_opt\\_%") and ( m.getName().matches("_In%") or @@ -80,12 +89,15 @@ class SALNotNull extends SALAnnotation { } } +/** DEPRECATED: Alias for SalNotNull */ +deprecated class SALNotNull = SalNotNull; + /** * A SAL macro indicating that a value may be `NULL`. */ -class SALMaybeNull extends SALAnnotation { - SALMaybeNull() { - exists(SALMacro m | m = this.getMacro() | +class SalMaybeNull extends SalAnnotation { + SalMaybeNull() { + exists(SalMacro m | m = this.getMacro() | m.getName().matches("%\\_opt\\_%") or m.getName().matches("\\_Ret_maybenull\\_%") or m.getName() = "_Result_nullonfailure_" @@ -93,14 +105,17 @@ class SALMaybeNull extends SALAnnotation { } } +/** DEPRECATED: Alias for SalMaybeNull */ +deprecated class SALMaybeNull = SalMaybeNull; + /** * A parameter annotated by one or more SAL annotations. */ -class SALParameter extends Parameter { +class SalParameter extends Parameter { /** One of this parameter's annotations. */ - SALAnnotation a; + SalAnnotation a; - SALParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } + SalParameter() { annotatesAt(a, this.getADeclarationEntry(), _, _) } predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") } @@ -109,14 +124,17 @@ class SALParameter extends Parameter { predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") } } +/** DEPRECATED: Alias for SalParameter */ +deprecated class SALParameter = SalParameter; + /////////////////////////////////////////////////////////////////////////////// // Implementation details /** * Holds if `a` annotates the declaration entry `d` and * its start position is the `idx`th position in `file` that holds a SAL element. */ -private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, int idx) { - annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx) +private predicate annotatesAt(SalAnnotation a, DeclarationEntry d, File file, int idx) { + annotatesAtPosition(a.(SalElement).getStartPosition(), d, file, idx) } /** @@ -127,12 +145,12 @@ private predicate annotatesAt(SALAnnotation a, DeclarationEntry d, File file, in // For performance reasons, do not mention the annotation itself here, // but compute with positions instead. This performs better on databases // with many annotations at the same position. -private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File file, int idx) { +private predicate annotatesAtPosition(SalPosition pos, DeclarationEntry d, File file, int idx) { pos = salRelevantPositionAt(file, idx) and salAnnotationPos(pos) and ( // Base case: `pos` right before `d` - d.(SALElement).getStartPosition() = salRelevantPositionAt(file, idx + 1) + d.(SalElement).getStartPosition() = salRelevantPositionAt(file, idx + 1) or // Recursive case: `pos` right before some annotation on `d` annotatesAtPosition(_, d, file, idx + 1) @@ -143,10 +161,10 @@ private predicate annotatesAtPosition(SALPosition pos, DeclarationEntry d, File * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. */ -library class SALElement extends Element { - SALElement() { - containsSALAnnotation(this.(DeclarationEntry).getFile()) or - this instanceof SALAnnotation +library class SalElement extends Element { + SalElement() { + containsSalAnnotation(this.(DeclarationEntry).getFile()) or + this instanceof SalAnnotation } predicate hasStartPosition(File file, int line, int col) { @@ -173,25 +191,28 @@ library class SALElement extends Element { ) } - SALPosition getStartPosition() { + SalPosition getStartPosition() { exists(File file, int line, int col | this.hasStartPosition(file, line, col) and - result = MkSALPosition(file, line, col) + result = MkSalPosition(file, line, col) ) } } +/** DEPRECATED: Alias for SalElement */ +deprecated class SALElement = SalElement; + /** Holds if `file` contains a SAL annotation. */ pragma[noinline] -private predicate containsSALAnnotation(File file) { any(SALAnnotation a).getFile() = file } +private predicate containsSalAnnotation(File file) { any(SalAnnotation a).getFile() = file } /** * A source-file position of a `SALElement`. Unlike location, this denotes a * point in the file rather than a range. */ -private newtype SALPosition = - MkSALPosition(File file, int line, int col) { - exists(SALElement e | +private newtype SalPosition = + MkSalPosition(File file, int line, int col) { + exists(SalElement e | e.hasStartPosition(file, line, col) or e.hasEndPosition(file, line, col) @@ -200,18 +221,18 @@ private newtype SALPosition = /** Holds if `pos` is the start position of a SAL annotation. */ pragma[noinline] -private predicate salAnnotationPos(SALPosition pos) { - any(SALAnnotation a).(SALElement).getStartPosition() = pos +private predicate salAnnotationPos(SalPosition pos) { + any(SalAnnotation a).(SalElement).getStartPosition() = pos } /** * Gets the `idx`th position in `file` that holds a SAL element, * ordering positions lexicographically by their start line and start column. */ -private SALPosition salRelevantPositionAt(File file, int idx) { +private SalPosition salRelevantPositionAt(File file, int idx) { result = - rank[idx](SALPosition pos, int line, int col | - pos = MkSALPosition(file, line, col) + rank[idx](SalPosition pos, int line, int col | + pos = MkSalPosition(file, line, col) | pos order by line, col ) diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql index 9a08bbd64a6..c062039d930 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql @@ -24,7 +24,7 @@ where if e = DefinitionInSnapshot() then defined = "" else - if e = SuggestiveSALAnnotation() + if e = SuggestiveSalAnnotation() then defined = "externally defined (SAL) " else defined = "externally defined (CSV) " ) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 29f519163cc..a5def46dd60 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -149,7 +149,7 @@ newtype Evidence = * The function is externally defined, but the parameter has an `_out` SAL annotation which * suggests that it is initialized in the function. */ - SuggestiveSALAnnotation() or + SuggestiveSalAnnotation() or /** * We have been given a CSV file which indicates this parameter is conditionally initialized. */ @@ -198,8 +198,8 @@ class InitializationFunction extends Function { or // If we have no definition, we look at SAL annotations not this.hasDefinition() and - this.getParameter(i).(SALParameter).isOut() and - evidence = SuggestiveSALAnnotation() + this.getParameter(i).(SalParameter).isOut() and + evidence = SuggestiveSalAnnotation() or // We have some external information that this function conditionally initializes not this.hasDefinition() and diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql index da17913dec5..abd1773afd8 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql @@ -19,8 +19,8 @@ import DataFlow::PathGraph /** * A configuration for tracking XML objects and their states. */ -class XXEConfiguration extends DataFlow::Configuration { - XXEConfiguration() { this = "XXEConfiguration" } +class XxeConfiguration extends DataFlow::Configuration { + XxeConfiguration() { this = "XXEConfiguration" } override predicate isSource(DataFlow::Node node, string flowstate) { any(XmlLibrary l).configurationSource(node, flowstate) @@ -45,7 +45,7 @@ class XXEConfiguration extends DataFlow::Configuration { } } -from XXEConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink +from XxeConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink where conf.hasFlowPath(source, sink) select sink, source, sink, "This $@ is not configured to prevent an XML external entity (XXE) attack.", source, "XML parser" diff --git a/cpp/ql/src/change-notes/2022-08-23-alert-messages.md b/cpp/ql/src/change-notes/2022-08-23-alert-messages.md new file mode 100644 index 00000000000..22f4c5c6682 --- /dev/null +++ b/cpp/ql/src/change-notes/2022-08-23-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to make the message consistent with other languages. \ No newline at end of file diff --git a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql index 0420b9c3984..d3f7ac9adb7 100644 --- a/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql +++ b/cpp/ql/src/jsf/3.02 Code Size and Complexity/AV Rule 2.ql @@ -16,17 +16,17 @@ import cpp // pointers. This will obviously not catch code that uses inline assembly to achieve // self-modification, nor will it spot the use of OS mechanisms to write into process // memory (such as WriteProcessMemory under Windows). -predicate maybeSMCConversion(Type t1, Type t2) { +predicate maybeSmcConversion(Type t1, Type t2) { t1 instanceof FunctionPointerType and t2 instanceof PointerType and not t2 instanceof FunctionPointerType and not t2 instanceof VoidPointerType or - maybeSMCConversion(t2, t1) + maybeSmcConversion(t2, t1) } from Expr e where e.fromSource() and - maybeSMCConversion(e.getUnderlyingType(), e.getActualType()) + maybeSmcConversion(e.getUnderlyingType(), e.getActualType()) select e, "AV Rule 2: There shall not be any self-modifying code." diff --git a/cpp/ql/test/library-tests/pod/isPOD.ql b/cpp/ql/test/library-tests/pod/isPOD.ql index e7860247eb7..77f7e136019 100644 --- a/cpp/ql/test/library-tests/pod/isPOD.ql +++ b/cpp/ql/test/library-tests/pod/isPOD.ql @@ -1,5 +1,5 @@ import cpp from Class c, boolean ispod -where if c.isPOD() then ispod = true else ispod = false +where if c.isPod() then ispod = true else ispod = false select c, ispod diff --git a/cpp/ql/test/library-tests/pod/isPOD03.ql b/cpp/ql/test/library-tests/pod/isPOD03.ql index 42f6eed559f..84f2433f8da 100644 --- a/cpp/ql/test/library-tests/pod/isPOD03.ql +++ b/cpp/ql/test/library-tests/pod/isPOD03.ql @@ -1,5 +1,5 @@ import semmle.code.cpp.PODType03 from Class c, boolean ispod -where if isPODClass03(c) then ispod = true else ispod = false +where if isPodClass03(c) then ispod = true else ispod = false select c, ispod diff --git a/cpp/ql/test/library-tests/sal/sal.ql b/cpp/ql/test/library-tests/sal/sal.ql index eb4908bae9e..52104793d3e 100644 --- a/cpp/ql/test/library-tests/sal/sal.ql +++ b/cpp/ql/test/library-tests/sal/sal.ql @@ -1,4 +1,4 @@ import Microsoft.SAL -from SALAnnotation a +from SalAnnotation a select a, a.getDeclaration() diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/EmptyBlock/EmptyBlock.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/EmptyBlock/EmptyBlock.expected index db58438a704..dc572fae9be 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/EmptyBlock/EmptyBlock.expected +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/EmptyBlock/EmptyBlock.expected @@ -1,3 +1,3 @@ -| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment | -| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment | -| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment | +| empty_block.cpp:9:10:9:11 | { ... } | Empty block without comment. | +| empty_block.cpp:12:10:13:3 | { ... } | Empty block without comment. | +| empty_block.cpp:20:10:21:3 | { ... } | Empty block without comment. | diff --git a/cpp/ql/test/query-tests/Documentation/CommentedOutCode/CommentedOutCode.expected b/cpp/ql/test/query-tests/Documentation/CommentedOutCode/CommentedOutCode.expected index b7889805514..9b4547cd2cd 100644 --- a/cpp/ql/test/query-tests/Documentation/CommentedOutCode/CommentedOutCode.expected +++ b/cpp/ql/test/query-tests/Documentation/CommentedOutCode/CommentedOutCode.expected @@ -1,20 +1,20 @@ -| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code | -| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code | -| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code | -| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code | -| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code | -| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code | -| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code | -| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code | -| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code | -| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code | -| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code | -| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code | -| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code | -| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code | -| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code | -| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code | -| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code | -| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code | -| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code | -| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code | +| test2.cpp:37:1:37:39 | // int myFunction() { return myValue; } | This comment appears to contain commented-out code. | +| test2.cpp:39:1:39:45 | // int myFunction() const { return myValue; } | This comment appears to contain commented-out code. | +| test2.cpp:41:1:41:54 | // int myFunction() const noexcept { return myValue; } | This comment appears to contain commented-out code. | +| test2.cpp:43:1:43:18 | // #define MYMACRO | This comment appears to contain commented-out code. | +| test2.cpp:45:1:45:23 | // #include "include.h" | This comment appears to contain commented-out code. | +| test2.cpp:47:1:51:2 | /*\n#ifdef\nvoid myFunction();\n#endif\n*/ | This comment appears to contain commented-out code. | +| test2.cpp:59:1:59:24 | // #if(defined(MYMACRO)) | This comment appears to contain commented-out code. | +| test2.cpp:63:1:63:15 | // #pragma once | This comment appears to contain commented-out code. | +| test2.cpp:65:1:65:17 | // # pragma once | This comment appears to contain commented-out code. | +| test2.cpp:67:1:67:19 | /*#error"myerror"*/ | This comment appears to contain commented-out code. | +| test2.cpp:91:1:95:2 | /*\n#ifdef MYMACRO\n\t// ...\n#endif // #ifdef MYMACRO\n*/ | This comment appears to contain commented-out code. | +| test2.cpp:107:21:107:43 | // #include "config2.h" | This comment appears to contain commented-out code. | +| test2.cpp:115:16:115:35 | /* #ifdef MYMACRO */ | This comment appears to contain commented-out code. | +| test2.cpp:117:1:117:24 | // commented_out_code(); | This comment appears to contain commented-out code. | +| test2.cpp:120:2:120:25 | // commented_out_code(); | This comment appears to contain commented-out code. | +| test.c:2:1:2:22 | // commented out code; | This comment appears to contain commented-out code. | +| test.c:4:1:7:8 | // some; | This comment appears to contain commented-out code. | +| test.c:9:1:13:8 | // also; | This comment appears to contain commented-out code. | +| test.c:21:1:26:2 | /*\n some;\n commented;\n out;\n code;\n*/ | This comment appears to contain commented-out code. | +| test.c:28:1:34:2 | /*\n also;\n this\n is;\n commented-out\n code;\n*/ | This comment appears to contain commented-out code. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected index a6d6da31f69..ce1f90c3ed2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BitwiseSignCheck/BitwiseSignCheck.expected @@ -1,4 +1,4 @@ -| bsc.cpp:2:10:2:32 | ... > ... | Potential unsafe sign check of a bitwise operation. | -| bsc.cpp:6:10:6:32 | ... > ... | Potential unsafe sign check of a bitwise operation. | -| bsc.cpp:18:10:18:28 | ... > ... | Potential unsafe sign check of a bitwise operation. | -| bsc.cpp:22:10:22:28 | ... < ... | Potential unsafe sign check of a bitwise operation. | +| bsc.cpp:2:10:2:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. | +| bsc.cpp:6:10:6:32 | ... > ... | Potentially unsafe sign check of a bitwise operation. | +| bsc.cpp:18:10:18:28 | ... > ... | Potentially unsafe sign check of a bitwise operation. | +| bsc.cpp:22:10:22:28 | ... < ... | Potentially unsafe sign check of a bitwise operation. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/FloatComparison/FloatComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/FloatComparison/FloatComparison.expected index 6152aa1c475..31fda8e5f89 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/FloatComparison/FloatComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/FloatComparison/FloatComparison.expected @@ -1,4 +1,4 @@ -| c.c:10:5:10:10 | ... == ... | Equality test on floating point values may not behave as expected. | -| c.c:14:5:14:14 | ... == ... | Equality test on floating point values may not behave as expected. | -| c.c:16:5:16:12 | ... == ... | Equality test on floating point values may not behave as expected. | -| c.c:17:5:17:12 | ... == ... | Equality test on floating point values may not behave as expected. | +| c.c:10:5:10:10 | ... == ... | Equality checks on floating point values can yield unexpected results. | +| c.c:14:5:14:14 | ... == ... | Equality checks on floating point values can yield unexpected results. | +| c.c:16:5:16:12 | ... == ... | Equality checks on floating point values can yield unexpected results. | +| c.c:17:5:17:12 | ... == ... | Equality checks on floating point values can yield unexpected results. | diff --git a/csharp/ql/campaigns/Solorigate/src/ModifiedFnvFunctionDetection.ql b/csharp/ql/campaigns/Solorigate/src/ModifiedFnvFunctionDetection.ql index e9f81596e04..5e4a47f7ec0 100644 --- a/csharp/ql/campaigns/Solorigate/src/ModifiedFnvFunctionDetection.ql +++ b/csharp/ql/campaigns/Solorigate/src/ModifiedFnvFunctionDetection.ql @@ -15,7 +15,7 @@ import experimental.code.csharp.Cryptography.NonCryptographicHashes from Variable v, Literal l, LoopStmt loop, Expr additional_xor where - maybeUsedInFNVFunction(v, _, _, loop) and + maybeUsedInFnvFunction(v, _, _, loop) and ( exists(BitwiseXorExpr xor2 | xor2.getAnOperand() = l and additional_xor = xor2 | loop.getAControlFlowExitNode().getASuccessor*() = xor2.getAControlFlowNode() and diff --git a/csharp/ql/lib/experimental/code/csharp/Cryptography/NonCryptographicHashes.qll b/csharp/ql/lib/experimental/code/csharp/Cryptography/NonCryptographicHashes.qll index 03585e32a77..28de629816d 100644 --- a/csharp/ql/lib/experimental/code/csharp/Cryptography/NonCryptographicHashes.qll +++ b/csharp/ql/lib/experimental/code/csharp/Cryptography/NonCryptographicHashes.qll @@ -13,7 +13,7 @@ private import semmle.code.csharp.dataflow.TaintTracking2 predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Expr mul, LoopStmt loop) { callable = loop.getEnclosingCallable() and ( - maybeUsedInFNVFunction(v, xor, mul, loop) or + maybeUsedInFnvFunction(v, xor, mul, loop) or maybeUsedInElfHashFunction(v, xor, mul, loop) ) } @@ -23,7 +23,7 @@ predicate maybeANonCryptogrphicHash(Callable callable, Variable v, Expr xor, Exp * where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression * followed by a multiplication `mul` expression. */ -predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) { +predicate maybeUsedInFnvFunction(Variable v, Operation xor, Operation mul, LoopStmt loop) { exists(Expr e1, Expr e2 | e1.getAChild*() = v.getAnAccess() and e2.getAChild*() = v.getAnAccess() and @@ -37,6 +37,9 @@ predicate maybeUsedInFNVFunction(Variable v, Operation xor, Operation mul, LoopS loop.getAChild*() = xor.getEnclosingStmt() } +/** DEPRECATED: Alias for maybeUsedInFnvFunction */ +deprecated predicate maybeUsedInFNVFunction = maybeUsedInFnvFunction/4; + /** * Holds if the arguments are used in a way that resembles an Elf-Hash hash function * where there is a loop statement `loop` where the variable `v` is used in an xor `xor` expression diff --git a/csharp/ql/lib/semmle/code/csharp/XML.qll b/csharp/ql/lib/semmle/code/csharp/XML.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking2.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking3.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking4.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking5.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPublic.qll old mode 100755 new mode 100644 diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll index b194ad57d57..0770a948b09 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll @@ -6,7 +6,7 @@ import csharp private import Email::Email private import ExternalLocationSink private import Html -private import semmle.code.csharp.security.dataflow.XSSSinks as XSSSinks +private import semmle.code.csharp.security.dataflow.XSSSinks as XssSinks private import semmle.code.csharp.frameworks.system.web.UI /** A data flow sink of remote user output. */ diff --git a/csharp/ql/src/Bad Practices/Comments/TodoComments.ql b/csharp/ql/src/Bad Practices/Comments/TodoComments.ql index bb87724678f..751c064bccf 100644 --- a/csharp/ql/src/Bad Practices/Comments/TodoComments.ql +++ b/csharp/ql/src/Bad Practices/Comments/TodoComments.ql @@ -14,4 +14,4 @@ import csharp from CommentLine c where c.getText().regexpMatch("(?s).*FIXME.*|.*TODO.*|.*(?= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:16:31:16:37 | access to array element | access to array element | -| ContainerLengthCmpOffByOne.cs:27:13:27:28 | ... <= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:29:31:29:37 | access to array element | access to array element | -| ContainerLengthCmpOffByOne.cs:33:13:33:28 | ... >= ... | Off-by-one index comparison against length leads to possible out of bounds $@. | ContainerLengthCmpOffByOne.cs:35:31:35:37 | access to array element | access to array element | +| ContainerLengthCmpOffByOne.cs:8:25:8:40 | ... <= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:10:31:10:37 | access to array element | access to array element | +| ContainerLengthCmpOffByOne.cs:14:25:14:40 | ... >= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:16:31:16:37 | access to array element | access to array element | +| ContainerLengthCmpOffByOne.cs:27:13:27:28 | ... <= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:29:31:29:37 | access to array element | access to array element | +| ContainerLengthCmpOffByOne.cs:33:13:33:28 | ... >= ... | Off-by-one index comparison against length may lead to out-of-bounds $@. | ContainerLengthCmpOffByOne.cs:35:31:35:37 | access to array element | access to array element | diff --git a/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/RandomUsedOnce.cs b/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/RandomUsedOnce.cs old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/RandomUsedOnce.qlref b/csharp/ql/test/query-tests/Likely Bugs/RandomUsedOnce/RandomUsedOnce.qlref old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/RecursiveEquals.cs b/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/RecursiveEquals.cs old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/RecursiveEquals.qlref b/csharp/ql/test/query-tests/Likely Bugs/RecursiveEquals/RecursiveEquals.qlref old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/UncheckedCastInEquals.expected b/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/UncheckedCastInEquals.expected index 2706724c429..f602c9fcd11 100644 --- a/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/UncheckedCastInEquals.expected +++ b/csharp/ql/test/query-tests/Likely Bugs/UncheckedCastInEquals/UncheckedCastInEquals.expected @@ -1 +1 @@ -| UncheckedCastInEquals.cs:7:17:7:27 | (...) ... | Missing type-check before casting parameter to 'Equals'. | +| UncheckedCastInEquals.cs:7:17:7:27 | (...) ... | Equals() method does not check argument type. | diff --git a/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected b/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.qlref b/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.qlref old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected index c9c2f544940..01b1dcfb67f 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-730/RegexInjection/RegexInjection.expected @@ -8,4 +8,4 @@ nodes | RegexInjection.cs:14:19:14:23 | access to local variable regex | semmle.label | access to local variable regex | subpaths #select -| RegexInjection.cs:14:19:14:23 | access to local variable regex | RegexInjection.cs:10:24:10:46 | access to property QueryString : NameValueCollection | RegexInjection.cs:14:19:14:23 | access to local variable regex | $@ flows to the construction of a regular expression. | RegexInjection.cs:10:24:10:46 | access to property QueryString | User-provided value | +| RegexInjection.cs:14:19:14:23 | access to local variable regex | RegexInjection.cs:10:24:10:46 | access to property QueryString : NameValueCollection | RegexInjection.cs:14:19:14:23 | access to local variable regex | This regular expression is constructed from a $@. | RegexInjection.cs:10:24:10:46 | access to property QueryString | user-provided value | diff --git a/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref b/csharp/ql/test/query-tests/UseBraces/UseBraces.qlref old mode 100755 new mode 100644 diff --git a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected index f6e2f4d87fd..8021c21df2a 100644 --- a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected +++ b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected @@ -1,3 +1,3 @@ -| RedundantToStringCall.cs:7:27:7:38 | call to method ToString | Redundant call to 'ToString'. | -| RedundantToStringCall.cs:10:37:10:48 | call to method ToString | Redundant call to 'ToString'. | -| RedundantToStringCallBad.cs:7:45:7:56 | call to method ToString | Redundant call to 'ToString'. | +| RedundantToStringCall.cs:7:27:7:38 | call to method ToString | Redundant call to 'ToString' on a String object. | +| RedundantToStringCall.cs:10:37:10:48 | call to method ToString | Redundant call to 'ToString' on a String object. | +| RedundantToStringCallBad.cs:7:45:7:56 | call to method ToString | Redundant call to 'ToString' on a String object. | diff --git a/docs/codeql/support/reusables/versions-compilers.rst b/docs/codeql/support/reusables/versions-compilers.rst index c734cf65ff3..21a0526af5f 100644 --- a/docs/codeql/support/reusables/versions-compilers.rst +++ b/docs/codeql/support/reusables/versions-compilers.rst @@ -23,7 +23,7 @@ JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" Python,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10",Not applicable,``.py`` Ruby [7]_,"up to 3.0.2",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" - TypeScript [8]_,"2.6-4.7",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" + TypeScript [8]_,"2.6-4.8",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" .. container:: footnote-group diff --git a/go/ql/lib/semmle/go/Util.qll b/go/ql/lib/semmle/go/Util.qll index ff597cdcc28..8c089054d90 100644 --- a/go/ql/lib/semmle/go/Util.qll +++ b/go/ql/lib/semmle/go/Util.qll @@ -12,7 +12,10 @@ class Boolean extends boolean { /** * Gets a regexp pattern that matches common top-level domain names. */ -string commonTLD() { +string commonTld() { // according to ranking by http://google.com/search?q=site:.<> result = "(?:com|org|edu|gov|uk|net|io)(?![a-z0-9])" } + +/** DEPRECATED: Alias for commonTld */ +deprecated string commonTLD() { result = commonTld() } diff --git a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll index c9c0c58b33e..511bbd4ddce 100644 --- a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll +++ b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll @@ -114,7 +114,7 @@ private predicate entryNode(ControlFlow::Node node) { node.isEntryNode() } * graph so that we can use the dominator tree to find the most recent * side-effect. */ -private predicate sideEffectCFG(ControlFlow::Node src, ControlFlow::Node dst) { +private predicate sideEffectCfg(ControlFlow::Node src, ControlFlow::Node dst) { src.getASuccessor() = dst or // Add an edge from the entry point to any node that might have a side @@ -128,7 +128,7 @@ private predicate sideEffectCFG(ControlFlow::Node src, ControlFlow::Node dst) { * the side-effect CFG. */ private predicate iDomEffect(ControlFlow::Node dominator, ControlFlow::Node node) = - idominance(entryNode/1, sideEffectCFG/2)(_, dominator, node) + idominance(entryNode/1, sideEffectCfg/2)(_, dominator, node) /** * Gets the most recent side effect. To be more precise, `result` is a @@ -190,7 +190,7 @@ private ControlFlow::Node mostRecentSideEffect(ControlFlow::Node node) { /** Used to represent the "global value number" of an expression. */ cached -private newtype GVNBase = +private newtype GvnBase = MkNumericConst(string val) { mkNumericConst(_, val) } or MkStringConst(string val) { mkStringConst(_, val) } or MkBoolConst(boolean val) { mkBoolConst(_, val) } or @@ -204,7 +204,7 @@ private newtype GVNBase = MkOtherVariable(ValueEntity x, ControlFlow::Node dominator) { mkOtherVariable(_, x, dominator) } or MkMethodAccess(GVN base, Function m) { mkMethodAccess(_, base, m) } or MkFieldRead(GVN base, Field f, ControlFlow::Node dominator) { mkFieldRead(_, base, f, dominator) } or - MkPureCall(Function f, GVN callee, GVNList args) { mkPureCall(_, f, callee, args) } or + MkPureCall(Function f, GVN callee, GvnList args) { mkPureCall(_, f, callee, args) } or MkIndex(GVN base, GVN index, ControlFlow::Node dominator) { mkIndex(_, base, index, dominator) } or // Dereference a pointer. The value might have changed since the last // time the pointer was dereferenced, so we need to include a definition @@ -217,22 +217,22 @@ private newtype GVNBase = // given a unique number based on the expression itself. MkUnanalyzable(DataFlow::Node e) { not analyzableExpr(e) } -private newtype GVNList = +private newtype GvnList = MkNil() or - MkCons(GVN head, GVNList tail) { globalValueNumbers(_, _, head, tail) } + MkCons(GVN head, GvnList tail) { globalValueNumbers(_, _, head, tail) } -private GVNList globalValueNumbers(DataFlow::CallNode ce, int start) { +private GvnList globalValueNumbers(DataFlow::CallNode ce, int start) { analyzableCall(ce, _) and start = ce.getNumArgument() and result = MkNil() or - exists(GVN head, GVNList tail | + exists(GVN head, GvnList tail | globalValueNumbers(ce, start, head, tail) and result = MkCons(head, tail) ) } -private predicate globalValueNumbers(DataFlow::CallNode ce, int start, GVN head, GVNList tail) { +private predicate globalValueNumbers(DataFlow::CallNode ce, int start, GVN head, GvnList tail) { analyzableCall(ce, _) and head = globalValueNumber(ce.getArgument(start)) and tail = globalValueNumbers(ce, start + 1) @@ -254,8 +254,8 @@ private predicate globalValueNumbers(DataFlow::CallNode ce, int start, GVN head, * expression with this `GVN` and using its `toString` and `getLocation` * methods. */ -class GVN extends GVNBase { - GVN() { this instanceof GVNBase } +class GVN extends GvnBase { + GVN() { this instanceof GvnBase } /** Gets a data-flow node that has this GVN. */ DataFlow::Node getANode() { this = globalValueNumber(result) } @@ -386,7 +386,7 @@ private predicate analyzableCall(DataFlow::CallNode ce, Function f) { not ce.isConst() } -private predicate mkPureCall(DataFlow::CallNode ce, Function f, GVN callee, GVNList args) { +private predicate mkPureCall(DataFlow::CallNode ce, Function f, GVN callee, GvnList args) { analyzableCall(ce, f) and callee = globalValueNumber(ce.getCalleeNode()) and args = globalValueNumbers(ce, 0) @@ -523,7 +523,7 @@ GVN globalValueNumber(DataFlow::Node nd) { result = MkFieldRead(qualifier, target, dominator) ) or - exists(Function f, GVN callee, GVNList args | + exists(Function f, GVN callee, GvnList args | mkPureCall(nd, f, callee, args) and result = MkPureCall(f, callee, args) ) diff --git a/go/ql/src/RedundantCode/DuplicateCondition.ql b/go/ql/src/RedundantCode/DuplicateCondition.ql index ac3c586eda4..3d7416450dc 100644 --- a/go/ql/src/RedundantCode/DuplicateCondition.ql +++ b/go/ql/src/RedundantCode/DuplicateCondition.ql @@ -24,10 +24,10 @@ Expr getCondition(IfStmt stmt, int i) { } /** Gets the global value number of `e`, which is the `i`th condition of `is`. */ -GVN conditionGVN(IfStmt is, int i, Expr e) { +GVN conditionGvn(IfStmt is, int i, Expr e) { e = getCondition(is, i) and result = e.getGlobalValueNumber() } from IfStmt is, Expr e, Expr f, int i, int j -where conditionGVN(is, i, e) = conditionGVN(is, j, f) and i < j +where conditionGvn(is, i, e) = conditionGvn(is, j, f) and i < j select f, "This condition is a duplicate of $@.", e, "an earlier condition" diff --git a/go/ql/src/RedundantCode/DuplicateSwitchCase.ql b/go/ql/src/RedundantCode/DuplicateSwitchCase.ql index 7af97b76875..b2777a1131f 100644 --- a/go/ql/src/RedundantCode/DuplicateSwitchCase.ql +++ b/go/ql/src/RedundantCode/DuplicateSwitchCase.ql @@ -14,10 +14,10 @@ import go /** Gets the global value number of `e`, which is the `i`th case label of `switch`. */ -GVN switchCaseGVN(SwitchStmt switch, int i, Expr e) { +GVN switchCaseGvn(SwitchStmt switch, int i, Expr e) { e = switch.getCase(i).getExpr(0) and result = e.getGlobalValueNumber() } from SwitchStmt switch, int i, Expr e, int j, Expr f -where switchCaseGVN(switch, i, e) = switchCaseGVN(switch, j, f) and i < j +where switchCaseGvn(switch, i, e) = switchCaseGvn(switch, j, f) and i < j select f, "This case is a duplicate of $@.", e, "an earlier case" diff --git a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql index ef0ec60d871..a6ce8c8c8b6 100644 --- a/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql +++ b/go/ql/src/Security/CWE-020/IncompleteHostnameRegexp.ql @@ -28,7 +28,7 @@ predicate isIncompleteHostNameRegexpPattern(string pattern, string hostPart) { "(?`_,``org.json``,,236,,,,,,,, Java Standard Library,``java.*``,3,577,130,28,,,7,,,10 Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2 - `Spring `_,``org.springframework.*``,29,476,101,,,,19,14,,29 + `Spring `_,``org.springframework.*``,29,477,101,,,,19,14,,29 Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``kotlin.jvm.internal``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",65,395,932,,,,14,18,,3 - Totals,,217,6438,1474,117,6,10,107,33,1,84 + Totals,,217,6439,1474,117,6,10,107,33,1,84 diff --git a/java/downgrades/ecb42310286011ada450ff65b9b417509863549f/old.dbscheme b/java/downgrades/ecb42310286011ada450ff65b9b417509863549f/old.dbscheme old mode 100755 new mode 100644 diff --git a/java/downgrades/ecb42310286011ada450ff65b9b417509863549f/semmlecode.dbscheme b/java/downgrades/ecb42310286011ada450ff65b9b417509863549f/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/downgrades/initial/semmlecode.dbscheme b/java/downgrades/initial/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index f7932c7327f..ace326a600e 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1584,7 +1584,7 @@ open class KotlinFileExtractor( } } - private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.find { it is IrFunction && it.name.asString() == name } as IrFunction? + private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType { it.name.asString() == name } val jvmIntrinsicsClass by lazy { val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner @@ -1600,11 +1600,13 @@ open class KotlinFileExtractor( return result } - private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? { + private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, parameterTypes: Array, warnAgainstElement: IrElement): IrFunction? { val fn = pluginContext.referenceFunctions(FqName(functionFilter)) - .firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type } - ?.owner + .firstOrNull { fnSymbol -> + fnSymbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type && + fnSymbol.owner.valueParameters.map { it.type.classFqName?.asString() }.toTypedArray() contentEquals parameterTypes + }?.owner if (fn != null) { if (fn.parentClassOrNull != null) { @@ -1641,12 +1643,11 @@ open class KotlinFileExtractor( } val stringValueOfObjectMethod by lazy { - val result = javaLangString?.declarations?.find { - it is IrFunction && + val result = javaLangString?.declarations?.findSubType { it.name.asString() == "valueOf" && it.valueParameters.size == 1 && it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType - } as IrFunction? + } if (result == null) { logger.error("Couldn't find declaration java.lang.String.valueOf(Object)") } @@ -1654,9 +1655,9 @@ open class KotlinFileExtractor( } val objectCloneMethod by lazy { - val result = javaLangObject?.declarations?.find { - it is IrFunction && it.name.asString() == "clone" - } as IrFunction? + val result = javaLangObject?.declarations?.findSubType { + it.name.asString() == "clone" + } if (result == null) { logger.error("Couldn't find declaration java.lang.Object.clone(...)") } @@ -1670,10 +1671,9 @@ open class KotlinFileExtractor( } val kotlinNoWhenBranchMatchedConstructor by lazy { - val result = kotlinNoWhenBranchMatchedExn?.declarations?.find { - it is IrConstructor && + val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType { it.valueParameters.isEmpty() - } as IrConstructor? + } if (result == null) { logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException") } @@ -1756,6 +1756,12 @@ open class KotlinFileExtractor( else -> false } + private fun isGenericArrayType(typeName: String) = + when(typeName) { + "Array" -> true + else -> false + } + private fun extractCall(c: IrCall, callable: Label, stmtExprParent: StmtExprParent) { with("call", c) { val target = tryReplaceSyntheticFunction(c.symbol.owner) @@ -1798,13 +1804,13 @@ open class KotlinFileExtractor( return } - val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.find { it is IrFunction && it.name.asString() == fnName } + val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.findSubType { it.name.asString() == fnName } if (func == null) { logger.errorElement("Couldn't find function $fnName on enum type", c) return } - extractMethodAccess(func as IrFunction, false) + extractMethodAccess(func, false) } fun binopReceiver(id: Label, receiver: IrExpression?, receiverDescription: String) { @@ -2177,8 +2183,20 @@ open class KotlinFileExtractor( extractRawMethodAccess(getter, c, callable, parent, idx, enclosingStmt, listOf(), null, ext, typeArguments) } } - isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> { - findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn -> + isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") -> { + val parentClass = target.parent + if (parentClass !is IrClass) { + logger.errorElement("Iterator parent is not a class", c) + return + } + + var typeFilter = if (isGenericArrayType(parentClass.name.asString())) { + "kotlin.jvm.internal.ArrayIteratorKt" + } else { + "kotlin.jvm.internal.ArrayIteratorsKt" + } + + findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", typeFilter, arrayOf(parentClass.kotlinFqName.asString()), c)?.let { iteratorFn -> val dispatchReceiver = c.dispatchReceiver if (dispatchReceiver == null) { logger.errorElement("No dispatch receiver found for array iterator call", c) @@ -2273,10 +2291,10 @@ open class KotlinFileExtractor( logger.errorElement("Argument to dataClassArrayMemberToString not a class", c) return } - val realCallee = javaUtilArrays?.declarations?.find { decl -> - decl is IrFunction && decl.name.asString() == "toString" && decl.valueParameters.size == 1 && + val realCallee = javaUtilArrays?.declarations?.findSubType { decl -> + decl.name.asString() == "toString" && decl.valueParameters.size == 1 && decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true - } as IrFunction? + } if (realCallee == null) { logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c) } else { @@ -2300,10 +2318,10 @@ open class KotlinFileExtractor( logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c) return } - val realCallee = javaUtilArrays?.declarations?.find { decl -> - decl is IrFunction && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 && + val realCallee = javaUtilArrays?.declarations?.findSubType { decl -> + decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 && decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true - } as IrFunction? + } if (realCallee == null) { logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c) } else { @@ -2486,18 +2504,21 @@ open class KotlinFileExtractor( } } - private fun writeUpdateInPlaceExpr(origin: IrStatementOrigin, tw: TrapWriter, id: Label, type: TypeResults, exprParent: ExprParent): Boolean { + private fun writeUpdateInPlaceExpr(origin: IrStatementOrigin): ((tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int) -> Unit)? { when(origin) { - IrStatementOrigin.PLUSEQ -> tw.writeExprs_assignaddexpr(id.cast(), type.javaResult.id, exprParent.parent, exprParent.idx) - IrStatementOrigin.MINUSEQ -> tw.writeExprs_assignsubexpr(id.cast(), type.javaResult.id, exprParent.parent, exprParent.idx) - IrStatementOrigin.MULTEQ -> tw.writeExprs_assignmulexpr(id.cast(), type.javaResult.id, exprParent.parent, exprParent.idx) - IrStatementOrigin.DIVEQ -> tw.writeExprs_assigndivexpr(id.cast(), type.javaResult.id, exprParent.parent, exprParent.idx) - IrStatementOrigin.PERCEQ -> tw.writeExprs_assignremexpr(id.cast(), type.javaResult.id, exprParent.parent, exprParent.idx) - else -> return false + IrStatementOrigin.PLUSEQ -> return { tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int -> tw.writeExprs_assignaddexpr(id.cast(), type, exprParent, index) } + IrStatementOrigin.MINUSEQ -> return { tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int -> tw.writeExprs_assignsubexpr(id.cast(), type, exprParent, index) } + IrStatementOrigin.MULTEQ -> return { tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int -> tw.writeExprs_assignmulexpr(id.cast(), type, exprParent, index) } + IrStatementOrigin.DIVEQ -> return { tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int -> tw.writeExprs_assigndivexpr(id.cast(), type, exprParent, index) } + IrStatementOrigin.PERCEQ -> return { tw: TrapWriter, id: Label, type: Label, exprParent: Label, index: Int -> tw.writeExprs_assignremexpr(id.cast(), type, exprParent, index) } + else -> return null } - return true } + /** + * This tried to extract a block as an array update. + * It returns true if it succeeds, and false otherwise. + */ private fun tryExtractArrayUpdate(e: IrContainerExpression, callable: Label, parent: StmtExprParent): Boolean { /* * We're expecting the pattern @@ -2517,6 +2538,11 @@ open class KotlinFileExtractor( indexVarDecl.initializer?.let { indexVarInitializer -> (e.statements[2] as? IrCall)?.let { arraySetCall -> if (isFunction(arraySetCall.symbol.owner, "kotlin", "(some array type)", { isArrayType(it) }, "set")) { + val updateRhs = arraySetCall.getValueArgument(1) + if (updateRhs == null) { + logger.errorElement("Update RHS not found", e) + return false + } getUpdateInPlaceRHS( e.origin, // Using e.origin not arraySetCall.origin here distinguishes a compiler-generated block from a user manually code that looks the same. { oldValue -> @@ -2526,8 +2552,19 @@ open class KotlinFileExtractor( receiverVal -> receiverVal.symbol.owner == arrayVarDecl.symbol.owner } ?: false }, - arraySetCall.getValueArgument(1)!! + updateRhs )?.let { updateRhs -> + val origin = e.origin + if (origin == null) { + logger.errorElement("No origin found", e) + return false + } + val writeUpdateInPlaceExprFun = writeUpdateInPlaceExpr(origin) + if (writeUpdateInPlaceExprFun == null) { + logger.errorElement("Unexpected origin", e) + return false + } + // Create an assignment skeleton _ op= _ val exprParent = parent.expr(e, callable) val assignId = tw.getFreshIdLabel() @@ -2538,10 +2575,7 @@ open class KotlinFileExtractor( tw.writeCallableEnclosingExpr(assignId, callable) tw.writeStatementEnclosingExpr(assignId, exprParent.enclosingStmt) - if (!writeUpdateInPlaceExpr(e.origin!!, tw, assignId, type, exprParent)) { - logger.errorElement("Unexpected origin", e) - return false - } + writeUpdateInPlaceExprFun(tw, assignId, type.javaResult.id, exprParent.parent, exprParent.idx) // Extract e1[e2] val lhsId = tw.getFreshIdLabel() @@ -2893,9 +2927,17 @@ open class KotlinFileExtractor( // Check for a desugared in-place update operator, such as "v += e": val inPlaceUpdateRhs = getUpdateInPlaceRHS(e.origin, { it is IrGetValue && it.symbol.owner == e.symbol.owner }, rhsValue) if (inPlaceUpdateRhs != null) { - if (!writeUpdateInPlaceExpr(e.origin!!, tw, id, type, exprParent)) { - logger.errorElement("Unexpected origin", e) + val origin = e.origin + if (origin == null) { + logger.errorElement("No origin for set-value", e) return + } else { + val writeUpdateInPlaceExprFun = writeUpdateInPlaceExpr(origin) + if (writeUpdateInPlaceExprFun == null) { + logger.errorElement("Unexpected origin for set-value", e) + return + } + writeUpdateInPlaceExprFun(tw, id, type.javaResult.id, exprParent.parent, exprParent.idx) } } else { tw.writeExprs_assignexpr(id, type.javaResult.id, exprParent.parent, exprParent.idx) @@ -4428,7 +4470,7 @@ open class KotlinFileExtractor( return } - val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()} + val invokeMethod = functionType.classOrNull?.owner?.declarations?.findSubType { it.name.asString() == OperatorNameConventions.INVOKE.asString()} if (invokeMethod == null) { logger.errorElement("Couldn't find `invoke` method on functional interface.", e) return @@ -4439,7 +4481,7 @@ open class KotlinFileExtractor( logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e) return } - val samMember = typeOwner.declarations.filterIsInstance().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT } + val samMember = typeOwner.declarations.findSubType { it is IrOverridableMember && it.modality == Modality.ABSTRACT } if (samMember == null) { logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e) return @@ -4628,7 +4670,7 @@ open class KotlinFileExtractor( val superCallId = tw.getFreshIdLabel() tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor) - val baseConstructor = baseClass.owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol } + val baseConstructor = baseClass.owner.declarations.findSubType { it.symbol is IrConstructorSymbol } val baseConstructorId = useFunction(baseConstructor as IrFunction) tw.writeHasLocation(superCallId, locId) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt index db25b2b84a7..3869affa5e4 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt @@ -326,11 +326,11 @@ open class KotlinUsesExtractor( if (replacementClass === parentClass) return f return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) { - val result = replacementClass.declarations.find { replacementDecl -> + val result = replacementClass.declarations.findSubType { replacementDecl -> replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all { erase(it.first.type) == erase(it.second.type) } - } as IrFunction? + } if (result == null) { logger.warn("Failed to replace synthetic class function ${f.name}") } else { @@ -351,9 +351,9 @@ open class KotlinUsesExtractor( if (replacementClass === parentClass) return f return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) { - val result = replacementClass.declarations.find { replacementDecl -> - replacementDecl is IrField && replacementDecl.name == f.name - } as IrField? + val result = replacementClass.declarations.findSubType { replacementDecl -> + replacementDecl.name == f.name + } if (result == null) { logger.warn("Failed to replace synthetic class field ${f.name}") } else { @@ -1097,7 +1097,7 @@ open class KotlinUsesExtractor( return f.returnType } - val otherKeySet = parentClass.declarations.filterIsInstance().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 } + val otherKeySet = parentClass.declarations.findSubType { it.name.asString() == "keySet" && it.valueParameters.size == 1 } ?: return f.returnType return otherKeySet.returnType.codeQlWithHasQuestionMark(false) @@ -1177,8 +1177,7 @@ open class KotlinUsesExtractor( getJavaEquivalentClass(parentClass)?.let { javaClass -> if (javaClass != parentClass) // Look for an exact type match... - javaClass.declarations.find { decl -> - decl is IrFunction && + javaClass.declarations.findSubType { decl -> decl.name == f.name && decl.valueParameters.size == f.valueParameters.size && // Note matching by classifier not the whole type so that generic arguments are allowed to differ, @@ -1194,7 +1193,7 @@ open class KotlinUsesExtractor( } ?: // Or check property accessors: if (f.isAccessor) { - val prop = javaClass.declarations.filterIsInstance().find { decl -> + val prop = javaClass.declarations.findSubType { decl -> decl.name == (f.propertyIfAccessor as IrProperty).name } if (prop?.getter?.name == f.name) diff --git a/java/kotlin-extractor/src/main/kotlin/utils/Iterable.kt b/java/kotlin-extractor/src/main/kotlin/utils/Iterable.kt new file mode 100644 index 00000000000..a94a883b171 --- /dev/null +++ b/java/kotlin-extractor/src/main/kotlin/utils/Iterable.kt @@ -0,0 +1,15 @@ +package com.github.codeql + +import org.jetbrains.kotlin.ir.declarations.IrDeclaration + +/** + * This behaves the same as Iterable.find, but requires + * that the value found is of the subtype S, and it casts + * the result for you appropriately. + */ +inline fun Iterable.findSubType( + predicate: (S) -> Boolean +): S? { + return this.find { it is S && predicate(it) } as S? +} + diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/diagnostics.ql old mode 100755 new mode 100644 diff --git a/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql b/java/ql/integration-tests/linux-only/kotlin/custom_plugin/methods.ql old mode 100755 new mode 100644 diff --git a/java/ql/lib/change-notes/2022-08-25-taint-model-spring-crudrepository.md b/java/ql/lib/change-notes/2022-08-25-taint-model-spring-crudrepository.md new file mode 100644 index 00000000000..2d5fce9346f --- /dev/null +++ b/java/ql/lib/change-notes/2022-08-25-taint-model-spring-crudrepository.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added flow summary for `org.springframework.data.repository.CrudRepository.save()`. diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/FileSystem.qll b/java/ql/lib/semmle/code/FileSystem.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/Location.qll b/java/ql/lib/semmle/code/Location.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Annotation.qll b/java/ql/lib/semmle/code/java/Annotation.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/CompilationUnit.qll b/java/ql/lib/semmle/code/java/CompilationUnit.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Dependency.qll b/java/ql/lib/semmle/code/java/Dependency.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Element.qll b/java/ql/lib/semmle/code/java/Element.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Exception.qll b/java/ql/lib/semmle/code/java/Exception.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Generics.qll b/java/ql/lib/semmle/code/java/Generics.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Import.qll b/java/ql/lib/semmle/code/java/Import.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/J2EE.qll b/java/ql/lib/semmle/code/java/J2EE.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/JMX.qll b/java/ql/lib/semmle/code/java/JMX.qll index 16c8736059f..66aa951ba28 100644 --- a/java/ql/lib/semmle/code/java/JMX.qll +++ b/java/ql/lib/semmle/code/java/JMX.qll @@ -27,7 +27,7 @@ class MXBean extends ManagedBean { class RegisteredManagedBeanImpl extends Class { RegisteredManagedBeanImpl() { this.getAnAncestor() instanceof ManagedBean and - exists(JMXRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this) + exists(JmxRegistrationCall registerCall | registerCall.getObjectArgument().getType() = this) } /** @@ -39,32 +39,35 @@ class RegisteredManagedBeanImpl extends Class { /** * A call that registers an object with the `MBeanServer`, directly or indirectly. */ -class JMXRegistrationCall extends MethodAccess { - JMXRegistrationCall() { this.getCallee() instanceof JMXRegistrationMethod } +class JmxRegistrationCall extends MethodAccess { + JmxRegistrationCall() { this.getCallee() instanceof JmxRegistrationMethod } /** * Gets the argument that represents the object in the registration call. */ Expr getObjectArgument() { - result = this.getArgument(this.getCallee().(JMXRegistrationMethod).getObjectPosition()) + result = this.getArgument(this.getCallee().(JmxRegistrationMethod).getObjectPosition()) } } +/** DEPRECATED: Alias for JmxRegistrationCall */ +deprecated class JMXRegistrationCall = JmxRegistrationCall; + /** * A method used to register `MBean` and `MXBean` instances with the `MBeanServer`. * * This is either the `registerMBean` method on `MBeanServer`, or it is a wrapper around that * registration method. */ -class JMXRegistrationMethod extends Method { - JMXRegistrationMethod() { +class JmxRegistrationMethod extends Method { + JmxRegistrationMethod() { // A direct registration with the `MBeanServer`. this.getDeclaringType().hasQualifiedName("javax.management", "MBeanServer") and this.getName() = "registerMBean" or // The `MBeanServer` is often wrapped by an application specific management class, so identify - // methods that wrap a call to another `JMXRegistrationMethod`. - exists(JMXRegistrationCall c | + // methods that wrap a call to another `JmxRegistrationMethod`. + exists(JmxRegistrationCall c | // This must be a call to another JMX registration method, where the object argument is an access // of one of the parameters of this method. c.getObjectArgument().(VarAccess).getVariable() = this.getAParameter() @@ -81,25 +84,37 @@ class JMXRegistrationMethod extends Method { result = 0 or // Identify the position in this method where the object parameter should be passed. - exists(JMXRegistrationCall c | + exists(JmxRegistrationCall c | c.getObjectArgument().(VarAccess).getVariable() = this.getParameter(result) ) } } +/** DEPRECATED: Alias for JmxRegistrationMethod */ +deprecated class JMXRegistrationMethod = JmxRegistrationMethod; + /** The class `javax.management.remote.JMXConnectorFactory`. */ -class TypeJMXConnectorFactory extends Class { - TypeJMXConnectorFactory() { +class TypeJmxConnectorFactory extends Class { + TypeJmxConnectorFactory() { this.hasQualifiedName("javax.management.remote", "JMXConnectorFactory") } } +/** DEPRECATED: Alias for TypeJmxConnectorFactory */ +deprecated class TypeJMXConnectorFactory = TypeJmxConnectorFactory; + /** The class `javax.management.remote.JMXServiceURL`. */ -class TypeJMXServiceURL extends Class { - TypeJMXServiceURL() { this.hasQualifiedName("javax.management.remote", "JMXServiceURL") } +class TypeJmxServiceUrl extends Class { + TypeJmxServiceUrl() { this.hasQualifiedName("javax.management.remote", "JMXServiceURL") } } +/** DEPRECATED: Alias for TypeJmxServiceUrl */ +deprecated class TypeJMXServiceURL = TypeJmxServiceUrl; + /** The class `javax.management.remote.rmi.RMIConnector`. */ -class TypeRMIConnector extends Class { - TypeRMIConnector() { this.hasQualifiedName("javax.management.remote.rmi", "RMIConnector") } +class TypeRmiConnector extends Class { + TypeRmiConnector() { this.hasQualifiedName("javax.management.remote.rmi", "RMIConnector") } } + +/** DEPRECATED: Alias for TypeRmiConnector */ +deprecated class TypeRMIConnector = TypeRmiConnector; diff --git a/java/ql/lib/semmle/code/java/Javadoc.qll b/java/ql/lib/semmle/code/java/Javadoc.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/KotlinType.qll b/java/ql/lib/semmle/code/java/KotlinType.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Modifier.qll b/java/ql/lib/semmle/code/java/Modifier.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Modules.qll b/java/ql/lib/semmle/code/java/Modules.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/NumberFormatException.qll b/java/ql/lib/semmle/code/java/NumberFormatException.qll index f8aab0ba26f..e3b83811cf0 100644 --- a/java/ql/lib/semmle/code/java/NumberFormatException.qll +++ b/java/ql/lib/semmle/code/java/NumberFormatException.qll @@ -15,7 +15,7 @@ private class SpecialMethodAccess extends MethodAccess { this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) } - predicate throwsNFE() { + predicate throwsNfe() { this.isParseMethod("Byte", "parseByte") or this.isParseMethod("Short", "parseShort") or this.isParseMethod("Integer", "parseInt") or @@ -33,6 +33,9 @@ private class SpecialMethodAccess extends MethodAccess { this.isValueOfMethod("Float") or this.isValueOfMethod("Double") } + + /** DEPRECATED: Alias for throwsNfe */ + deprecated predicate throwsNFE() { this.throwsNfe() } } /** A `ClassInstanceExpr` that constructs a number from its string representation. */ @@ -43,7 +46,7 @@ private class SpecialClassInstanceExpr extends ClassInstanceExpr { this.getNumArgument() = 1 } - predicate throwsNFE() { + predicate throwsNfe() { this.isStringConstructor("Byte") or this.isStringConstructor("Short") or this.isStringConstructor("Integer") or @@ -51,6 +54,9 @@ private class SpecialClassInstanceExpr extends ClassInstanceExpr { this.isStringConstructor("Float") or this.isStringConstructor("Double") } + + /** DEPRECATED: Alias for throwsNfe */ + deprecated predicate throwsNFE() { this.throwsNfe() } } /** The class `java.lang.NumberFormatException`. */ @@ -59,7 +65,7 @@ class NumberFormatException extends RefType { } /** Holds if `java.lang.NumberFormatException` is caught. */ -predicate catchesNFE(TryStmt t) { +predicate catchesNfe(TryStmt t) { exists(CatchClause cc, LocalVariableDeclExpr v | t.getACatchClause() = cc and cc.getVariable() = v and @@ -67,7 +73,13 @@ predicate catchesNFE(TryStmt t) { ) } +/** DEPRECATED: Alias for catchesNfe */ +deprecated predicate catchesNFE = catchesNfe/1; + /** Holds if `java.lang.NumberFormatException` can be thrown. */ -predicate throwsNFE(Expr e) { - e.(SpecialClassInstanceExpr).throwsNFE() or e.(SpecialMethodAccess).throwsNFE() +predicate throwsNfe(Expr e) { + e.(SpecialClassInstanceExpr).throwsNfe() or e.(SpecialMethodAccess).throwsNfe() } + +/** DEPRECATED: Alias for throwsNfe */ +deprecated predicate throwsNFE = throwsNfe/1; diff --git a/java/ql/lib/semmle/code/java/Package.qll b/java/ql/lib/semmle/code/java/Package.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Statement.qll b/java/ql/lib/semmle/code/java/Statement.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/Variable.qll b/java/ql/lib/semmle/code/java/Variable.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index d3f0492089d..e33afceb63e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -120,6 +120,7 @@ private module Frameworks { private import semmle.code.java.frameworks.ratpack.RatpackExec private import semmle.code.java.frameworks.spring.SpringCache private import semmle.code.java.frameworks.spring.SpringContext + private import semmle.code.java.frameworks.spring.SpringData private import semmle.code.java.frameworks.spring.SpringHttp private import semmle.code.java.frameworks.spring.SpringUtil private import semmle.code.java.frameworks.spring.SpringUi diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll index fcd4fe90b6d..a6189337751 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll @@ -88,7 +88,7 @@ private class ReverseDnsSource extends RemoteFlowSource { ReverseDnsSource() { // Try not to trigger on `localhost`. exists(MethodAccess m | m = this.asExpr() | - m.getMethod() instanceof ReverseDNSMethod and + m.getMethod() instanceof ReverseDnsMethod and not exists(MethodAccess l | (variableStep(l, m.getQualifier()) or l = m.getQualifier()) and l.getMethod().getName() = "getLocalHost" @@ -221,8 +221,8 @@ class TypeInetAddr extends RefType { } /** A reverse DNS method. */ -class ReverseDNSMethod extends Method { - ReverseDNSMethod() { +class ReverseDnsMethod extends Method { + ReverseDnsMethod() { this.getDeclaringType() instanceof TypeInetAddr and ( this.getName() = "getHostName" or @@ -231,6 +231,9 @@ class ReverseDNSMethod extends Method { } } +/** DEPRECATED: Alias for ReverseDnsMethod */ +deprecated class ReverseDNSMethod = ReverseDnsMethod; + /** Android `Intent` that may have come from a hostile application. */ class AndroidIntentInput extends DataFlow::Node { Type receiverType; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll index 543c392817c..3eedae0159b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll @@ -4,6 +4,7 @@ private import DataFlowUtil private import semmle.code.java.dataflow.InstanceAccess private import semmle.code.java.dataflow.FlowSummary private import semmle.code.java.dispatch.VirtualDispatch as VirtualDispatch +private import semmle.code.java.dispatch.internal.Unification private module DispatchImpl { /** Gets a viable implementation of the target of the given `Call`. */ @@ -115,74 +116,20 @@ private module DispatchImpl { exact = false and exists(RefType t2 | result.asCallable() = VirtualDispatch::viableMethodImpl(def, t.getSourceDeclaration(), t2) and - not failsUnification(t, t2) + not Unification::failsUnification(t, t2) ) or result.asSummarizedCallable() = def ) } - pragma[noinline] - private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) { - contextArgHasType(_, _, t1, _) and t1.getGenericType() = g + private predicate unificationTargetLeft(ParameterizedType t1) { contextArgHasType(_, _, t1, _) } + + private predicate unificationTargetRight(ParameterizedType t2) { + exists(VirtualDispatch::viableMethodImpl(_, _, t2)) } - pragma[noinline] - private predicate unificationTargetRight(ParameterizedType t2, GenericType g) { - exists(VirtualDispatch::viableMethodImpl(_, _, t2)) and t2.getGenericType() = g - } - - private predicate unificationTargets(Type t1, Type t2) { - exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g)) - or - exists(Array a1, Array a2 | - unificationTargets(a1, a2) and - t1 = a1.getComponentType() and - t2 = a2.getComponentType() - ) - or - exists(ParameterizedType pt1, ParameterizedType pt2, int pos | - unificationTargets(pt1, pt2) and - not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and - t1 = pt1.getTypeArgument(pos) and - t2 = pt2.getTypeArgument(pos) - ) - } - - pragma[noinline] - private predicate typeArgsOfUnificationTargets( - ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2 - ) { - unificationTargets(t1, t2) and - arg1 = t1.getTypeArgument(pos) and - arg2 = t2.getTypeArgument(pos) - } - - private predicate failsUnification(Type t1, Type t2) { - unificationTargets(t1, t2) and - ( - exists(RefType arg1, RefType arg2 | - typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and - failsUnification(arg1, arg2) - ) - or - failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType()) - or - not ( - t1 instanceof Array and t2 instanceof Array - or - t1.(PrimitiveType) = t2.(PrimitiveType) - or - t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration() - or - t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration() - or - t1 instanceof BoundedType and t2 instanceof RefType - or - t1 instanceof RefType and t2 instanceof BoundedType - ) - ) - } + private module Unification = MkUnification; private int parameterPosition() { result in [-1, any(Parameter p).getPosition()] } diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll index f0ddffa9aa2..8dbb9bb530e 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll @@ -162,7 +162,7 @@ class LiveClass extends SourceClassOrInterface { exists(LiveField f | f.getDeclaringType() = this | // A `serialVersionUID` field is considered to be a live field, but is // not be enough to be make this class live. - not f instanceof SerialVersionUIDField + not f instanceof SerialVersionUidField ) or // If this is a namespace class, it is live if there is at least one live nested class. @@ -250,7 +250,7 @@ class DeadMethod extends Callable { // These getters and setters are often generated in an ad-hoc way by the developer, which leads to // methods that are theoretically dead, but uninteresting. We therefore ignore them, so long as // they are "simple". - not exists(JPAReadField readField | this.getDeclaringType() = readField.getDeclaringType() | + not exists(JpaReadField readField | this.getDeclaringType() = readField.getDeclaringType() | this.(GetterMethod).getField() = readField or this.(SetterMethod).getField() = readField ) diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll index dcd58987b94..4499c6d63c8 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll @@ -87,8 +87,8 @@ abstract class WhitelistedLiveField extends Field { } * A static, final, long field named `serialVersionUID` in a class that extends `Serializable` acts as * a version number for the serialization framework. */ -class SerialVersionUIDField extends ReflectivelyReadField { - SerialVersionUIDField() { +class SerialVersionUidField extends ReflectivelyReadField { + SerialVersionUidField() { this.hasName("serialVersionUID") and this.isStatic() and this.isFinal() and @@ -97,6 +97,9 @@ class SerialVersionUIDField extends ReflectivelyReadField { } } +/** DEPRECATED: Alias for SerialVersionUidField */ +deprecated class SerialVersionUIDField = SerialVersionUidField; + /** * A field is read by the JAXB during serialization if it is a JAXB bound field, and if the * containing class is considered "live". @@ -154,8 +157,8 @@ class JacksonMixinReflextivelyReadField extends ReflectivelyReadField { /** * A field which is read by a JPA compatible Java persistence framework. */ -class JPAReadField extends ReflectivelyReadField { - JPAReadField() { +class JpaReadField extends ReflectivelyReadField { + JpaReadField() { exists(PersistentEntity entity | this = entity.getAField() and ( @@ -169,3 +172,6 @@ class JPAReadField extends ReflectivelyReadField { ) } } + +/** DEPRECATED: Alias for JpaReadField */ +deprecated class JPAReadField = JpaReadField; diff --git a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll index 4a12730b60f..d6d0653c1ea 100644 --- a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll @@ -128,8 +128,9 @@ class JacksonMixinCallableEntryPoint extends EntryPoint { override Callable getALiveCallable() { result = this } } -class JAXAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedClass { - JAXAnnotationReflectivelyConstructedClass() { +/** A JAX annotation seen as a reflectively constructed class. */ +class JaxAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedClass { + JaxAnnotationReflectivelyConstructedClass() { this instanceof JaxWsEndpoint or this instanceof JaxbXmlRegistry or this instanceof JaxRsResourceClass or @@ -137,6 +138,10 @@ class JAXAnnotationReflectivelyConstructedClass extends ReflectivelyConstructedC } } +/** DEPRECATED: Alias for JaxAnnotationReflectivelyConstructedClass */ +deprecated class JAXAnnotationReflectivelyConstructedClass = + JaxAnnotationReflectivelyConstructedClass; + class DeserializedClass extends ReflectivelyConstructedClass { DeserializedClass() { exists(CastingExpr cast, ReadObjectMethod readObject | @@ -342,8 +347,9 @@ class GsonDeserializationEntryPoint extends ReflectivelyConstructedClass { } } -class JAXBDeserializationEntryPoint extends ReflectivelyConstructedClass { - JAXBDeserializationEntryPoint() { +/** A JAXB deserialization entry point seen as a reflectively constructed class. */ +class JaxbDeserializationEntryPoint extends ReflectivelyConstructedClass { + JaxbDeserializationEntryPoint() { // A class can be deserialized by JAXB if it's an `XmlRootElement`... this.getAnAnnotation().getType().hasQualifiedName("javax.xml.bind.annotation", "XmlRootElement") or @@ -356,6 +362,9 @@ class JAXBDeserializationEntryPoint extends ReflectivelyConstructedClass { } } +/** DEPRECATED: Alias for JaxbDeserializationEntryPoint */ +deprecated class JAXBDeserializationEntryPoint = JaxbDeserializationEntryPoint; + /** * A `javax.annotation` for a method that is called after or before dependency injection on a type. * diff --git a/java/ql/lib/semmle/code/java/deadcode/SpringEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/SpringEntryPoints.qll index 562c7ef7c1c..fd2dc8974f7 100644 --- a/java/ql/lib/semmle/code/java/deadcode/SpringEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/SpringEntryPoints.qll @@ -104,8 +104,8 @@ class SpringAspect extends CallableEntryPoint { /** * Spring Shell provides annotations for identifying methods that contribute CLI commands. */ -class SpringCLI extends CallableEntryPoint { - SpringCLI() { +class SpringCli extends CallableEntryPoint { + SpringCli() { ( hasAnnotation("org.springframework.shell.core.annotation", "CliCommand") or hasAnnotation("org.springframework.shell.core.annotation", "CliAvailabilityIndicator") @@ -116,6 +116,9 @@ class SpringCLI extends CallableEntryPoint { } } +/** DEPRECATED: Alias for SpringCli */ +deprecated class SpringCLI = SpringCli; + /** * An entry point which acts as a remote API for a Flex application to access a Spring application. */ diff --git a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll index 836ad5a1f55..5f2f215802f 100644 --- a/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/WebEntryPoints.qll @@ -58,15 +58,18 @@ class ServletFilterClass extends ReflectivelyConstructedClass { /** * An entry point into a GWT application. */ -class GWTEntryPointConstructedClass extends ReflectivelyConstructedClass { - GWTEntryPointConstructedClass() { this.(GwtEntryPointClass).isLive() } +class GwtEntryPointConstructedClass extends ReflectivelyConstructedClass { + GwtEntryPointConstructedClass() { this.(GwtEntryPointClass).isLive() } } +/** DEPRECATED: Alias for GwtEntryPointConstructedClass */ +deprecated class GWTEntryPointConstructedClass = GwtEntryPointConstructedClass; + /** * Servlets referred to from a GWT module config file. */ -class GWTServletClass extends ReflectivelyConstructedClass { - GWTServletClass() { +class GwtServletClass extends ReflectivelyConstructedClass { + GwtServletClass() { this instanceof ServletClass and // There must be evidence that GWT is being used, otherwise missing `*.gwt.xml` files could cause // all `Servlet`s to be live. @@ -81,6 +84,9 @@ class GWTServletClass extends ReflectivelyConstructedClass { } } +/** DEPRECATED: Alias for GwtServletClass */ +deprecated class GWTServletClass = GwtServletClass; + /** * Methods that may be called reflectively by the UiHandler framework. */ diff --git a/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll b/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll index a05553eb373..29e93f426dc 100644 --- a/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll +++ b/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll @@ -15,6 +15,7 @@ private import semmle.code.java.dataflow.internal.DataFlowUtil private import semmle.code.java.dataflow.internal.DataFlowPrivate private import semmle.code.java.dataflow.internal.ContainerFlow private import semmle.code.java.dataflow.InstanceAccess +private import semmle.code.java.dispatch.internal.Unification /** * Gets a viable dispatch target for `ma`. This is the input dispatch relation. @@ -266,67 +267,10 @@ Method viableImpl_out(MethodAccess ma) { ) } -private module Unification { - pragma[noinline] - private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) { - objectToStringQualType(_, t1) and t1.getGenericType() = g - } +private predicate unificationTargetLeft(ParameterizedType t1) { objectToStringQualType(_, t1) } - pragma[noinline] - private predicate unificationTargetRight(ParameterizedType t2, GenericType g) { - exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g - } - - private predicate unificationTargets(Type t1, Type t2) { - exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g)) - or - exists(Array a1, Array a2 | - unificationTargets(a1, a2) and - t1 = a1.getComponentType() and - t2 = a2.getComponentType() - ) - or - exists(ParameterizedType pt1, ParameterizedType pt2, int pos | - unificationTargets(pt1, pt2) and - not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and - t1 = pt1.getTypeArgument(pos) and - t2 = pt2.getTypeArgument(pos) - ) - } - - pragma[noinline] - private predicate typeArgsOfUnificationTargets( - ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2 - ) { - unificationTargets(t1, t2) and - arg1 = t1.getTypeArgument(pos) and - arg2 = t2.getTypeArgument(pos) - } - - pragma[nomagic] - predicate failsUnification(Type t1, Type t2) { - unificationTargets(t1, t2) and - ( - exists(RefType arg1, RefType arg2 | - typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and - failsUnification(arg1, arg2) - ) - or - failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType()) - or - not ( - t1 instanceof Array and t2 instanceof Array - or - t1.(PrimitiveType) = t2.(PrimitiveType) - or - t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration() - or - t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration() - or - t1 instanceof BoundedType and t2 instanceof RefType - or - t1 instanceof RefType and t2 instanceof BoundedType - ) - ) - } +private predicate unificationTargetRight(ParameterizedType t2) { + exists(viableMethodImpl(_, _, t2)) } + +private module Unification = MkUnification; diff --git a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll index 7d4b617ca19..86bb5bbe8ad 100644 --- a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll +++ b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll @@ -9,6 +9,7 @@ private import DispatchFlow as DispatchFlow private import ObjFlow as ObjFlow private import semmle.code.java.dataflow.internal.BaseSSA private import semmle.code.java.controlflow.Guards +private import semmle.code.java.dispatch.internal.Unification /** * A conservative analysis that returns a single method - if we can establish @@ -91,69 +92,10 @@ private module Dispatch { ) } - private module Unification_v2 { - pragma[noinline] - private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) { - qualType(_, t1, _) and t1.getGenericType() = g - } + private predicate unificationTargetLeft_v2(ParameterizedType t1) { qualType(_, t1, _) } - pragma[noinline] - private predicate unificationTargetRight(ParameterizedType t2, GenericType g) { - exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g - } - - private predicate unificationTargets(Type t1, Type t2) { - exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g)) - or - exists(Array a1, Array a2 | - unificationTargets(a1, a2) and - t1 = a1.getComponentType() and - t2 = a2.getComponentType() - ) - or - exists(ParameterizedType pt1, ParameterizedType pt2, int pos | - unificationTargets(pt1, pt2) and - not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and - t1 = pt1.getTypeArgument(pos) and - t2 = pt2.getTypeArgument(pos) - ) - } - - pragma[noinline] - private predicate typeArgsOfUnificationTargets( - ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2 - ) { - unificationTargets(t1, t2) and - arg1 = t1.getTypeArgument(pos) and - arg2 = t2.getTypeArgument(pos) - } - - predicate failsUnification(Type t1, Type t2) { - unificationTargets(t1, t2) and - ( - exists(RefType arg1, RefType arg2 | - typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and - failsUnification(arg1, arg2) - ) - or - failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType()) - or - not ( - t1 instanceof Array and t2 instanceof Array - or - t1.(PrimitiveType) = t2.(PrimitiveType) - or - t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration() - or - t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration() - or - t1 instanceof BoundedType and t2 instanceof RefType - or - t1 instanceof RefType and t2 instanceof BoundedType - ) - ) - } - } + private module Unification_v2 = + MkUnification; /** * INTERNAL: Use `viableImpl` instead. @@ -203,70 +145,15 @@ private module Dispatch { else result = source.getMethod().getSourceDeclaration() } - private module Unification_v1 { - pragma[noinline] - private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) { - hasQualifierType(_, t1, _) and t1.getGenericType() = g - } + private predicate unificationTargetLeft_v1(ParameterizedType t1) { hasQualifierType(_, t1, _) } - pragma[noinline] - private predicate unificationTargetRight(ParameterizedType t2, GenericType g) { - exists(viableMethodImpl(_, _, t2)) and t2.getGenericType() = g - } - - private predicate unificationTargets(Type t1, Type t2) { - exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g)) - or - exists(Array a1, Array a2 | - unificationTargets(a1, a2) and - t1 = a1.getComponentType() and - t2 = a2.getComponentType() - ) - or - exists(ParameterizedType pt1, ParameterizedType pt2, int pos | - unificationTargets(pt1, pt2) and - not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and - t1 = pt1.getTypeArgument(pos) and - t2 = pt2.getTypeArgument(pos) - ) - } - - pragma[noinline] - private predicate typeArgsOfUnificationTargets( - ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2 - ) { - unificationTargets(t1, t2) and - arg1 = t1.getTypeArgument(pos) and - arg2 = t2.getTypeArgument(pos) - } - - predicate failsUnification(Type t1, Type t2) { - unificationTargets(t1, t2) and - ( - exists(RefType arg1, RefType arg2 | - typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and - failsUnification(arg1, arg2) - ) - or - failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType()) - or - not ( - t1 instanceof Array and t2 instanceof Array - or - t1.(PrimitiveType) = t2.(PrimitiveType) - or - t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration() - or - t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration() - or - t1 instanceof BoundedType and t2 instanceof RefType - or - t1 instanceof RefType and t2 instanceof BoundedType - ) - ) - } + private predicate unificationTargetRight(ParameterizedType t2) { + exists(viableMethodImpl(_, _, t2)) } + private module Unification_v1 = + MkUnification; + private RefType getPreciseType(Expr e) { result = e.(FunctionalExpr).getConstructedType() or diff --git a/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll b/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll new file mode 100644 index 00000000000..46bcc3a2201 --- /dev/null +++ b/java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll @@ -0,0 +1,136 @@ +/** + * Provides a module to check whether two `ParameterizedType`s are unifiable. + */ + +import java + +/** Holds if `t` is a relevant type to consider for unification. */ +signature predicate unificationTarget(ParameterizedType t); + +/** + * Given two sets of parameterised types to consider for unification, returns + * the set of pairs that are not unifiable. + */ +module MkUnification { + pragma[noinline] + private predicate unificationTargetLeft(ParameterizedType t1, GenericType g) { + targetLeft(t1) and t1.getGenericType() = g + } + + pragma[noinline] + private predicate unificationTargetRight(ParameterizedType t2, GenericType g) { + targetRight(t2) and t2.getGenericType() = g + } + + private predicate unificationTargets(Type t1, Type t2) { + exists(GenericType g | unificationTargetLeft(t1, g) and unificationTargetRight(t2, g)) + or + exists(Array a1, Array a2 | + unificationTargets(a1, a2) and + t1 = a1.getComponentType() and + t2 = a2.getComponentType() + ) + or + exists(ParameterizedType pt1, ParameterizedType pt2, int pos | + unificationTargets(pt1, pt2) and + not pt1.getSourceDeclaration() != pt2.getSourceDeclaration() and + t1 = pt1.getTypeArgument(pos) and + t2 = pt2.getTypeArgument(pos) + ) + } + + pragma[noinline] + private predicate typeArgsOfUnificationTargets( + ParameterizedType t1, ParameterizedType t2, int pos, RefType arg1, RefType arg2 + ) { + unificationTargets(t1, t2) and + arg1 = t1.getTypeArgument(pos) and + arg2 = t2.getTypeArgument(pos) + } + + private RefType getUpperBound(RefType t) { + if t instanceof BoundedType + then result = t.(BoundedType).getAnUltimateUpperBoundType() + else result = t + } + + /** + * Holds if `t1` and `t2` are not unifiable. + * + * Restricted to only consider pairs of types such that `targetLeft(t1)`, + * `targetRight(t2)`, and that both are parameterised instances of the same + * generic type. + */ + pragma[nomagic] + predicate failsUnification(Type t1, Type t2) { + unificationTargets(t1, t2) and + ( + exists(RefType arg1, RefType arg2 | + typeArgsOfUnificationTargets(t1, t2, _, arg1, arg2) and + failsUnification(arg1, arg2) + ) + or + failsUnification(t1.(Array).getComponentType(), t2.(Array).getComponentType()) + or + // Can't unify an `extends` bound against a concrete type that doesn't + // descend from that upper bound: + exists(RefType upperbound, RefType other | + t1.(BoundedType).getAnUltimateUpperBoundType().getSourceDeclaration() = upperbound and + t2.(RefType).getSourceDeclaration() = other and + not t2 instanceof BoundedType + or + t2.(BoundedType).getAnUltimateUpperBoundType().getSourceDeclaration() = upperbound and + t1.(RefType).getSourceDeclaration() = other and + not t1 instanceof BoundedType + | + not other.getASourceSupertype*() = upperbound + ) + or + // Can't unify two `extends` bounds that don't intersect: + exists(RefType upperbound1, RefType upperbound2 | + t1.(BoundedType).getAnUltimateUpperBoundType() = upperbound1 and + t2.(BoundedType).getAnUltimateUpperBoundType() = upperbound2 and + notHaveIntersection(upperbound1, upperbound2) + ) + or + // Can't unify `? super X` against `Y` or `_ extends Y` where `Y` isn't an + // ancestor of `X`: + exists(RefType lowerbound, RefType upperbound | + t1.(Wildcard).getLowerBoundType().(RefType).getSourceDeclaration() = lowerbound and + getUpperBound(t2).getSourceDeclaration() = upperbound + or + t2.(Wildcard).getLowerBoundType().(RefType).getSourceDeclaration() = lowerbound and + getUpperBound(t1).getSourceDeclaration() = upperbound + | + not lowerbound instanceof BoundedType and + not lowerbound.getASourceSupertype*() = upperbound + ) + or + // Can't unify `? super T`, where `T` is a type variable `T extends S`, + // with a type that doesn't intersect with `S`: + exists(BoundedType lowerbound, RefType upperbound | + t1.(Wildcard).getLowerBoundType() = lowerbound and + getUpperBound(t2) = upperbound + or + t2.(Wildcard).getLowerBoundType() = lowerbound and + getUpperBound(t1) = upperbound + | + notHaveIntersection(lowerbound.getUpperBoundType(), upperbound) + ) + or + not ( + t1 instanceof Array and t2 instanceof Array + or + t1.(PrimitiveType) = t2.(PrimitiveType) + or + t1.(Class).getSourceDeclaration() = t2.(Class).getSourceDeclaration() + or + t1.(Interface).getSourceDeclaration() = t2.(Interface).getSourceDeclaration() + or + t1 instanceof BoundedType and t2 instanceof RefType + or + t1 instanceof RefType and t2 instanceof BoundedType + ) + ) + } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/Camel.qll b/java/ql/lib/semmle/code/java/frameworks/Camel.qll index c72c884220b..4a1cf58779e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Camel.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Camel.qll @@ -13,7 +13,7 @@ import semmle.code.java.frameworks.camel.CamelJavaAnnotations class CamelToUri extends string { CamelToUri() { exists(SpringCamelXmlToElement toXmlElement | this = toXmlElement.getUri()) or - exists(CamelJavaDSLToDecl toJavaDSL | this = toJavaDSL.getUri()) + exists(CamelJavaDslToDecl toJavaDsl | this = toJavaDsl.getUri()) } } @@ -77,13 +77,13 @@ class CamelTargetClass extends Class { this = xmlMethod.getBeanType() ) or - exists(CamelJavaDSLMethodDecl methodDecl | this = methodDecl.getABean()) + exists(CamelJavaDslMethodDecl methodDecl | this = methodDecl.getABean()) or // Any beans referred to in Java DSL bean or beanRef elements are considered as possible // targets. Whether the route builder is ever constructed or called is not considered. - exists(CamelJavaDSLBeanDecl beanDecl | this = beanDecl.getABeanClass()) + exists(CamelJavaDslBeanDecl beanDecl | this = beanDecl.getABeanClass()) or - exists(CamelJavaDSLBeanRefDecl beanRefDecl | this = beanRefDecl.getABeanClass()) + exists(CamelJavaDslBeanRefDecl beanRefDecl | this = beanRefDecl.getABeanClass()) } /** diff --git a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll index a7ea3aba8aa..8fe204ad846 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JAXB.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JAXB.qll @@ -2,20 +2,26 @@ import semmle.code.java.Type -library class JAXBElement extends Class { - JAXBElement() { +library class JaxbElement extends Class { + JaxbElement() { this.getAnAncestor().getQualifiedName() = "javax.xml.bind.JAXBElement" or this.getAnAnnotation().getType().getName() = "XmlRootElement" } } -library class JAXBMarshalMethod extends Method { - JAXBMarshalMethod() { +/** DEPRECATED: Alias for JaxbElement */ +deprecated class JAXBElement = JaxbElement; + +library class JaxbMarshalMethod extends Method { + JaxbMarshalMethod() { this.getDeclaringType().getQualifiedName() = "javax.xml.bind.Marshaller" and this.getName() = "marshal" } } +/** DEPRECATED: Alias for JaxbMarshalMethod */ +deprecated class JAXBMarshalMethod = JaxbMarshalMethod; + class JaxbAnnotationType extends AnnotationType { JaxbAnnotationType() { this.getPackage().getName() = "javax.xml.bind.annotation" } } diff --git a/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll b/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll index dfa7fd6286a..e19a6b43019 100644 --- a/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll +++ b/java/ql/lib/semmle/code/java/frameworks/UnboundId.qll @@ -58,13 +58,16 @@ class MethodUnboundIdFilterCreate extends Method { } /** A method with the name `createANDFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ -class MethodUnboundIdFilterCreateANDFilter extends Method { - MethodUnboundIdFilterCreateANDFilter() { +class MethodUnboundIdFilterCreateAndFilter extends Method { + MethodUnboundIdFilterCreateAndFilter() { this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and this.hasName("createANDFilter") } } +/** DEPRECATED: Alias for MethodUnboundIdFilterCreateAndFilter */ +deprecated class MethodUnboundIdFilterCreateANDFilter = MethodUnboundIdFilterCreateAndFilter; + /** A method with the name `createORFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ class MethodUnboundIdFilterCreateORFilter extends Method { MethodUnboundIdFilterCreateORFilter() { @@ -73,9 +76,12 @@ class MethodUnboundIdFilterCreateORFilter extends Method { } } +/** DEPRECATED: Alias for MethodUnboundIdFilterCreateNOTFilter */ +deprecated class MethodUnboundIdFilterCreateNOTFilter = MethodUnboundIdFilterCreateNotFilter; + /** A method with the name `createNOTFilter` declared in `com.unboundid.ldap.sdk.Filter`. */ -class MethodUnboundIdFilterCreateNOTFilter extends Method { - MethodUnboundIdFilterCreateNOTFilter() { +class MethodUnboundIdFilterCreateNotFilter extends Method { + MethodUnboundIdFilterCreateNotFilter() { this.getDeclaringType() instanceof TypeUnboundIdLdapFilter and this.hasName("createNOTFilter") } diff --git a/java/ql/lib/semmle/code/java/frameworks/camel/CamelJavaDSL.qll b/java/ql/lib/semmle/code/java/frameworks/camel/CamelJavaDSL.qll index e4b687a73b0..b59f7a94cdb 100644 --- a/java/ql/lib/semmle/code/java/frameworks/camel/CamelJavaDSL.qll +++ b/java/ql/lib/semmle/code/java/frameworks/camel/CamelJavaDSL.qll @@ -35,8 +35,8 @@ library class ProcessorDefinitionElement extends MethodAccess { * * This declares a "target" for this route, described by the URI given as the first argument. */ -class CamelJavaDSLToDecl extends ProcessorDefinitionElement { - CamelJavaDSLToDecl() { getMethod().hasName("to") } +class CamelJavaDslToDecl extends ProcessorDefinitionElement { + CamelJavaDslToDecl() { getMethod().hasName("to") } /** * Gets the URI specified by this `to` declaration. @@ -47,14 +47,17 @@ class CamelJavaDSLToDecl extends ProcessorDefinitionElement { deprecated string getURI() { result = getUri() } } +/** DEPRECATED: Alias for CamelJavaDslToDecl */ +deprecated class CamelJavaDSLToDecl = CamelJavaDslToDecl; + /** * A declaration of a "bean" target in the Apache Camel Java DSL. * * This declares a bean to call for this route. The bean is defined either by a Class reference, * or the bean object itself. */ -class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement { - CamelJavaDSLBeanDecl() { getMethod().hasName("bean") } +class CamelJavaDslBeanDecl extends ProcessorDefinitionElement { + CamelJavaDslBeanDecl() { getMethod().hasName("bean") } /** * Gets a bean class that may be registered as a target by this `bean()` declaration. @@ -71,6 +74,9 @@ class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement { } } +/** DEPRECATED: Alias for CamelJavaDslBeanDecl */ +deprecated class CamelJavaDSLBeanDecl = CamelJavaDslBeanDecl; + /** * A declaration of a "beanRef" target in the Apache Camel Java DSL. * @@ -78,8 +84,8 @@ class CamelJavaDSLBeanDecl extends ProcessorDefinitionElement { * the bean reference is dependent on which registries are used by Apache Camel, but we make the * assumption that it either represetns a qualified name, or a Srping bean identifier. */ -class CamelJavaDSLBeanRefDecl extends ProcessorDefinitionElement { - CamelJavaDSLBeanRefDecl() { getMethod().hasName("beanRef") } +class CamelJavaDslBeanRefDecl extends ProcessorDefinitionElement { + CamelJavaDslBeanRefDecl() { getMethod().hasName("beanRef") } /** * Gets the string describing the bean referred to. @@ -98,13 +104,16 @@ class CamelJavaDSLBeanRefDecl extends ProcessorDefinitionElement { } } +/** DEPRECATED: Alias for CamelJavaDslBeanRefDecl */ +deprecated class CamelJavaDSLBeanRefDecl = CamelJavaDslBeanRefDecl; + /** * A "method" Camel expression in the Apache Camel Java DSL. * * An expression that represents a call to a bean, or particular method on a bean. */ -class CamelJavaDSLMethodDecl extends MethodAccess { - CamelJavaDSLMethodDecl() { +class CamelJavaDslMethodDecl extends MethodAccess { + CamelJavaDslMethodDecl() { getMethod() .getDeclaringType() .getSourceDeclaration() @@ -129,3 +138,6 @@ class CamelJavaDSLMethodDecl extends MethodAccess { else result = getArgument(0).getType() } } + +/** DEPRECATED: Alias for CamelJavaDslMethodDecl */ +deprecated class CamelJavaDSLMethodDecl = CamelJavaDslMethodDecl; diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/Spring.qll b/java/ql/lib/semmle/code/java/frameworks/spring/Spring.qll index cfc318190c4..fd3008e5f00 100644 --- a/java/ql/lib/semmle/code/java/frameworks/spring/Spring.qll +++ b/java/ql/lib/semmle/code/java/frameworks/spring/Spring.qll @@ -13,6 +13,7 @@ import semmle.code.java.frameworks.spring.SpringContext import semmle.code.java.frameworks.spring.SpringComponentScan import semmle.code.java.frameworks.spring.SpringConstructorArg import semmle.code.java.frameworks.spring.SpringController +import semmle.code.java.frameworks.spring.SpringData import semmle.code.java.frameworks.spring.SpringDescription import semmle.code.java.frameworks.spring.SpringEntry import semmle.code.java.frameworks.spring.SpringFlex diff --git a/java/ql/lib/semmle/code/java/frameworks/spring/SpringData.qll b/java/ql/lib/semmle/code/java/frameworks/spring/SpringData.qll new file mode 100644 index 00000000000..52c8579b4c7 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/spring/SpringData.qll @@ -0,0 +1,17 @@ +/** + * Provides classes and predicates for working with Spring classes and interfaces from + * `org.springframework.data`. + */ + +import java +private import semmle.code.java.dataflow.ExternalFlow + +/** + * Provides models for the `org.springframework.data` package. + */ +private class FlowSummaries extends SummaryModelCsv { + override predicate row(string row) { + row = + "org.springframework.data.repository;CrudRepository;true;save;;;Argument[0];ReturnValue;value;manual" + } +} diff --git a/java/ql/lib/semmle/code/java/metrics/MetricCallable.qll b/java/ql/lib/semmle/code/java/metrics/MetricCallable.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricElement.qll b/java/ql/lib/semmle/code/java/metrics/MetricElement.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricField.qll b/java/ql/lib/semmle/code/java/metrics/MetricField.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricPackage.qll b/java/ql/lib/semmle/code/java/metrics/MetricPackage.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll b/java/ql/lib/semmle/code/java/metrics/MetricRefType.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll b/java/ql/lib/semmle/code/java/metrics/MetricStmt.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll index a236d4d8af6..3fe06a2de08 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll @@ -49,7 +49,7 @@ private class Serializable extends ClassStore { /** The instantiation of a marshallable class, which can be stored to disk as XML. */ private class Marshallable extends ClassStore { - Marshallable() { this.getConstructor().getDeclaringType() instanceof JAXBElement } + Marshallable() { this.getConstructor().getDeclaringType() instanceof JaxbElement } /** Gets a store, for example `marshaller.marshal(instance)`. */ override Expr getAStore() { @@ -69,7 +69,7 @@ private Expr getInstanceInput(DataFlow::Node instance, RefType t) { fa.getField().getDeclaringType() = t | t.getASourceSupertype*() instanceof TypeSerializable or - t instanceof JAXBElement + t instanceof JaxbElement ) } @@ -98,7 +98,7 @@ private predicate serializableStore(DataFlow::Node instance, Expr store) { private predicate marshallableStore(DataFlow::Node instance, Expr store) { exists(MethodAccess m | store = m and - m.getMethod() instanceof JAXBMarshalMethod and + m.getMethod() instanceof JaxbMarshalMethod and instance.asExpr() = m.getArgument(0) ) } diff --git a/java/ql/lib/semmle/code/java/security/JndiInjection.qll b/java/ql/lib/semmle/code/java/security/JndiInjection.qll index 543ce2bc859..9dca731af80 100644 --- a/java/ql/lib/semmle/code/java/security/JndiInjection.qll +++ b/java/ql/lib/semmle/code/java/security/JndiInjection.qll @@ -176,7 +176,7 @@ private predicate nameAddStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) { * by calling `new JMXServiceURL(tainted)`. */ private predicate jmxServiceUrlStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) { - exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeJMXServiceURL | + exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeJmxServiceUrl | n1.asExpr() = cc.getAnArgument() and n2.asExpr() = cc ) @@ -189,7 +189,7 @@ private predicate jmxServiceUrlStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2 private predicate jmxConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) { exists(MethodAccess ma, Method m | n1.asExpr() = ma.getArgument(0) and n2.asExpr() = ma | ma.getMethod() = m and - m.getDeclaringType() instanceof TypeJMXConnectorFactory and + m.getDeclaringType() instanceof TypeJmxConnectorFactory and m.hasName("newJMXConnector") ) } @@ -199,7 +199,7 @@ private predicate jmxConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) * `RMIConnector` by calling `new RMIConnector(tainted)`. */ private predicate rmiConnectorStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) { - exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeRMIConnector | + exists(ConstructorCall cc | cc.getConstructedType() instanceof TypeRmiConnector | n1.asExpr() = cc.getAnArgument() and n2.asExpr() = cc ) diff --git a/java/ql/lib/semmle/code/java/security/LdapInjection.qll b/java/ql/lib/semmle/code/java/security/LdapInjection.qll index 54e0dff2eb2..35c59279f4e 100644 --- a/java/ql/lib/semmle/code/java/security/LdapInjection.qll +++ b/java/ql/lib/semmle/code/java/security/LdapInjection.qll @@ -140,8 +140,8 @@ private predicate filterStep(DataFlow::ExprNode n1, DataFlow::ExprNode n2) { ma.getMethod() = m | m instanceof MethodUnboundIdFilterCreate or - m instanceof MethodUnboundIdFilterCreateANDFilter or - m instanceof MethodUnboundIdFilterCreateNOTFilter or + m instanceof MethodUnboundIdFilterCreateAndFilter or + m instanceof MethodUnboundIdFilterCreateNotFilter or m instanceof MethodUnboundIdFilterCreateORFilter or m instanceof MethodUnboundIdFilterSimplifyFilter ) diff --git a/java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll b/java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll index 3a8bf058df8..f83a6411618 100644 --- a/java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll +++ b/java/ql/lib/semmle/code/java/security/OverlyLargeRangeQuery.qll @@ -238,8 +238,13 @@ module RangePrinter { /** Gets a char range that is overly large because of `reason`. */ RegExpCharacterRange getABadRange(string reason, int priority) { + result instanceof OverlyWideRange and priority = 0 and - reason = "is equivalent to " + result.(OverlyWideRange).printEquivalent() + exists(string equiv | equiv = result.(OverlyWideRange).printEquivalent() | + if equiv.length() <= 50 + then reason = "is equivalent to " + equiv + else reason = "is equivalent to " + equiv.substring(0, 50) + "..." + ) or priority = 1 and exists(RegExpCharacterRange other | diff --git a/java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll b/java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll index 000c247fc71..d006837466b 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/ExponentialBackTracking.qll @@ -115,6 +115,7 @@ private newtype TStatePair = private int rankState(State state) { state = rank[result](State s, Location l | + stateInsideBacktracking(s) and l = s.getRepr().getLocation() | s order by l.getStartLine(), l.getStartColumn(), s.toString() diff --git a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll index fdcb10c2f85..033b8aa8cfd 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll @@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm { * Holds if this root term is relevant to the ReDoS analysis. */ predicate isRelevant() { - // there is at least one repetition - getRoot(any(InfiniteRepetitionQuantifier q)) = this and // is actually used as a RegExp this.isUsedAsRegExp() and // not excluded for library specific reasons @@ -877,6 +875,101 @@ predicate isStartState(State state) { */ signature predicate isCandidateSig(State state, string pump); +/** + * Holds if `state` is a candidate for ReDoS. + */ +signature predicate isCandidateSig(State state); + +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +module PrefixConstruction { + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + s = stateInRelevantRegexp() and + isStartState(s) and + getRoot(s.getRepr()) = root and + l = s.getRepr().getLocation() + | + s + order by + l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), + l.getEndLine() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s + order by + loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), + s.getRepr().toString() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = prefix(prev) + getCanonicalEdgeChar(prev, state) + ) + } + + /** + * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. + */ + private string getCanonicalEdgeChar(State prev, State next) { + result = + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) + } + + /** Gets a state within a regular expression that contains a candidate state. */ + pragma[noinline] + State stateInRelevantRegexp() { + exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr())) + } +} + /** * A module for pruning candidate ReDoS states. * The candidates are specified by the `isCandidate` signature predicate. @@ -910,95 +1003,9 @@ module ReDoSPruning { /** Gets a state that can reach the `accept-any` state using only epsilon steps. */ private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) } - /** - * Predicates for constructing a prefix string that leads to a given state. - */ - private module PrefixConstruction { - /** - * Holds if `state` is the textually last start state for the regular expression. - */ - private predicate lastStartState(State state) { - exists(RegExpRoot root | - state = - max(State s, Location l | - s = stateInPumpableRegexp() and - isStartState(s) and - getRoot(s.getRepr()) = root and - l = s.getRepr().getLocation() - | - s - order by - l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), - l.getEndLine() - ) - ) - } + predicate isCandidateState(State s) { isReDoSCandidate(s, _) } - /** - * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. - */ - private predicate existsTransition(State a, State b) { delta(a, _, b) } - - /** - * Gets the minimum number of transitions it takes to reach `state` from the `start` state. - */ - int prefixLength(State start, State state) = - shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) - - /** - * Gets the minimum number of transitions it takes to reach `state` from the start state. - */ - private int lengthFromStart(State state) { result = prefixLength(_, state) } - - /** - * Gets a string for which the regular expression will reach `state`. - * - * Has at most one result for any given `state`. - * This predicate will not always have a result even if there is a ReDoS issue in - * the regular expression. - */ - string prefix(State state) { - lastStartState(state) and - result = "" - or - // the search stops past the last redos candidate state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and - exists(State prev | - // select a unique predecessor (by an arbitrary measure) - prev = - min(State s, Location loc | - lengthFromStart(s) = lengthFromStart(state) - 1 and - loc = s.getRepr().getLocation() and - delta(s, _, state) - | - s - order by - loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), - s.getRepr().toString() - ) - | - // greedy search for the shortest prefix - result = prefix(prev) and delta(prev, Epsilon(), state) - or - not delta(prev, Epsilon(), state) and - result = prefix(prev) + getCanonicalEdgeChar(prev, state) - ) - } - - /** - * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. - */ - private string getCanonicalEdgeChar(State prev, State next) { - result = - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) - } - - /** Gets a state within a regular expression that has a pumpable state. */ - pragma[noinline] - State stateInPumpableRegexp() { - exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) - } - } + import PrefixConstruction as Prefix /** * Predicates for testing the presence of a rejecting suffix. @@ -1018,8 +1025,6 @@ module ReDoSPruning { * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ private module SuffixConstruction { - import PrefixConstruction - /** * Holds if all states reachable from `fork` by repeating `w` * are likely rejectable by appending some suffix. @@ -1036,7 +1041,7 @@ module ReDoSPruning { */ pragma[noinline] private predicate isLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and ( // exists a reject edge with some char. hasRejectEdge(s) @@ -1052,7 +1057,7 @@ module ReDoSPruning { * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. */ predicate isRejectState(State s) { - s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) + s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_) } /** @@ -1060,7 +1065,7 @@ module ReDoSPruning { */ pragma[noopt] predicate hasEdgeToLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | @@ -1076,7 +1081,7 @@ module ReDoSPruning { */ pragma[noinline] private string hasEdgeToLikelyRejectableHelper(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and not hasRejectEdge(s) and not isRejectState(s) and deltaClosedChar(s, result, _) @@ -1088,8 +1093,8 @@ module ReDoSPruning { * `prev` to `next` that the character symbol `char`. */ predicate deltaClosedChar(State prev, string char, State next) { - prev = stateInPumpableRegexp() and - next = stateInPumpableRegexp() and + prev = Prefix::stateInRelevantRegexp() and + next = Prefix::stateInRelevantRegexp() and deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) } @@ -1099,18 +1104,28 @@ module ReDoSPruning { result = getAnInputSymbolMatching(char) } + pragma[noinline] + RegExpRoot relevantRoot() { + exists(RegExpTerm term, State s | + s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm() + ) + } + /** * Gets a char used for finding possible suffixes inside `root`. */ pragma[noinline] private string relevant(RegExpRoot root) { - exists(ascii(result)) and exists(root) - or - exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) - or - // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). - // The three chars must be kept in sync with `hasSimpleRejectEdge`. - result = ["|", "\n", "Z"] and exists(root) + root = relevantRoot() and + ( + exists(ascii(result)) and exists(root) + or + exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + or + // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). + // The three chars must be kept in sync with `hasSimpleRejectEdge`. + result = ["|", "\n", "Z"] and exists(root) + ) } /** @@ -1208,12 +1223,12 @@ module ReDoSPruning { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { isReDoSAttackable(t, pump, s) and ( - prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and - not PrefixConstruction::prefix(s) = "" + prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and + not Prefix::prefix(s) = "" or - PrefixConstruction::prefix(s) = "" and prefixMsg = "" + Prefix::prefix(s) = "" and prefixMsg = "" or - not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + not exists(Prefix::prefix(s)) and prefixMsg = "" ) } diff --git a/java/ql/lib/semmle/code/xml/XML.qll b/java/ql/lib/semmle/code/xml/XML.qll old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/37f33da42d2cffa6ad8b26feaa6beed1c5ce3149/semmlecode.dbscheme b/java/ql/lib/upgrades/37f33da42d2cffa6ad8b26feaa6beed1c5ce3149/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/57c55f404a5954f0e738febf590ad5d49dd67b08/semmlecode.dbscheme b/java/ql/lib/upgrades/57c55f404a5954f0e738febf590ad5d49dd67b08/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/81ccfabe82e696953268e784979262e56871ce86/old.dbscheme b/java/ql/lib/upgrades/81ccfabe82e696953268e784979262e56871ce86/old.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/81ccfabe82e696953268e784979262e56871ce86/semmlecode.dbscheme b/java/ql/lib/upgrades/81ccfabe82e696953268e784979262e56871ce86/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/89a76edebff191538968a6b25d22ada661ffa59a/semmlecode.dbscheme b/java/ql/lib/upgrades/89a76edebff191538968a6b25d22ada661ffa59a/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/b9225587bc0a643ae484ec215b9a6f19d17d0fc2/old.dbscheme b/java/ql/lib/upgrades/b9225587bc0a643ae484ec215b9a6f19d17d0fc2/old.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/b9225587bc0a643ae484ec215b9a6f19d17d0fc2/semmlecode.dbscheme b/java/ql/lib/upgrades/b9225587bc0a643ae484ec215b9a6f19d17d0fc2/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/lib/upgrades/cf58c7d9b1fa1eae9cdc20ce8f157c140ac0c3de/semmlecode.dbscheme b/java/ql/lib/upgrades/cf58c7d9b1fa1eae9cdc20ce8f157c140ac0c3de/semmlecode.dbscheme old mode 100755 new mode 100644 diff --git a/java/ql/src/DeadCode/UselessParameter.ql b/java/ql/src/DeadCode/UselessParameter.ql index 71e9d2606fa..3d29c8faf10 100644 --- a/java/ql/src/DeadCode/UselessParameter.ql +++ b/java/ql/src/DeadCode/UselessParameter.ql @@ -14,4 +14,4 @@ import semmle.code.java.deadcode.DeadCode from RootdefCallable c where not c.whitelisted() -select c.unusedParameter() as p, "The parameter " + p + " is unused." +select c.unusedParameter() as p, "The parameter '" + p + "' is never used." diff --git a/java/ql/src/Likely Bugs/Comparison/BitwiseSignCheck.ql b/java/ql/src/Likely Bugs/Comparison/BitwiseSignCheck.ql index 4ed6845c70e..4ef249524a6 100644 --- a/java/ql/src/Likely Bugs/Comparison/BitwiseSignCheck.ql +++ b/java/ql/src/Likely Bugs/Comparison/BitwiseSignCheck.ql @@ -16,4 +16,4 @@ where e.isStrict() and e.getGreaterOperand() instanceof BitwiseExpr and e.getLesserOperand().(IntegerLiteral).getIntValue() = 0 -select e, "Sign check of a bitwise operation." +select e, "Potentially unsafe sign check of a bitwise operation." diff --git a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql index 346b21bb847..0b8b1b9098b 100644 --- a/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/MissingInstanceofInEquals.ql @@ -77,4 +77,4 @@ where // Exclude `equals` methods that implement reference-equality. not m instanceof ReferenceEquals and not m instanceof UnimplementedEquals -select m, "equals() method does not seem to check argument type." +select m, "equals() method does not check argument type." diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 50dfe9d725a..576b0820e0a 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/java/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -19,4 +19,5 @@ import DataFlow::PathGraph from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink where queryTaintedBy(query, source, sink) -select query, source, sink, "Query might include code from $@.", source.getNode(), "this user input" +select query, source, sink, "This SQL query depends on $@.", source.getNode(), + "a user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-611/XXE.ql b/java/ql/src/Security/CWE/CWE-611/XXE.ql index b50c9c7fef8..d00480a815d 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXE.ql +++ b/java/ql/src/Security/CWE/CWE-611/XXE.ql @@ -51,5 +51,6 @@ class XxeConfig extends TaintTracking::Configuration { from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf where conf.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(), - "user input" +select sink.getNode(), source, sink, + "A $@ is parsed as XML without guarding against external entity expansion.", source.getNode(), + "user-provided value" diff --git a/java/ql/src/Violations of Best Practice/Comments/TodoComments.ql b/java/ql/src/Violations of Best Practice/Comments/TodoComments.ql index 37ec6695a51..ef0b604ac5e 100644 --- a/java/ql/src/Violations of Best Practice/Comments/TodoComments.ql +++ b/java/ql/src/Violations of Best Practice/Comments/TodoComments.ql @@ -17,4 +17,4 @@ from JavadocText c where c.getText().matches("%TODO%") or c.getText().matches("%FIXME%") -select c, "TODO/FIXME comment." +select c, "TODO comments should be addressed." diff --git a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql index ccca6818ad1..582e109e35e 100644 --- a/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql +++ b/java/ql/src/Violations of Best Practice/Dead Code/DeadStoreOfLocalUnread.ql @@ -21,4 +21,4 @@ where read(v) and not def.(AssignExpr).getSource() instanceof NullLiteral and (def instanceof Assignment or def.(UnaryAssignExpr).getParent() instanceof ExprStmt) -select def, "This assignment to " + v.getName() + " is useless: the value is never read." +select def, "This definition of " + v.getName() + " is never used." diff --git a/java/ql/src/Violations of Best Practice/Dead Code/NonAssignedFields.ql b/java/ql/src/Violations of Best Practice/Dead Code/NonAssignedFields.ql index 6c32937a2a9..3e1d7cfd135 100644 --- a/java/ql/src/Violations of Best Practice/Dead Code/NonAssignedFields.ql +++ b/java/ql/src/Violations of Best Practice/Dead Code/NonAssignedFields.ql @@ -86,5 +86,6 @@ where ) and // Exclude special VM classes. not isVMObserver(f.getDeclaringType()) -select f, "Field " + f.getName() + " never assigned non-null value, yet it is read at $@.", fr, - fr.getFile().getStem() + ".java:" + fr.getLocation().getStartLine() +select f, + "The field '" + f.getName() + "' is never explicitly assigned a value, yet it is read $@.", fr, + "here" diff --git a/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql b/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql index 2b48745a01c..6a7928b4561 100644 --- a/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql +++ b/java/ql/src/Violations of Best Practice/Exception Handling/NumberFormatException.ql @@ -15,10 +15,10 @@ import semmle.code.java.NumberFormatException from Expr e where - throwsNFE(e) and + throwsNfe(e) and not exists(TryStmt t | t.getBlock() = e.getEnclosingStmt().getEnclosingStmt*() and - catchesNFE(t) + catchesNfe(t) ) and not exists(Callable c | e.getEnclosingCallable() = c and diff --git a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql index 33fe1cdb46d..84bc421ee66 100644 --- a/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql +++ b/java/ql/src/Violations of Best Practice/Implementation Hiding/StaticArray.ql @@ -41,4 +41,4 @@ where f.getType() instanceof Array and f.fromSource() and forall(AssignExpr a | a.getDest() = f.getAnAccess() | nonEmptyArrayLiteralOrNull(a.getSource())) -select f, "The array constant " + f.getName() + " is vulnerable to mutation." +select f, "The array constant '" + f.getName() + "' is vulnerable to mutation." diff --git a/java/ql/src/Violations of Best Practice/legacy/UnnecessaryImport.ql b/java/ql/src/Violations of Best Practice/legacy/UnnecessaryImport.ql index 096cd8b551f..04b7c9f2516 100644 --- a/java/ql/src/Violations of Best Practice/legacy/UnnecessaryImport.ql +++ b/java/ql/src/Violations of Best Practice/legacy/UnnecessaryImport.ql @@ -71,4 +71,4 @@ where not neededImport(i) and not i instanceof ImportStaticOnDemand and not i instanceof ImportStaticTypeMember -select i, "The statement '" + i + "' is unnecessary." +select i, "Import of '" + i + "' is not used." diff --git a/java/ql/src/change-notes/2022-08-23-alert-messages.md b/java/ql/src/change-notes/2022-08-23-alert-messages.md new file mode 100644 index 00000000000..22f4c5c6682 --- /dev/null +++ b/java/ql/src/change-notes/2022-08-23-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to make the message consistent with other languages. \ No newline at end of file diff --git a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql index f917936a33f..4510bbbc869 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -117,12 +117,12 @@ predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) { } /** Holds if a DSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ -predicate hasShortDSAKeyPair(MethodAccess ma, string msg) { +predicate hasShortDsaKeyPair(MethodAccess ma, string msg) { hasShortAsymmetricKeyPair(ma, msg, "DSA") or hasShortAsymmetricKeyPair(ma, msg, "DH") } /** Holds if a RSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */ -predicate hasShortRSAKeyPair(MethodAccess ma, string msg) { +predicate hasShortRsaKeyPair(MethodAccess ma, string msg) { hasShortAsymmetricKeyPair(ma, msg, "RSA") } @@ -147,7 +147,7 @@ predicate hasShortECKeyPair(MethodAccess ma, string msg) { from Expr e, string msg where hasShortAESKey(e, msg) or - hasShortDSAKeyPair(e, msg) or - hasShortRSAKeyPair(e, msg) or + hasShortDsaKeyPair(e, msg) or + hasShortRsaKeyPair(e, msg) or hasShortECKeyPair(e, msg) select e, msg diff --git a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql index 864692ed8b6..d61119fc853 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql @@ -48,4 +48,4 @@ where ) or hasEmbeddedPassword(nameAttr.getValue().trim()) // Attribute value matches password pattern -select nameAttr, "Plaintext password in configuration file." +select nameAttr, "Avoid plaintext passwords in configuration files." diff --git a/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql b/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql index 3b8b5dc759a..f60e5d9070b 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-730/RegexInjection.ql @@ -85,5 +85,5 @@ class RegexInjectionConfiguration extends TaintTracking::Configuration { from DataFlow::PathNode source, DataFlow::PathNode sink, RegexInjectionConfiguration c where c.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ is user controlled.", source.getNode(), - "This regular expression pattern" +select sink.getNode(), source, sink, "This regular expression is constructed from a $@.", + source.getNode(), "user-provided value" diff --git a/java/ql/src/experimental/Security/CWE/CWE-755/NFEAndroidDoS.ql b/java/ql/src/experimental/Security/CWE/CWE-755/NFEAndroidDoS.ql index b737c460fa9..9793430a2ee 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-755/NFEAndroidDoS.ql +++ b/java/ql/src/experimental/Security/CWE/CWE-755/NFEAndroidDoS.ql @@ -21,8 +21,8 @@ import DataFlow::PathGraph /** * Taint configuration tracking flow from untrusted inputs to number conversion calls in exported Android compononents. */ -class NFELocalDoSConfiguration extends TaintTracking::Configuration { - NFELocalDoSConfiguration() { this = "NFELocalDoSConfiguration" } +class NfeLocalDoSConfiguration extends TaintTracking::Configuration { + NfeLocalDoSConfiguration() { this = "NFELocalDoSConfiguration" } /** Holds if source is a remote flow source */ override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -31,17 +31,17 @@ class NFELocalDoSConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { exists(Expr e | e.getEnclosingCallable().getDeclaringType().(ExportableAndroidComponent).isExported() and - throwsNFE(e) and + throwsNfe(e) and not exists(TryStmt t | t.getBlock() = e.getAnEnclosingStmt() and - catchesNFE(t) + catchesNfe(t) ) and sink.asExpr() = e ) } } -from DataFlow::PathNode source, DataFlow::PathNode sink, NFELocalDoSConfiguration conf +from DataFlow::PathNode source, DataFlow::PathNode sink, NfeLocalDoSConfiguration conf where conf.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Uncaught NumberFormatException in an exported Android component due to $@.", source.getNode(), diff --git a/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java b/java/ql/test/experimental/query-tests/security/CWE-094/ScriptEngineTest.java old mode 100755 new mode 100644 diff --git a/java/ql/test/experimental/query-tests/security/CWE-200/AndroidManifest.xml b/java/ql/test/experimental/query-tests/security/CWE-200/AndroidManifest.xml old mode 100755 new mode 100644 diff --git a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected index fac44a3c2ec..c6e5515918f 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-555/PasswordInConfigurationFile.expected @@ -1,3 +1,3 @@ -| applicationContext.xml:9:3:9:48 | name=password | Plaintext password in configuration file. | -| context.xml:4:2:8:50 | password=1234 | Plaintext password in configuration file. | -| custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Plaintext password in configuration file. | +| applicationContext.xml:9:3:9:48 | name=password | Avoid plaintext passwords in configuration files. | +| context.xml:4:2:8:50 | password=1234 | Avoid plaintext passwords in configuration files. | +| custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Avoid plaintext passwords in configuration files. | diff --git a/java/ql/test/experimental/query-tests/security/CWE-730/RegexInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-730/RegexInjection.expected index 375b65d88b0..a795f1591ad 100644 --- a/java/ql/test/experimental/query-tests/security/CWE-730/RegexInjection.expected +++ b/java/ql/test/experimental/query-tests/security/CWE-730/RegexInjection.expected @@ -56,18 +56,18 @@ nodes subpaths | RegexInjection.java:68:36:68:42 | pattern : String | RegexInjection.java:71:14:71:23 | str : String | RegexInjection.java:72:12:72:14 | str : String | RegexInjection.java:68:32:68:43 | foo(...) : String | #select -| RegexInjection.java:16:26:16:47 | ... + ... | RegexInjection.java:13:22:13:52 | getParameter(...) : String | RegexInjection.java:16:26:16:47 | ... + ... | $@ is user controlled. | RegexInjection.java:13:22:13:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:23:24:23:30 | pattern | RegexInjection.java:20:22:20:52 | getParameter(...) : String | RegexInjection.java:23:24:23:30 | pattern | $@ is user controlled. | RegexInjection.java:20:22:20:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:30:31:30:37 | pattern | RegexInjection.java:27:22:27:52 | getParameter(...) : String | RegexInjection.java:30:31:30:37 | pattern | $@ is user controlled. | RegexInjection.java:27:22:27:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:37:29:37:35 | pattern | RegexInjection.java:34:22:34:52 | getParameter(...) : String | RegexInjection.java:37:29:37:35 | pattern | $@ is user controlled. | RegexInjection.java:34:22:34:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:44:34:44:40 | pattern | RegexInjection.java:41:22:41:52 | getParameter(...) : String | RegexInjection.java:44:34:44:40 | pattern | $@ is user controlled. | RegexInjection.java:41:22:41:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:54:28:54:34 | pattern | RegexInjection.java:51:22:51:52 | getParameter(...) : String | RegexInjection.java:54:28:54:34 | pattern | $@ is user controlled. | RegexInjection.java:51:22:51:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:61:28:61:34 | pattern | RegexInjection.java:58:22:58:52 | getParameter(...) : String | RegexInjection.java:61:28:61:34 | pattern | $@ is user controlled. | RegexInjection.java:58:22:58:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:68:26:68:52 | ... + ... | RegexInjection.java:65:22:65:52 | getParameter(...) : String | RegexInjection.java:68:26:68:52 | ... + ... | $@ is user controlled. | RegexInjection.java:65:22:65:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:90:26:90:47 | ... + ... | RegexInjection.java:84:22:84:52 | getParameter(...) : String | RegexInjection.java:90:26:90:47 | ... + ... | $@ is user controlled. | RegexInjection.java:84:22:84:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:103:40:103:46 | pattern | RegexInjection.java:100:22:100:52 | getParameter(...) : String | RegexInjection.java:103:40:103:46 | pattern | $@ is user controlled. | RegexInjection.java:100:22:100:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:110:42:110:48 | pattern | RegexInjection.java:107:22:107:52 | getParameter(...) : String | RegexInjection.java:110:42:110:48 | pattern | $@ is user controlled. | RegexInjection.java:107:22:107:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:117:44:117:50 | pattern | RegexInjection.java:114:22:114:52 | getParameter(...) : String | RegexInjection.java:117:44:117:50 | pattern | $@ is user controlled. | RegexInjection.java:114:22:114:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:124:41:124:47 | pattern | RegexInjection.java:121:22:121:52 | getParameter(...) : String | RegexInjection.java:124:41:124:47 | pattern | $@ is user controlled. | RegexInjection.java:121:22:121:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:131:43:131:49 | pattern | RegexInjection.java:128:22:128:52 | getParameter(...) : String | RegexInjection.java:131:43:131:49 | pattern | $@ is user controlled. | RegexInjection.java:128:22:128:52 | getParameter(...) | This regular expression pattern | -| RegexInjection.java:146:45:146:51 | pattern | RegexInjection.java:143:22:143:52 | getParameter(...) : String | RegexInjection.java:146:45:146:51 | pattern | $@ is user controlled. | RegexInjection.java:143:22:143:52 | getParameter(...) | This regular expression pattern | +| RegexInjection.java:16:26:16:47 | ... + ... | RegexInjection.java:13:22:13:52 | getParameter(...) : String | RegexInjection.java:16:26:16:47 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:13:22:13:52 | getParameter(...) | user-provided value | +| RegexInjection.java:23:24:23:30 | pattern | RegexInjection.java:20:22:20:52 | getParameter(...) : String | RegexInjection.java:23:24:23:30 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:20:22:20:52 | getParameter(...) | user-provided value | +| RegexInjection.java:30:31:30:37 | pattern | RegexInjection.java:27:22:27:52 | getParameter(...) : String | RegexInjection.java:30:31:30:37 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:27:22:27:52 | getParameter(...) | user-provided value | +| RegexInjection.java:37:29:37:35 | pattern | RegexInjection.java:34:22:34:52 | getParameter(...) : String | RegexInjection.java:37:29:37:35 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:34:22:34:52 | getParameter(...) | user-provided value | +| RegexInjection.java:44:34:44:40 | pattern | RegexInjection.java:41:22:41:52 | getParameter(...) : String | RegexInjection.java:44:34:44:40 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:41:22:41:52 | getParameter(...) | user-provided value | +| RegexInjection.java:54:28:54:34 | pattern | RegexInjection.java:51:22:51:52 | getParameter(...) : String | RegexInjection.java:54:28:54:34 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:51:22:51:52 | getParameter(...) | user-provided value | +| RegexInjection.java:61:28:61:34 | pattern | RegexInjection.java:58:22:58:52 | getParameter(...) : String | RegexInjection.java:61:28:61:34 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:58:22:58:52 | getParameter(...) | user-provided value | +| RegexInjection.java:68:26:68:52 | ... + ... | RegexInjection.java:65:22:65:52 | getParameter(...) : String | RegexInjection.java:68:26:68:52 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:65:22:65:52 | getParameter(...) | user-provided value | +| RegexInjection.java:90:26:90:47 | ... + ... | RegexInjection.java:84:22:84:52 | getParameter(...) : String | RegexInjection.java:90:26:90:47 | ... + ... | This regular expression is constructed from a $@. | RegexInjection.java:84:22:84:52 | getParameter(...) | user-provided value | +| RegexInjection.java:103:40:103:46 | pattern | RegexInjection.java:100:22:100:52 | getParameter(...) : String | RegexInjection.java:103:40:103:46 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:100:22:100:52 | getParameter(...) | user-provided value | +| RegexInjection.java:110:42:110:48 | pattern | RegexInjection.java:107:22:107:52 | getParameter(...) : String | RegexInjection.java:110:42:110:48 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:107:22:107:52 | getParameter(...) | user-provided value | +| RegexInjection.java:117:44:117:50 | pattern | RegexInjection.java:114:22:114:52 | getParameter(...) : String | RegexInjection.java:117:44:117:50 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:114:22:114:52 | getParameter(...) | user-provided value | +| RegexInjection.java:124:41:124:47 | pattern | RegexInjection.java:121:22:121:52 | getParameter(...) : String | RegexInjection.java:124:41:124:47 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:121:22:121:52 | getParameter(...) | user-provided value | +| RegexInjection.java:131:43:131:49 | pattern | RegexInjection.java:128:22:128:52 | getParameter(...) : String | RegexInjection.java:131:43:131:49 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:128:22:128:52 | getParameter(...) | user-provided value | +| RegexInjection.java:146:45:146:51 | pattern | RegexInjection.java:143:22:143:52 | getParameter(...) : String | RegexInjection.java:146:45:146:51 | pattern | This regular expression is constructed from a $@. | RegexInjection.java:143:22:143:52 | getParameter(...) | user-provided value | diff --git a/java/ql/test/experimental/query-tests/security/CWE-755/AndroidManifest.xml b/java/ql/test/experimental/query-tests/security/CWE-755/AndroidManifest.xml old mode 100755 new mode 100644 diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected new file mode 100644 index 00000000000..cd1884eb00e --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.expected @@ -0,0 +1,6 @@ +| arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt | +| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt | +| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt | +| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt | +| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt | diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt new file mode 100644 index 00000000000..45a49b80097 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.kt @@ -0,0 +1,13 @@ +fun test( + a: Array, + b: IntArray, + c: BooleanArray) { + + for (i in a) { } + for (i in b) { } + for (i in c) { } + + val i1 = a.iterator() + val i2 = b.iterator() + val i3 = c.iterator() +} diff --git a/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql new file mode 100644 index 00000000000..442e454424a --- /dev/null +++ b/java/ql/test/kotlin/library-tests/arrays/arrayIterators.ql @@ -0,0 +1,10 @@ +import java + +query predicate iterator(MethodAccess ma, string mn, string t) { + exists(Method m | + ma.getMethod() = m and + m.getName() = "iterator" and + mn = m.getSignature() and + t = ma.getMethod().getDeclaringType().getQualifiedName() + ) +} diff --git a/java/ql/test/kotlin/library-tests/arrays/test.expected b/java/ql/test/kotlin/library-tests/arrays/test.expected index 8ef00e41d6f..7693b3acd6b 100644 --- a/java/ql/test/kotlin/library-tests/arrays/test.expected +++ b/java/ql/test/kotlin/library-tests/arrays/test.expected @@ -18,6 +18,7 @@ sourceSignatures | arrayCreations.kt:27:24:27:38 | invoke | invoke(int) | | arrayGetsSets.kt:1:1:22:1 | arrayGetSet | arrayGetSet(int[],short[],byte[],long[],float[],double[],boolean[],char[],java.lang.Object[]) | | arrayGetsSets.kt:24:1:41:1 | arrayGetSetInPlace | arrayGetSetInPlace(int[],long[],float[],double[]) | +| arrayIterators.kt:1:1:13:1 | test | test(java.lang.Integer[],int[],boolean[]) | | primitiveArrays.kt:3:1:7:1 | Test | Test() | | primitiveArrays.kt:5:3:5:123 | test | test(java.lang.Integer[],java.lang.Integer[],int[],java.lang.Integer[][],java.lang.Integer[][],int[][]) | #select diff --git a/java/ql/test/library-tests/frameworks/spring/data/Test.java b/java/ql/test/library-tests/frameworks/spring/data/Test.java new file mode 100644 index 00000000000..e23fc652692 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/data/Test.java @@ -0,0 +1,19 @@ +import org.springframework.data.repository.CrudRepository; + +class Struct { + public String field; + public Struct(String f){ + this.field = f; + } +} + +public class Test { + String source() { return null; } + void sink(Object o) {} + + void testCrudRepository(CrudRepository cr) { + Struct s = new Struct(source()); + s = cr.save(s); + sink(s.field); //$hasValueFlow + } +} diff --git a/java/ql/test/library-tests/frameworks/spring/data/options b/java/ql/test/library-tests/frameworks/spring/data/options new file mode 100644 index 00000000000..4bbebb24131 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/data/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/spring-data-commons-2.5.1 diff --git a/swift/integration-tests/osx-only/frontend-invocations/A.swift b/java/ql/test/library-tests/frameworks/spring/data/test.expected similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/A.swift rename to java/ql/test/library-tests/frameworks/spring/data/test.expected diff --git a/java/ql/test/library-tests/frameworks/spring/data/test.ql b/java/ql/test/library-tests/frameworks/spring/data/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/spring/data/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected b/java/ql/test/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected index 3bedb52a4a8..fd1fbd7ede5 100644 --- a/java/ql/test/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected +++ b/java/ql/test/query-tests/MissingInstanceofInEquals/MissingInstanceofInEquals.expected @@ -1 +1 @@ -| Bad.java:13:17:13:22 | equals | equals() method does not seem to check argument type. | +| Bad.java:13:17:13:22 | equals | equals() method does not check argument type. | diff --git a/java/ql/test/query-tests/StaticArray/StaticArray.expected b/java/ql/test/query-tests/StaticArray/StaticArray.expected index 5eb4b7510af..69b16f41515 100644 --- a/java/ql/test/query-tests/StaticArray/StaticArray.expected +++ b/java/ql/test/query-tests/StaticArray/StaticArray.expected @@ -1,5 +1,5 @@ -| StaticArray.java:3:31:3:33 | bad | The array constant bad is vulnerable to mutation. | -| StaticArray.java:14:35:14:54 | bad_multidimensional | The array constant bad_multidimensional is vulnerable to mutation. | -| StaticArray.java:15:35:15:67 | bad_multidimensional_partial_init | The array constant bad_multidimensional_partial_init is vulnerable to mutation. | -| StaticArray.java:17:31:17:47 | bad_separate_init | The array constant bad_separate_init is vulnerable to mutation. | -| StaticArray.java:26:33:26:44 | bad_nonempty | The array constant bad_nonempty is vulnerable to mutation. | +| StaticArray.java:3:31:3:33 | bad | The array constant 'bad' is vulnerable to mutation. | +| StaticArray.java:14:35:14:54 | bad_multidimensional | The array constant 'bad_multidimensional' is vulnerable to mutation. | +| StaticArray.java:15:35:15:67 | bad_multidimensional_partial_init | The array constant 'bad_multidimensional_partial_init' is vulnerable to mutation. | +| StaticArray.java:17:31:17:47 | bad_separate_init | The array constant 'bad_separate_init' is vulnerable to mutation. | +| StaticArray.java:26:33:26:44 | bad_nonempty | The array constant 'bad_nonempty' is vulnerable to mutation. | diff --git a/java/ql/test/query-tests/UnreadLocal/DeadStoreOfLocalUnread.expected b/java/ql/test/query-tests/UnreadLocal/DeadStoreOfLocalUnread.expected index e3434efd564..449d0da340f 100644 --- a/java/ql/test/query-tests/UnreadLocal/DeadStoreOfLocalUnread.expected +++ b/java/ql/test/query-tests/UnreadLocal/DeadStoreOfLocalUnread.expected @@ -1,2 +1,2 @@ -| A.java:29:13:29:21 | ...=... | This assignment to x is useless: the value is never read. | -| UnreadLocal/ImplicitReads.java:38:5:38:9 | ...=... | This assignment to c is useless: the value is never read. | +| A.java:29:13:29:21 | ...=... | This definition of x is never used. | +| UnreadLocal/ImplicitReads.java:38:5:38:9 | ...=... | This definition of c is never used. | diff --git a/java/ql/test/query-tests/dead-code/UselessParameter/UselessParameter.expected b/java/ql/test/query-tests/dead-code/UselessParameter/UselessParameter.expected index 5100c651a2b..07f2c07fc55 100644 --- a/java/ql/test/query-tests/dead-code/UselessParameter/UselessParameter.expected +++ b/java/ql/test/query-tests/dead-code/UselessParameter/UselessParameter.expected @@ -1 +1 @@ -| Test.java:6:11:6:15 | x | The parameter x is unused. | +| Test.java:6:11:6:15 | x | The parameter 'x' is never used. | diff --git a/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-266/AndroidManifest.xml old mode 100755 new mode 100644 diff --git a/java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-502/AndroidManifest.xml old mode 100755 new mode 100644 diff --git a/java/ql/test/query-tests/security/CWE-611/XXE.expected b/java/ql/test/query-tests/security/CWE-611/XXE.expected index 6bbb246cb6a..993a6012273 100644 --- a/java/ql/test/query-tests/security/CWE-611/XXE.expected +++ b/java/ql/test/query-tests/security/CWE-611/XXE.expected @@ -251,101 +251,101 @@ nodes | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | semmle.label | getInputStream(...) | subpaths #select -| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | user input | -| DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) | user input | -| DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user input | -| DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user input | -| SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | user input | -| SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | user input | -| SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:13:18:13:38 | getInputStream(...) | user input | -| SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:30:18:30:38 | getInputStream(...) | user input | -| SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:38:18:38:38 | getInputStream(...) | user input | -| SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:46:18:46:38 | getInputStream(...) | user input | -| SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user input | -| SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user input | -| SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user input | -| SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user input | -| SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user input | -| SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user input | -| SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | user input | -| SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | user input | -| SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | user input | -| SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | Unsafe parsing of XML file from $@. | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | user input | -| SAXSourceTests.java:20:18:20:23 | source | SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:20:18:20:23 | source | Unsafe parsing of XML file from $@. | SAXSourceTests.java:17:62:17:82 | getInputStream(...) | user input | -| SchemaTests.java:12:39:12:77 | new StreamSource(...) | SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:12:56:12:76 | getInputStream(...) | user input | -| SchemaTests.java:25:39:25:77 | new StreamSource(...) | SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:25:56:25:76 | getInputStream(...) | user input | -| SchemaTests.java:31:39:31:77 | new StreamSource(...) | SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:31:56:31:76 | getInputStream(...) | user input | -| SchemaTests.java:38:39:38:77 | new StreamSource(...) | SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:38:56:38:76 | getInputStream(...) | user input | -| SchemaTests.java:45:39:45:77 | new StreamSource(...) | SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) | Unsafe parsing of XML file from $@. | SchemaTests.java:45:56:45:76 | getInputStream(...) | user input | -| SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | user input | -| SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | user input | -| SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) | user input | -| SimpleXMLTests.java:31:41:31:53 | new String(...) | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:31:41:31:53 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:38:41:38:53 | new String(...) | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:38:41:38:53 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) | user input | -| SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | user input | -| SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | user input | -| SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | user input | -| SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | user input | -| SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) | user input | -| SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) | user input | -| SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) | user input | -| SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) | user input | -| SimpleXMLTests.java:90:37:90:49 | new String(...) | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:90:37:90:49 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:97:37:97:49 | new String(...) | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:97:37:97:49 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:104:26:104:38 | new String(...) | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:104:26:104:38 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:111:26:111:38 | new String(...) | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:111:26:111:38 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | user input | -| SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) | user input | -| SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | user input | -| SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) | user input | -| SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | user input | -| SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) | user input | -| SimpleXMLTests.java:146:22:146:34 | new String(...) | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:146:22:146:34 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) | user input | -| SimpleXMLTests.java:153:22:153:34 | new String(...) | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:153:22:153:34 | new String(...) | Unsafe parsing of XML file from $@. | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) | user input | -| TransformerTests.java:20:27:20:65 | new StreamSource(...) | TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:20:44:20:64 | getInputStream(...) | user input | -| TransformerTests.java:21:23:21:61 | new StreamSource(...) | TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:21:40:21:60 | getInputStream(...) | user input | -| TransformerTests.java:71:27:71:65 | new StreamSource(...) | TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:71:44:71:64 | getInputStream(...) | user input | -| TransformerTests.java:72:23:72:61 | new StreamSource(...) | TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:72:40:72:60 | getInputStream(...) | user input | -| TransformerTests.java:79:27:79:65 | new StreamSource(...) | TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:79:44:79:64 | getInputStream(...) | user input | -| TransformerTests.java:80:23:80:61 | new StreamSource(...) | TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:80:40:80:60 | getInputStream(...) | user input | -| TransformerTests.java:88:27:88:65 | new StreamSource(...) | TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:88:44:88:64 | getInputStream(...) | user input | -| TransformerTests.java:89:23:89:61 | new StreamSource(...) | TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:89:40:89:60 | getInputStream(...) | user input | -| TransformerTests.java:97:27:97:65 | new StreamSource(...) | TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:97:44:97:64 | getInputStream(...) | user input | -| TransformerTests.java:98:23:98:61 | new StreamSource(...) | TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:98:40:98:60 | getInputStream(...) | user input | -| TransformerTests.java:103:21:103:59 | new StreamSource(...) | TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:103:38:103:58 | getInputStream(...) | user input | -| TransformerTests.java:116:21:116:59 | new StreamSource(...) | TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:116:38:116:58 | getInputStream(...) | user input | -| TransformerTests.java:122:21:122:59 | new StreamSource(...) | TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:122:38:122:58 | getInputStream(...) | user input | -| TransformerTests.java:129:21:129:59 | new StreamSource(...) | TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:129:38:129:58 | getInputStream(...) | user input | -| TransformerTests.java:136:21:136:59 | new StreamSource(...) | TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:136:38:136:58 | getInputStream(...) | user input | -| TransformerTests.java:141:18:141:70 | new SAXSource(...) | TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:18:141:70 | new SAXSource(...) | Unsafe parsing of XML file from $@. | TransformerTests.java:141:48:141:68 | getInputStream(...) | user input | -| UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | Unsafe parsing of XML file from $@. | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | user input | -| XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:16:34:16:54 | getInputStream(...) | user input | -| XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:56:34:56:54 | getInputStream(...) | user input | -| XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:63:34:63:54 | getInputStream(...) | user input | -| XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:70:34:70:54 | getInputStream(...) | user input | -| XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:78:34:78:54 | getInputStream(...) | user input | -| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user input | -| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user input | -| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | Unsafe parsing of XML file from $@. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user input | -| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | Unsafe parsing of XML file from $@. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | user input | -| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | Unsafe parsing of XML file from $@. | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | user input | +| DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:14:19:14:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:28:19:28:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:35:19:35:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:42:19:42:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:49:19:49:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:64:19:64:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:71:19:71:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:79:19:79:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:87:19:87:39 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) : InputStream | DocumentBuilderTests.java:94:16:94:38 | getInputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:93:51:93:71 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:101:16:101:52 | sourceToInputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value | +| DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) : InputStream | DocumentBuilderTests.java:102:16:102:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | DocumentBuilderTests.java:100:41:100:61 | getInputStream(...) | user-provided value | +| SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXBuilderTests.java:8:19:8:39 | getInputStream(...) | user-provided value | +| SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXBuilderTests.java:20:19:20:39 | getInputStream(...) | user-provided value | +| SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | SAXParserTests.java:13:18:13:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:13:18:13:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | SAXParserTests.java:30:18:30:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:30:18:30:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | SAXParserTests.java:38:18:38:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:38:18:38:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | SAXParserTests.java:46:18:46:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:46:18:46:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | SAXParserTests.java:55:18:55:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:55:18:55:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | SAXParserTests.java:64:18:64:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:64:18:64:38 | getInputStream(...) | user-provided value | +| SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | SAXParserTests.java:73:18:73:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXParserTests.java:73:18:73:38 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:8:17:8:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:23:17:23:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:30:17:30:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:37:17:37:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:45:17:45:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:53:17:53:37 | getInputStream(...) | user-provided value | +| SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SAXReaderTests.java:61:17:61:37 | getInputStream(...) | user-provided value | +| SAXSourceTests.java:20:18:20:23 | source | SAXSourceTests.java:17:62:17:82 | getInputStream(...) : InputStream | SAXSourceTests.java:20:18:20:23 | source | A $@ is parsed as XML without guarding against external entity expansion. | SAXSourceTests.java:17:62:17:82 | getInputStream(...) | user-provided value | +| SchemaTests.java:12:39:12:77 | new StreamSource(...) | SchemaTests.java:12:56:12:76 | getInputStream(...) : InputStream | SchemaTests.java:12:39:12:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:12:56:12:76 | getInputStream(...) | user-provided value | +| SchemaTests.java:25:39:25:77 | new StreamSource(...) | SchemaTests.java:25:56:25:76 | getInputStream(...) : InputStream | SchemaTests.java:25:39:25:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:25:56:25:76 | getInputStream(...) | user-provided value | +| SchemaTests.java:31:39:31:77 | new StreamSource(...) | SchemaTests.java:31:56:31:76 | getInputStream(...) : InputStream | SchemaTests.java:31:39:31:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:31:56:31:76 | getInputStream(...) | user-provided value | +| SchemaTests.java:38:39:38:77 | new StreamSource(...) | SchemaTests.java:38:56:38:76 | getInputStream(...) : InputStream | SchemaTests.java:38:39:38:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:38:56:38:76 | getInputStream(...) | user-provided value | +| SchemaTests.java:45:39:45:77 | new StreamSource(...) | SchemaTests.java:45:56:45:76 | getInputStream(...) : InputStream | SchemaTests.java:45:39:45:77 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | SchemaTests.java:45:56:45:76 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:14:41:14:61 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:19:41:19:61 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:24:41:24:84 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:24:63:24:83 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:31:41:31:53 | new String(...) | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:31:41:31:53 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:30:5:30:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:38:41:38:53 | new String(...) | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:38:41:38:53 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:37:5:37:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) : InputStream | SimpleXMLTests.java:43:41:43:84 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:43:63:43:83 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:48:37:48:57 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:53:37:53:57 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:58:26:58:46 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:63:26:63:46 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:68:37:68:80 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:68:59:68:79 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) : InputStream | SimpleXMLTests.java:73:37:73:80 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:73:59:73:79 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:78:26:78:69 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:78:48:78:68 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) : InputStream | SimpleXMLTests.java:83:26:83:69 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:83:48:83:68 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:90:37:90:49 | new String(...) | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:90:37:90:49 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:89:5:89:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:97:37:97:49 | new String(...) | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:97:37:97:49 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:96:5:96:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:104:26:104:38 | new String(...) | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:104:26:104:38 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:103:5:103:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:111:26:111:38 | new String(...) | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:111:26:111:38 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:110:5:110:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:115:22:115:42 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:119:22:119:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:119:44:119:64 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:124:22:124:42 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:129:22:129:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:129:44:129:64 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:134:22:134:42 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) : InputStream | SimpleXMLTests.java:139:22:139:65 | new InputStreamReader(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:139:44:139:64 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:146:22:146:34 | new String(...) | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:146:22:146:34 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:145:5:145:25 | getInputStream(...) | user-provided value | +| SimpleXMLTests.java:153:22:153:34 | new String(...) | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) : InputStream | SimpleXMLTests.java:153:22:153:34 | new String(...) | A $@ is parsed as XML without guarding against external entity expansion. | SimpleXMLTests.java:152:5:152:25 | getInputStream(...) | user-provided value | +| TransformerTests.java:20:27:20:65 | new StreamSource(...) | TransformerTests.java:20:44:20:64 | getInputStream(...) : InputStream | TransformerTests.java:20:27:20:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:20:44:20:64 | getInputStream(...) | user-provided value | +| TransformerTests.java:21:23:21:61 | new StreamSource(...) | TransformerTests.java:21:40:21:60 | getInputStream(...) : InputStream | TransformerTests.java:21:23:21:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:21:40:21:60 | getInputStream(...) | user-provided value | +| TransformerTests.java:71:27:71:65 | new StreamSource(...) | TransformerTests.java:71:44:71:64 | getInputStream(...) : InputStream | TransformerTests.java:71:27:71:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:71:44:71:64 | getInputStream(...) | user-provided value | +| TransformerTests.java:72:23:72:61 | new StreamSource(...) | TransformerTests.java:72:40:72:60 | getInputStream(...) : InputStream | TransformerTests.java:72:23:72:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:72:40:72:60 | getInputStream(...) | user-provided value | +| TransformerTests.java:79:27:79:65 | new StreamSource(...) | TransformerTests.java:79:44:79:64 | getInputStream(...) : InputStream | TransformerTests.java:79:27:79:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:79:44:79:64 | getInputStream(...) | user-provided value | +| TransformerTests.java:80:23:80:61 | new StreamSource(...) | TransformerTests.java:80:40:80:60 | getInputStream(...) : InputStream | TransformerTests.java:80:23:80:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:80:40:80:60 | getInputStream(...) | user-provided value | +| TransformerTests.java:88:27:88:65 | new StreamSource(...) | TransformerTests.java:88:44:88:64 | getInputStream(...) : InputStream | TransformerTests.java:88:27:88:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:88:44:88:64 | getInputStream(...) | user-provided value | +| TransformerTests.java:89:23:89:61 | new StreamSource(...) | TransformerTests.java:89:40:89:60 | getInputStream(...) : InputStream | TransformerTests.java:89:23:89:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:89:40:89:60 | getInputStream(...) | user-provided value | +| TransformerTests.java:97:27:97:65 | new StreamSource(...) | TransformerTests.java:97:44:97:64 | getInputStream(...) : InputStream | TransformerTests.java:97:27:97:65 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:97:44:97:64 | getInputStream(...) | user-provided value | +| TransformerTests.java:98:23:98:61 | new StreamSource(...) | TransformerTests.java:98:40:98:60 | getInputStream(...) : InputStream | TransformerTests.java:98:23:98:61 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:98:40:98:60 | getInputStream(...) | user-provided value | +| TransformerTests.java:103:21:103:59 | new StreamSource(...) | TransformerTests.java:103:38:103:58 | getInputStream(...) : InputStream | TransformerTests.java:103:21:103:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:103:38:103:58 | getInputStream(...) | user-provided value | +| TransformerTests.java:116:21:116:59 | new StreamSource(...) | TransformerTests.java:116:38:116:58 | getInputStream(...) : InputStream | TransformerTests.java:116:21:116:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:116:38:116:58 | getInputStream(...) | user-provided value | +| TransformerTests.java:122:21:122:59 | new StreamSource(...) | TransformerTests.java:122:38:122:58 | getInputStream(...) : InputStream | TransformerTests.java:122:21:122:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:122:38:122:58 | getInputStream(...) | user-provided value | +| TransformerTests.java:129:21:129:59 | new StreamSource(...) | TransformerTests.java:129:38:129:58 | getInputStream(...) : InputStream | TransformerTests.java:129:21:129:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:129:38:129:58 | getInputStream(...) | user-provided value | +| TransformerTests.java:136:21:136:59 | new StreamSource(...) | TransformerTests.java:136:38:136:58 | getInputStream(...) : InputStream | TransformerTests.java:136:21:136:59 | new StreamSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:136:38:136:58 | getInputStream(...) | user-provided value | +| TransformerTests.java:141:18:141:70 | new SAXSource(...) | TransformerTests.java:141:48:141:68 | getInputStream(...) : InputStream | TransformerTests.java:141:18:141:70 | new SAXSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | TransformerTests.java:141:48:141:68 | getInputStream(...) | user-provided value | +| UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | UnmarshallerTests.java:28:18:28:38 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:16:18:16:55 | new InputSource(...) | XMLReaderTests.java:16:34:16:54 | getInputStream(...) : InputStream | XMLReaderTests.java:16:18:16:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:16:34:16:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:56:18:56:55 | new InputSource(...) | XMLReaderTests.java:56:34:56:54 | getInputStream(...) : InputStream | XMLReaderTests.java:56:18:56:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:56:34:56:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:63:18:63:55 | new InputSource(...) | XMLReaderTests.java:63:34:63:54 | getInputStream(...) : InputStream | XMLReaderTests.java:63:18:63:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:63:34:63:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:70:18:70:55 | new InputSource(...) | XMLReaderTests.java:70:34:70:54 | getInputStream(...) : InputStream | XMLReaderTests.java:70:18:70:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:70:34:70:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:78:18:78:55 | new InputSource(...) | XMLReaderTests.java:78:34:78:54 | getInputStream(...) : InputStream | XMLReaderTests.java:78:18:78:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:78:34:78:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:86:18:86:55 | new InputSource(...) | XMLReaderTests.java:86:34:86:54 | getInputStream(...) : InputStream | XMLReaderTests.java:86:18:86:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:86:34:86:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:94:18:94:55 | new InputSource(...) | XMLReaderTests.java:94:34:94:54 | getInputStream(...) : InputStream | XMLReaderTests.java:94:18:94:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:94:34:94:54 | getInputStream(...) | user-provided value | +| XMLReaderTests.java:100:18:100:55 | new InputSource(...) | XMLReaderTests.java:100:34:100:54 | getInputStream(...) : InputStream | XMLReaderTests.java:100:18:100:55 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XMLReaderTests.java:100:34:100:54 | getInputStream(...) | user-provided value | +| XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) : InputStream | XPathExpressionTests.java:27:21:27:58 | new InputSource(...) | A $@ is parsed as XML without guarding against external entity expansion. | XPathExpressionTests.java:27:37:27:57 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:9:35:9:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:10:34:10:54 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:24:35:24:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:25:34:25:54 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:31:35:31:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:32:34:32:54 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:39:35:39:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:40:34:40:54 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:47:35:47:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:48:34:48:54 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:55:35:55:55 | getInputStream(...) | user-provided value | +| XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | A $@ is parsed as XML without guarding against external entity expansion. | XmlInputFactoryTests.java:56:34:56:54 | getInputStream(...) | user-provided value | diff --git a/java/ql/test/query-tests/security/CWE-749/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-749/AndroidManifest.xml old mode 100755 new mode 100644 diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index 6898986e749..2fbc09e8d9e 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "4.7.2" + "typescript": "4.8.2" }, "scripts": { "build": "tsc --project tsconfig.json", diff --git a/javascript/extractor/lib/typescript/src/ast_extractor.ts b/javascript/extractor/lib/typescript/src/ast_extractor.ts index c1415dbd294..b935294feb6 100644 --- a/javascript/extractor/lib/typescript/src/ast_extractor.ts +++ b/javascript/extractor/lib/typescript/src/ast_extractor.ts @@ -168,20 +168,9 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj } } - // Number of conditional type expressions the visitor is currently inside. - // We disable type extraction inside such type expressions, to avoid complications - // with `infer` types. - let insideConditionalTypes = 0; - visitAstNode(ast); function visitAstNode(node: AugmentedNode) { - if (node.kind === ts.SyntaxKind.ConditionalType) { - ++insideConditionalTypes; - } ts.forEachChild(node, visitAstNode); - if (node.kind === ts.SyntaxKind.ConditionalType) { - --insideConditionalTypes; - } // fill in line/column info if ("pos" in node) { @@ -202,7 +191,7 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj } } - if (typeChecker != null && insideConditionalTypes === 0) { + if (typeChecker != null) { if (isTypedNode(node)) { let contextualType = isContextuallyTypedNode(node) ? typeChecker.getContextualType(node) diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index 626c8a593b0..440e621efd2 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -241,7 +241,7 @@ const astProperties: string[] = [ "constructor", "declarationList", "declarations", - "decorators", + "illegalDecorators", "default", "delete", "dotDotDotToken", diff --git a/javascript/extractor/lib/typescript/src/type_table.ts b/javascript/extractor/lib/typescript/src/type_table.ts index 1479d84e5da..9a14db84019 100644 --- a/javascript/extractor/lib/typescript/src/type_table.ts +++ b/javascript/extractor/lib/typescript/src/type_table.ts @@ -947,7 +947,7 @@ export class TypeTable { * Returns a unique string for the given call/constructor signature. */ private getSignatureString(kind: ts.SignatureKind, signature: AugmentedSignature): string { - let modifiers : ts.ModifiersArray = signature.getDeclaration()?.modifiers; + let modifiers = signature.getDeclaration()?.modifiers; let isAbstract = modifiers && modifiers.filter(modifier => modifier.kind == ts.SyntaxKind.AbstractKeyword).length > 0 let parameters = signature.getParameters(); diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index 3a10c8452f0..05fb731c9e4 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -6,7 +6,7 @@ version "12.7.11" resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446 -typescript@4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4" - integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A== +typescript@4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.2.tgz#e3b33d5ccfb5914e4eeab6699cf208adee3fd790" + integrity sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw== diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 6ae1e79dc33..50ee6835aeb 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -41,7 +41,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2022-07-11"; + public static final String EXTRACTOR_VERSION = "2022-08-25"; public static final Pattern NEWLINE = Pattern.compile("\n"); diff --git a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java index 9ac0915fc90..1cb1913ee75 100644 --- a/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/ts/extractor/TypeScriptASTConverter.java @@ -976,8 +976,9 @@ public class TypeScriptASTConverter { hasDeclareKeyword, hasAbstractKeyword); attachSymbolInformation(classDecl.getClassDef(), node); - if (node.has("decorators")) { - classDecl.addDecorators(convertChildren(node, "decorators")); + List decorators = getDecorators(node); + if (!decorators.isEmpty()) { + classDecl.addDecorators(decorators); advanceUntilAfter(loc, classDecl.getDecorators()); } Node exportedDecl = fixExports(loc, classDecl); @@ -989,6 +990,17 @@ public class TypeScriptASTConverter { return exportedDecl; } + List getDecorators(JsonObject node) throws ParseError { + List result = new ArrayList<>(); + for (JsonElement elt : getChildIterable(node, "modifiers")) { + JsonObject modifier = elt.getAsJsonObject(); + if (hasKind(modifier, "Decorator")) { + result.add((Decorator) convertNode(modifier)); + } + } + return result; + } + private Node convertCommaListExpression(JsonObject node, SourceLocation loc) throws ParseError { return new SequenceExpression(loc, convertChildren(node, "elements")); } @@ -1041,7 +1053,7 @@ public class TypeScriptASTConverter { private List convertParameterDecorators(JsonObject function) throws ParseError { List decoratorLists = new ArrayList<>(); for (JsonElement parameter : getProperParameters(function)) { - decoratorLists.add(makeDecoratorList(parameter.getAsJsonObject().get("decorators"))); + decoratorLists.add(makeDecoratorList(parameter.getAsJsonObject().get("modifiers"))); } return decoratorLists; } @@ -1139,7 +1151,7 @@ public class TypeScriptASTConverter { loc, hasModifier(node, "ConstKeyword"), hasModifier(node, "DeclareKeyword"), - convertChildrenNotNull(node, "decorators"), + convertChildrenNotNull(node, "illegalDecorators"), // as of https://github.com/microsoft/TypeScript/pull/50343/ the property is called `illegalDecorators` instead of `decorators` convertChild(node, "name"), convertChildren(node, "members")); attachSymbolInformation(enumDeclaration, node); @@ -1664,8 +1676,9 @@ public class TypeScriptASTConverter { FunctionExpression method = convertImplicitFunction(node, loc); MethodDefinition methodDefinition = new MethodDefinition(loc, flags, methodKind, convertChild(node, "name"), method); - if (node.has("decorators")) { - methodDefinition.addDecorators(convertChildren(node, "decorators")); + List decorators = getDecorators(node); + if (!decorators.isEmpty()) { + methodDefinition.addDecorators(decorators); advanceUntilAfter(loc, methodDefinition.getDecorators()); } return methodDefinition; @@ -2079,8 +2092,9 @@ public class TypeScriptASTConverter { convertChild(node, "name"), convertChild(node, "initializer"), convertChildAsType(node, "type")); - if (node.has("decorators")) { - fieldDefinition.addDecorators(convertChildren(node, "decorators")); + List decorators = getDecorators(node); + if (!decorators.isEmpty()) { + fieldDefinition.addDecorators(decorators); advanceUntilAfter(loc, fieldDefinition.getDecorators()); } return fieldDefinition; diff --git a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/DebugResultInclusion.ql b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/DebugResultInclusion.ql index 215103358ea..28a95268a57 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/DebugResultInclusion.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/DebugResultInclusion.ql @@ -15,16 +15,16 @@ import extraction.ExtractEndpointData string getAReasonSinkExcluded(DataFlow::Node sinkCandidate, Query query) { query instanceof NosqlInjectionQuery and - result = NosqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) + result = NosqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) or query instanceof SqlInjectionQuery and - result = SqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) + result = SqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) or query instanceof TaintedPathQuery and - result = TaintedPathATM::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) + result = TaintedPathAtm::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) or query instanceof XssQuery and - result = XssATM::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) + result = XssAtm::SinkEndpointFilter::getAReasonSinkExcluded(sinkCandidate) } pragma[inline] diff --git a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointData.qll b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointData.qll index 53d559d2568..af91933b7a4 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointData.qll +++ b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointData.qll @@ -14,10 +14,26 @@ import experimental.adaptivethreatmodeling.EndpointFeatures as EndpointFeatures import experimental.adaptivethreatmodeling.EndpointScoring as EndpointScoring import experimental.adaptivethreatmodeling.EndpointTypes import experimental.adaptivethreatmodeling.FilteringReasons -import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM -import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM -import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM -import experimental.adaptivethreatmodeling.XssATM as XssATM +import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm + +/** DEPRECATED: Alias for NosqlInjectionAtm */ +deprecated module NosqlInjectionATM = NosqlInjectionAtm; + +import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm + +/** DEPRECATED: Alias for SqlInjectionAtm */ +deprecated module SqlInjectionATM = SqlInjectionAtm; + +import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm + +/** DEPRECATED: Alias for TaintedPathAtm */ +deprecated module TaintedPathATM = TaintedPathAtm; + +import experimental.adaptivethreatmodeling.XssATM as XssAtm + +/** DEPRECATED: Alias for XssAtm */ +deprecated module XssATM = XssAtm; + import Labels import NoFeaturizationRestrictionsConfig import Queries @@ -25,13 +41,13 @@ import Queries /** Gets the ATM configuration object for the specified query. */ AtmConfig getAtmCfg(Query query) { query instanceof NosqlInjectionQuery and - result instanceof NosqlInjectionATM::NosqlInjectionAtmConfig + result instanceof NosqlInjectionAtm::NosqlInjectionAtmConfig or - query instanceof SqlInjectionQuery and result instanceof SqlInjectionATM::SqlInjectionAtmConfig + query instanceof SqlInjectionQuery and result instanceof SqlInjectionAtm::SqlInjectionAtmConfig or - query instanceof TaintedPathQuery and result instanceof TaintedPathATM::TaintedPathAtmConfig + query instanceof TaintedPathQuery and result instanceof TaintedPathAtm::TaintedPathAtmConfig or - query instanceof XssQuery and result instanceof XssATM::DomBasedXssAtmConfig + query instanceof XssQuery and result instanceof XssAtm::DomBasedXssAtmConfig } /** DEPRECATED: Alias for getAtmCfg */ @@ -39,13 +55,13 @@ deprecated ATMConfig getATMCfg(Query query) { result = getAtmCfg(query) } /** Gets the ATM data flow configuration for the specified query. */ DataFlow::Configuration getDataFlowCfg(Query query) { - query instanceof NosqlInjectionQuery and result instanceof NosqlInjectionATM::Configuration + query instanceof NosqlInjectionQuery and result instanceof NosqlInjectionAtm::Configuration or - query instanceof SqlInjectionQuery and result instanceof SqlInjectionATM::Configuration + query instanceof SqlInjectionQuery and result instanceof SqlInjectionAtm::Configuration or - query instanceof TaintedPathQuery and result instanceof TaintedPathATM::Configuration + query instanceof TaintedPathQuery and result instanceof TaintedPathAtm::Configuration or - query instanceof XssQuery and result instanceof XssATM::Configuration + query instanceof XssQuery and result instanceof XssAtm::Configuration } /** Gets a known sink for the specified query. */ diff --git a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql index 11986562085..697928d74b0 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/modelbuilding/extraction/ExtractEndpointMapping.ql @@ -4,25 +4,25 @@ * Maps ML-powered queries to their `EndpointType` for clearer labelling while evaluating ML model during training. */ -import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM -import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM -import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM -import experimental.adaptivethreatmodeling.XssATM as XssATM +import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm +import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm +import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm +import experimental.adaptivethreatmodeling.XssATM as XssAtm import experimental.adaptivethreatmodeling.AdaptiveThreatModeling from string queryName, AtmConfig c, EndpointType e where ( queryName = "SqlInjection" and - c instanceof SqlInjectionATM::SqlInjectionAtmConfig + c instanceof SqlInjectionAtm::SqlInjectionAtmConfig or queryName = "NosqlInjection" and - c instanceof NosqlInjectionATM::NosqlInjectionAtmConfig + c instanceof NosqlInjectionAtm::NosqlInjectionAtmConfig or queryName = "TaintedPath" and - c instanceof TaintedPathATM::TaintedPathAtmConfig + c instanceof TaintedPathAtm::TaintedPathAtmConfig or - queryName = "Xss" and c instanceof XssATM::DomBasedXssAtmConfig + queryName = "Xss" and c instanceof XssAtm::DomBasedXssAtmConfig ) and e = c.getASinkEndpointType() select queryName, e.getEncoding() as label diff --git a/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/EndpointFeatures.ql b/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/EndpointFeatures.ql index ab0191c5129..9985625d85c 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/EndpointFeatures.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/EndpointFeatures.ql @@ -7,20 +7,20 @@ */ import javascript -import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM -import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM -import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM -import experimental.adaptivethreatmodeling.XssATM as XssATM +import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm +import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm +import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm +import experimental.adaptivethreatmodeling.XssATM as XssAtm import experimental.adaptivethreatmodeling.EndpointFeatures as EndpointFeatures import experimental.adaptivethreatmodeling.StandardEndpointFilters as StandardEndpointFilters import extraction.NoFeaturizationRestrictionsConfig query predicate tokenFeatures(DataFlow::Node endpoint, string featureName, string featureValue) { ( - not exists(NosqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or - not exists(SqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or - not exists(TaintedPathATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or - not exists(XssATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or + not exists(NosqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or + not exists(SqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or + not exists(TaintedPathAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or + not exists(XssAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint)) or StandardEndpointFilters::isArgumentToModeledFunction(endpoint) ) and EndpointFeatures::tokenFeatures(endpoint, featureName, featureValue) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/FilteredTruePositives.ql b/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/FilteredTruePositives.ql index 9edae6cec5e..8ae82446403 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/FilteredTruePositives.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/FilteredTruePositives.ql @@ -17,31 +17,31 @@ import semmle.javascript.security.dataflow.SqlInjectionCustomizations import semmle.javascript.security.dataflow.TaintedPathCustomizations import semmle.javascript.security.dataflow.DomBasedXssCustomizations import experimental.adaptivethreatmodeling.StandardEndpointFilters as StandardEndpointFilters -import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM -import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionATM -import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathATM -import experimental.adaptivethreatmodeling.XssATM as XssATM +import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm +import experimental.adaptivethreatmodeling.SqlInjectionATM as SqlInjectionAtm +import experimental.adaptivethreatmodeling.TaintedPathATM as TaintedPathAtm +import experimental.adaptivethreatmodeling.XssATM as XssAtm query predicate nosqlFilteredTruePositives(DataFlow::Node endpoint, string reason) { endpoint instanceof NosqlInjection::Sink and - reason = NosqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and + reason = NosqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and not reason = ["argument to modeled function", "modeled sink", "modeled database access"] } query predicate sqlFilteredTruePositives(DataFlow::Node endpoint, string reason) { endpoint instanceof SqlInjection::Sink and - reason = SqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and + reason = SqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and reason != "argument to modeled function" } query predicate taintedPathFilteredTruePositives(DataFlow::Node endpoint, string reason) { endpoint instanceof TaintedPath::Sink and - reason = TaintedPathATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and + reason = TaintedPathAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and reason != "argument to modeled function" } query predicate xssFilteredTruePositives(DataFlow::Node endpoint, string reason) { endpoint instanceof DomBasedXss::Sink and - reason = XssATM::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and + reason = XssAtm::SinkEndpointFilter::getAReasonSinkExcluded(endpoint) and reason != "argument to modeled function" } diff --git a/javascript/ql/experimental/adaptivethreatmodeling/test/modeled_apis/nosql_endpoint_filter_ignores_modeled_apis.ql b/javascript/ql/experimental/adaptivethreatmodeling/test/modeled_apis/nosql_endpoint_filter_ignores_modeled_apis.ql index 566a2bb98b8..9a81ce73d91 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/test/modeled_apis/nosql_endpoint_filter_ignores_modeled_apis.ql +++ b/javascript/ql/experimental/adaptivethreatmodeling/test/modeled_apis/nosql_endpoint_filter_ignores_modeled_apis.ql @@ -1,6 +1,6 @@ import javascript -import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionATM +import experimental.adaptivethreatmodeling.NosqlInjectionATM as NosqlInjectionAtm query predicate effectiveSinks(DataFlow::Node node) { - not exists(NosqlInjectionATM::SinkEndpointFilter::getAReasonSinkExcluded(node)) + not exists(NosqlInjectionAtm::SinkEndpointFilter::getAReasonSinkExcluded(node)) } diff --git a/javascript/ql/lib/change-notes/2022-05-24-typescript-4-8.md b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-8.md new file mode 100644 index 00000000000..28b73b84d1b --- /dev/null +++ b/javascript/ql/lib/change-notes/2022-05-24-typescript-4-8.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* Added support for TypeScript 4.8. \ No newline at end of file diff --git a/javascript/ql/lib/semmle/javascript/Actions.qll b/javascript/ql/lib/semmle/javascript/Actions.qll index 8ea789c96e0..d79bb6eff4a 100644 --- a/javascript/ql/lib/semmle/javascript/Actions.qll +++ b/javascript/ql/lib/semmle/javascript/Actions.qll @@ -11,7 +11,7 @@ import javascript */ module Actions { /** A YAML node in a GitHub Actions workflow file. */ - private class Node extends YAMLNode { + private class Node extends YamlNode { Node() { this.getLocation() .getFile() @@ -24,12 +24,12 @@ module Actions { * An Actions workflow. This is a mapping at the top level of an Actions YAML workflow file. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions. */ - class Workflow extends Node, YAMLDocument, YAMLMapping { + class Workflow extends Node, YamlDocument, YamlMapping { /** Gets the `jobs` mapping from job IDs to job definitions in this workflow. */ - YAMLMapping getJobs() { result = this.lookup("jobs") } + YamlMapping getJobs() { result = this.lookup("jobs") } /** Gets the name of the workflow. */ - string getName() { result = this.lookup("name").(YAMLString).getValue() } + string getName() { result = this.lookup("name").(YamlString).getValue() } /** Gets the name of the workflow file. */ string getFileName() { result = this.getFile().getBaseName() } @@ -45,7 +45,7 @@ module Actions { * An Actions On trigger within a workflow. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#on. */ - class On extends YAMLNode, YAMLMappingLikeNode { + class On extends YamlNode, YamlMappingLikeNode { Workflow workflow; On() { workflow.lookup("on") = this } @@ -58,7 +58,7 @@ module Actions { * An Actions job within a workflow. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobs. */ - class Job extends YAMLNode, YAMLMapping { + class Job extends YamlNode, YamlMapping { string jobId; Workflow workflow; @@ -74,19 +74,19 @@ module Actions { * Gets the ID of this job, as a YAML scalar node. * This is the job's key within the `jobs` mapping. */ - YAMLString getIdNode() { workflow.getJobs().maps(result, this) } + YamlString getIdNode() { workflow.getJobs().maps(result, this) } /** Gets the human-readable name of this job, if any, as a string. */ string getName() { result = this.getNameNode().getValue() } /** Gets the human-readable name of this job, if any, as a YAML scalar node. */ - YAMLString getNameNode() { result = this.lookup("name") } + YamlString getNameNode() { result = this.lookup("name") } /** Gets the step at the given index within this job. */ Step getStep(int index) { result.getJob() = this and result.getIndex() = index } /** Gets the sequence of `steps` within this job. */ - YAMLSequence getSteps() { result = this.lookup("steps") } + YamlSequence getSteps() { result = this.lookup("steps") } /** Gets the workflow this job belongs to. */ Workflow getWorkflow() { result = workflow } @@ -99,7 +99,7 @@ module Actions { * An `if` within a job. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idif. */ - class JobIf extends YAMLNode, YAMLScalar { + class JobIf extends YamlNode, YamlScalar { Job job; JobIf() { job.lookup("if") = this } @@ -112,7 +112,7 @@ module Actions { * A step within an Actions job. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idsteps. */ - class Step extends YAMLNode, YAMLMapping { + class Step extends YamlNode, YamlMapping { int index; Job job; @@ -134,14 +134,14 @@ module Actions { StepIf getIf() { result.getStep() = this } /** Gets the ID of this step, if any. */ - string getId() { result = this.lookup("id").(YAMLString).getValue() } + string getId() { result = this.lookup("id").(YamlString).getValue() } } /** * An `if` within a step. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsif. */ - class StepIf extends YAMLNode, YAMLScalar { + class StepIf extends YamlNode, YamlScalar { Step step; StepIf() { step.lookup("if") = this } @@ -170,7 +170,7 @@ module Actions { * * Does not handle local repository references, e.g. `.github/actions/action-name`. */ - class Uses extends YAMLNode, YAMLScalar { + class Uses extends YamlNode, YamlScalar { Step step; Uses() { step.lookup("uses") = this } @@ -200,7 +200,7 @@ module Actions { * arg2: abc * ``` */ - class With extends YAMLNode, YAMLMapping { + class With extends YamlNode, YamlMapping { Step step; With() { step.lookup("with") = this } @@ -219,7 +219,7 @@ module Actions { * ref: ${{ github.event.pull_request.head.sha }} * ``` */ - class Ref extends YAMLNode, YAMLString { + class Ref extends YamlNode, YamlString { With with; Ref() { with.lookup("ref") = this } @@ -232,7 +232,7 @@ module Actions { * A `run` field within an Actions job step, which runs command-line programs using an operating system shell. * See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsrun. */ - class Run extends YAMLNode, YAMLString { + class Run extends YamlNode, YamlString { Step step; Run() { step.lookup("run") = this } diff --git a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll index 016875ff8d4..8dd53402205 100644 --- a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll +++ b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll @@ -178,7 +178,7 @@ predicate isGeneratedFileName(File f) { predicate isGenerated(TopLevel tl) { tl.isMinified() or isBundle(tl) or - tl instanceof GWTGeneratedTopLevel or + tl instanceof GwtGeneratedTopLevel or tl instanceof DartGeneratedTopLevel or exists(GeneratedCodeMarkerComment gcmc | tl = gcmc.getTopLevel()) or hasManyInvocations(tl) or diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll index f4cdda89e31..f4c2a846ed8 100644 --- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll +++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll @@ -43,7 +43,7 @@ class JsonStringifyCall extends DataFlow::CallNode { /** * A taint step through the [`json2csv`](https://www.npmjs.com/package/json2csv) library. */ -class JSON2CSVTaintStep extends TaintTracking::SharedTaintStep { +class Json2CsvTaintStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(API::CallNode call | call = @@ -59,6 +59,9 @@ class JSON2CSVTaintStep extends TaintTracking::SharedTaintStep { } } +/** DEPRECATED: Alias for Json2CsvTaintStep */ +deprecated class JSON2CSVTaintStep = Json2CsvTaintStep; + /** * A step through the [`prettyjson`](https://www.npmjs.com/package/prettyjson) library. * This is not quite a `JSON.stringify` call, as it e.g. does not wrap keys in double quotes. diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index 21d7fa4007f..515e900f277 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -168,18 +168,24 @@ class PackageJson extends JsonObject { JsonArray getCPUs() { result = this.getPropValue("cpu") } /** Gets a platform supported by this package. */ - string getWhitelistedCPU() { + string getWhitelistedCpu() { result = this.getCPUs().getElementStringValue(_) and not result.matches("!%") } + /** DEPRECATED: Alias for getWhitelistedCpu */ + deprecated string getWhitelistedCPU() { result = this.getWhitelistedCpu() } + /** Gets a platform not supported by this package. */ - string getBlacklistedCPU() { + string getBlacklistedCpu() { exists(string str | str = this.getCPUs().getElementStringValue(_) | result = str.regexpCapture("!(.*)", 1) ) } + /** DEPRECATED: Alias for getBlacklistedCpu */ + deprecated string getBlacklistedCPU() { result = this.getBlacklistedCpu() } + /** Holds if this package prefers to be installed globally. */ predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JsonBoolean).getValue() = "true" } diff --git a/javascript/ql/lib/semmle/javascript/PrintAst.qll b/javascript/ql/lib/semmle/javascript/PrintAst.qll index 95c722f5402..29b1d619016 100644 --- a/javascript/ql/lib/semmle/javascript/PrintAst.qll +++ b/javascript/ql/lib/semmle/javascript/PrintAst.qll @@ -64,8 +64,8 @@ private newtype TPrintAstNode = // JSON TJsonNode(JsonValue value) { shouldPrint(value, _) and not isNotNeeded(value) } or // YAML - TYamlNode(YAMLNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or - TYamlMappingNode(YAMLMapping mapping, int i) { + TYamlNode(YamlNode n) { shouldPrint(n, _) and not isNotNeeded(n) } or + TYamlMappingNode(YamlMapping mapping, int i) { shouldPrint(mapping, _) and not isNotNeeded(mapping) and exists(mapping.getKeyNode(i)) } or // HTML @@ -628,7 +628,7 @@ module PrintYaml { * A print node representing a YAML value in a .yml file. */ class YamlNodeNode extends PrintAstNode, TYamlNode { - YAMLNode node; + YamlNode node; YamlNodeNode() { this = TYamlNode(node) } @@ -639,10 +639,10 @@ module PrintYaml { /** * Gets the `YAMLNode` represented by this node. */ - final YAMLNode getValue() { result = node } + final YamlNode getValue() { result = node } override PrintAstNode getChild(int childIndex) { - exists(YAMLNode child | result.(YamlNodeNode).getValue() = child | + exists(YamlNode child | result.(YamlNodeNode).getValue() = child | child = node.getChildNode(childIndex) ) } @@ -657,7 +657,7 @@ module PrintYaml { * Each child of this node aggregates the key and value of a mapping. */ class YamlMappingNode extends YamlNodeNode { - override YAMLMapping node; + override YamlMapping node; override PrintAstNode getChild(int childIndex) { exists(YamlMappingMapNode map | map = result | map.maps(node, childIndex)) @@ -671,21 +671,21 @@ module PrintYaml { * A print node representing the `i`th mapping in `mapping`. */ class YamlMappingMapNode extends PrintAstNode, TYamlMappingNode { - YAMLMapping mapping; + YamlMapping mapping; int i; YamlMappingMapNode() { this = TYamlMappingNode(mapping, i) } override string toString() { - result = "(Mapping " + i + ")" and not exists(mapping.getKeyNode(i).(YAMLScalar).getValue()) + result = "(Mapping " + i + ")" and not exists(mapping.getKeyNode(i).(YamlScalar).getValue()) or - result = "(Mapping " + i + ") " + mapping.getKeyNode(i).(YAMLScalar).getValue() + ":" + result = "(Mapping " + i + ") " + mapping.getKeyNode(i).(YamlScalar).getValue() + ":" } /** * Holds if this print node represents the `index`th mapping of `m`. */ - predicate maps(YAMLMapping m, int index) { + predicate maps(YamlMapping m, int index) { m = mapping and index = i } diff --git a/javascript/ql/lib/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll index e683fb0db2a..e443ede5104 100644 --- a/javascript/ql/lib/semmle/javascript/Regexp.qll +++ b/javascript/ql/lib/semmle/javascript/Regexp.qll @@ -1005,7 +1005,10 @@ module RegExpPatterns { * Gets a pattern that matches common top-level domain names in lower case. * DEPRECATED: use `getACommonTld` instead */ - deprecated predicate commonTLD = getACommonTld/0; + deprecated predicate commonTld = getACommonTld/0; + + /** DEPRECATED: Alias for commonTld */ + deprecated predicate commonTLD = commonTld/0; } /** diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index edf8296585a..24a901a0dcc 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -291,10 +291,13 @@ class StrictModeDecl extends KnownDirective { * "use asm"; * ``` */ -class ASMJSDirective extends KnownDirective { - ASMJSDirective() { this.getDirectiveText() = "use asm" } +class AsmJSDirective extends KnownDirective { + AsmJSDirective() { this.getDirectiveText() = "use asm" } } +/** DEPRECATED: Alias for AsmJSDirective */ +deprecated class ASMJSDirective = AsmJSDirective; + /** * A Babel directive. * diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll old mode 100755 new mode 100644 diff --git a/javascript/ql/lib/semmle/javascript/YAML.qll b/javascript/ql/lib/semmle/javascript/YAML.qll index 49e0d28ae28..e7b49165499 100644 --- a/javascript/ql/lib/semmle/javascript/YAML.qll +++ b/javascript/ql/lib/semmle/javascript/YAML.qll @@ -20,13 +20,13 @@ import javascript * << : *DEFAULTS # an alias node referring to anchor `DEFAULTS` * ``` */ -class YAMLNode extends @yaml_node, Locatable { +class YamlNode extends @yaml_node, Locatable { override Location getLocation() { yaml_locations(this, result) } /** * Gets the parent node of this node, which is always a collection. */ - YAMLCollection getParentNode() { yaml(this, _, result, _, _, _) } + YamlCollection getParentNode() { yaml(this, _, result, _, _, _) } /** * Gets the `i`th child node of this node. @@ -34,12 +34,12 @@ class YAMLNode extends @yaml_node, Locatable { * _Note_: The index of a child node relative to its parent is considered * an implementation detail and may change between versions of the extractor. */ - YAMLNode getChildNode(int i) { yaml(result, _, this, i, _, _) } + YamlNode getChildNode(int i) { yaml(result, _, this, i, _, _) } /** * Gets a child node of this node. */ - YAMLNode getAChildNode() { result = this.getChildNode(_) } + YamlNode getAChildNode() { result = this.getChildNode(_) } /** * Gets the number of child nodes of this node. @@ -49,12 +49,12 @@ class YAMLNode extends @yaml_node, Locatable { /** * Gets the `i`th child of this node, as a YAML value. */ - YAMLValue getChild(int i) { result = this.getChildNode(i).eval() } + YamlValue getChild(int i) { result = this.getChildNode(i).eval() } /** * Gets a child of this node, as a YAML value. */ - YAMLValue getAChild() { result = this.getChild(_) } + YamlValue getAChild() { result = this.getChild(_) } /** * Gets the tag of this node. @@ -79,16 +79,19 @@ class YAMLNode extends @yaml_node, Locatable { /** * Gets the toplevel document to which this node belongs. */ - YAMLDocument getDocument() { result = this.getParentNode*() } + YamlDocument getDocument() { result = this.getParentNode*() } /** * Gets the YAML value this node corresponds to after resolving aliases and includes. */ - YAMLValue eval() { result = this } + YamlValue eval() { result = this } - override string getAPrimaryQlClass() { result = "YAMLNode" } + override string getAPrimaryQlClass() { result = "YamlNode" } } +/** DEPRECATED: Alias for YamlNode */ +deprecated class YAMLNode = YamlNode; + /** * A YAML value; that is, either a scalar or a collection. * @@ -102,7 +105,10 @@ class YAMLNode extends @yaml_node, Locatable { * - sequence * ``` */ -abstract class YAMLValue extends YAMLNode { } +abstract class YamlValue extends YamlNode { } + +/** DEPRECATED: Alias for YamlValue */ +deprecated class YAMLValue = YamlValue; /** * A YAML scalar. @@ -118,7 +124,7 @@ abstract class YAMLValue extends YAMLNode { } * "hello" * ``` */ -class YAMLScalar extends YAMLValue, @yaml_scalar_node { +class YamlScalar extends YamlValue, @yaml_scalar_node { /** * Gets the style of this scalar, which is one of the following: * @@ -147,9 +153,12 @@ class YAMLScalar extends YAMLValue, @yaml_scalar_node { */ string getValue() { yaml_scalars(this, _, result) } - override string getAPrimaryQlClass() { result = "YAMLScalar" } + override string getAPrimaryQlClass() { result = "YamlScalar" } } +/** DEPRECATED: Alias for YamlScalar */ +deprecated class YAMLScalar = YamlScalar; + /** * A YAML scalar representing an integer value. * @@ -160,8 +169,8 @@ class YAMLScalar extends YAMLValue, @yaml_scalar_node { * 0xffff * ``` */ -class YAMLInteger extends YAMLScalar { - YAMLInteger() { this.hasStandardTypeTag("int") } +class YamlInteger extends YamlScalar { + YamlInteger() { this.hasStandardTypeTag("int") } /** * Gets the value of this scalar, as an integer. @@ -169,6 +178,9 @@ class YAMLInteger extends YAMLScalar { int getIntValue() { result = this.getValue().toInt() } } +/** DEPRECATED: Alias for YamlInteger */ +deprecated class YAMLInteger = YamlInteger; + /** * A YAML scalar representing a floating point value. * @@ -179,8 +191,8 @@ class YAMLInteger extends YAMLScalar { * 6.626e-34 * ``` */ -class YAMLFloat extends YAMLScalar { - YAMLFloat() { this.hasStandardTypeTag("float") } +class YamlFloat extends YamlScalar { + YamlFloat() { this.hasStandardTypeTag("float") } /** * Gets the value of this scalar, as a floating point number. @@ -188,6 +200,9 @@ class YAMLFloat extends YAMLScalar { float getFloatValue() { result = this.getValue().toFloat() } } +/** DEPRECATED: Alias for YamlFloat */ +deprecated class YAMLFloat = YamlFloat; + /** * A YAML scalar representing a time stamp. * @@ -197,8 +212,8 @@ class YAMLFloat extends YAMLScalar { * 2001-12-15T02:59:43.1Z * ``` */ -class YAMLTimestamp extends YAMLScalar { - YAMLTimestamp() { this.hasStandardTypeTag("timestamp") } +class YamlTimestamp extends YamlScalar { + YamlTimestamp() { this.hasStandardTypeTag("timestamp") } /** * Gets the value of this scalar, as a date. @@ -206,6 +221,9 @@ class YAMLTimestamp extends YAMLScalar { date getDateValue() { result = this.getValue().toDate() } } +/** DEPRECATED: Alias for YamlTimestamp */ +deprecated class YAMLTimestamp = YamlTimestamp; + /** * A YAML scalar representing a Boolean value. * @@ -215,8 +233,8 @@ class YAMLTimestamp extends YAMLScalar { * true * ``` */ -class YAMLBool extends YAMLScalar { - YAMLBool() { this.hasStandardTypeTag("bool") } +class YamlBool extends YamlScalar { + YamlBool() { this.hasStandardTypeTag("bool") } /** * Gets the value of this scalar, as a Boolean. @@ -224,6 +242,9 @@ class YAMLBool extends YAMLScalar { boolean getBoolValue() { if this.getValue() = "true" then result = true else result = false } } +/** DEPRECATED: Alias for YamlBool */ +deprecated class YAMLBool = YamlBool; + /** * A YAML scalar representing the null value. * @@ -233,10 +254,13 @@ class YAMLBool extends YAMLScalar { * null * ``` */ -class YAMLNull extends YAMLScalar { - YAMLNull() { this.hasStandardTypeTag("null") } +class YamlNull extends YamlScalar { + YamlNull() { this.hasStandardTypeTag("null") } } +/** DEPRECATED: Alias for YamlNull */ +deprecated class YAMLNull = YamlNull; + /** * A YAML scalar representing a string value. * @@ -246,10 +270,13 @@ class YAMLNull extends YAMLScalar { * "hello" * ``` */ -class YAMLString extends YAMLScalar { - YAMLString() { this.hasStandardTypeTag("str") } +class YamlString extends YamlScalar { + YamlString() { this.hasStandardTypeTag("str") } } +/** DEPRECATED: Alias for YamlString */ +deprecated class YAMLString = YamlString; + /** * A YAML scalar representing a merge key. * @@ -260,10 +287,13 @@ class YAMLString extends YAMLScalar { * << : *DEFAULTS # merge key * ``` */ -class YAMLMergeKey extends YAMLScalar { - YAMLMergeKey() { this.hasStandardTypeTag("merge") } +class YamlMergeKey extends YamlScalar { + YamlMergeKey() { this.hasStandardTypeTag("merge") } } +/** DEPRECATED: Alias for YamlMergeKey */ +deprecated class YAMLMergeKey = YamlMergeKey; + /** * A YAML scalar representing an `!include` directive. * @@ -271,11 +301,11 @@ class YAMLMergeKey extends YAMLScalar { * !include common.yaml * ``` */ -class YAMLInclude extends YAMLScalar { - YAMLInclude() { this.getTag() = "!include" } +class YamlInclude extends YamlScalar { + YamlInclude() { this.getTag() = "!include" } - override YAMLValue eval() { - exists(YAMLDocument targetDoc | + override YamlValue eval() { + exists(YamlDocument targetDoc | targetDoc.getFile().getAbsolutePath() = this.getTargetPath() and result = targetDoc.eval() ) @@ -293,6 +323,9 @@ class YAMLInclude extends YAMLScalar { } } +/** DEPRECATED: Alias for YamlInclude */ +deprecated class YAMLInclude = YamlInclude; + /** * A YAML collection, that is, either a mapping or a sequence. * @@ -310,10 +343,13 @@ class YAMLInclude extends YAMLScalar { * - -blue * ``` */ -class YAMLCollection extends YAMLValue, @yaml_collection_node { - override string getAPrimaryQlClass() { result = "YAMLCollection" } +class YamlCollection extends YamlValue, @yaml_collection_node { + override string getAPrimaryQlClass() { result = "YamlCollection" } } +/** DEPRECATED: Alias for YamlCollection */ +deprecated class YAMLCollection = YamlCollection; + /** * A YAML mapping. * @@ -324,11 +360,11 @@ class YAMLCollection extends YAMLValue, @yaml_collection_node { * y: 1 * ``` */ -class YAMLMapping extends YAMLCollection, @yaml_mapping_node { +class YamlMapping extends YamlCollection, @yaml_mapping_node { /** * Gets the `i`th key of this mapping. */ - YAMLNode getKeyNode(int i) { + YamlNode getKeyNode(int i) { i >= 0 and exists(int j | i = j - 1 and result = this.getChildNode(j)) } @@ -336,7 +372,7 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node { /** * Gets the `i`th value of this mapping. */ - YAMLNode getValueNode(int i) { + YamlNode getValueNode(int i) { i >= 0 and exists(int j | i = -j - 1 and result = this.getChildNode(j)) } @@ -344,30 +380,33 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node { /** * Gets the `i`th key of this mapping, as a YAML value. */ - YAMLValue getKey(int i) { result = this.getKeyNode(i).eval() } + YamlValue getKey(int i) { result = this.getKeyNode(i).eval() } /** * Gets the `i`th value of this mapping, as a YAML value. */ - YAMLValue getValue(int i) { result = this.getValueNode(i).eval() } + YamlValue getValue(int i) { result = this.getValueNode(i).eval() } /** * Holds if this mapping maps `key` to `value`. */ - predicate maps(YAMLValue key, YAMLValue value) { + predicate maps(YamlValue key, YamlValue value) { exists(int i | key = this.getKey(i) and value = this.getValue(i)) or - exists(YAMLMergeKey merge, YAMLMapping that | this.maps(merge, that) | that.maps(key, value)) + exists(YamlMergeKey merge, YamlMapping that | this.maps(merge, that) | that.maps(key, value)) } /** * Gets the value that this mapping maps `key` to. */ - YAMLValue lookup(string key) { exists(YAMLScalar s | s.getValue() = key | this.maps(s, result)) } + YamlValue lookup(string key) { exists(YamlScalar s | s.getValue() = key | this.maps(s, result)) } - override string getAPrimaryQlClass() { result = "YAMLMapping" } + override string getAPrimaryQlClass() { result = "YamlMapping" } } +/** DEPRECATED: Alias for YamlMapping */ +deprecated class YAMLMapping = YamlMapping; + /** * A YAML sequence. * @@ -379,20 +418,23 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node { * - blue * ``` */ -class YAMLSequence extends YAMLCollection, @yaml_sequence_node { +class YamlSequence extends YamlCollection, @yaml_sequence_node { /** * Gets the `i`th element in this sequence. */ - YAMLNode getElementNode(int i) { result = this.getChildNode(i) } + YamlNode getElementNode(int i) { result = this.getChildNode(i) } /** * Gets the `i`th element in this sequence, as a YAML value. */ - YAMLValue getElement(int i) { result = this.getElementNode(i).eval() } + YamlValue getElement(int i) { result = this.getElementNode(i).eval() } - override string getAPrimaryQlClass() { result = "YAMLSequence" } + override string getAPrimaryQlClass() { result = "YamlSequence" } } +/** DEPRECATED: Alias for YamlSequence */ +deprecated class YAMLSequence = YamlSequence; + /** * A YAML alias node referring to a target anchor. * @@ -402,8 +444,8 @@ class YAMLSequence extends YAMLCollection, @yaml_sequence_node { * *DEFAULTS * ``` */ -class YAMLAliasNode extends YAMLNode, @yaml_alias_node { - override YAMLValue eval() { +class YamlAliasNode extends YamlNode, @yaml_alias_node { + override YamlValue eval() { result.getAnchor() = this.getTarget() and result.getDocument() = this.getDocument() } @@ -413,9 +455,12 @@ class YAMLAliasNode extends YAMLNode, @yaml_alias_node { */ string getTarget() { yaml_aliases(this, result) } - override string getAPrimaryQlClass() { result = "YAMLAliasNode" } + override string getAPrimaryQlClass() { result = "YamlAliasNode" } } +/** DEPRECATED: Alias for YamlAliasNode */ +deprecated class YAMLAliasNode = YamlAliasNode; + /** * A YAML document. * @@ -427,14 +472,17 @@ class YAMLAliasNode extends YAMLNode, @yaml_alias_node { * y: 1 * ``` */ -class YAMLDocument extends YAMLNode { - YAMLDocument() { not exists(this.getParentNode()) } +class YamlDocument extends YamlNode { + YamlDocument() { not exists(this.getParentNode()) } } +/** DEPRECATED: Alias for YamlDocument */ +deprecated class YAMLDocument = YamlDocument; + /** * An error message produced by the YAML parser while processing a YAML file. */ -class YAMLParseError extends @yaml_error, Error { +class YamlParseError extends @yaml_error, Error { override Location getLocation() { yaml_locations(this, result) } override string getMessage() { yaml_errors(this, result) } @@ -442,6 +490,9 @@ class YAMLParseError extends @yaml_error, Error { override string toString() { result = this.getMessage() } } +/** DEPRECATED: Alias for YamlParseError */ +deprecated class YAMLParseError = YamlParseError; + /** * A YAML node that may contain sub-nodes that can be identified by a name. * I.e. a mapping, sequence, or scalar. @@ -464,30 +515,30 @@ class YAMLParseError extends @yaml_error, Error { * * are equivalent. */ -class YAMLMappingLikeNode extends YAMLNode { - YAMLMappingLikeNode() { - this instanceof YAMLMapping +class YamlMappingLikeNode extends YamlNode { + YamlMappingLikeNode() { + this instanceof YamlMapping or - this instanceof YAMLSequence + this instanceof YamlSequence or - this instanceof YAMLScalar + this instanceof YamlScalar } /** Gets sub-name identified by `name`. */ - YAMLNode getNode(string name) { - exists(YAMLMapping mapping | + YamlNode getNode(string name) { + exists(YamlMapping mapping | mapping = this and result = mapping.lookup(name) ) or - exists(YAMLSequence sequence, YAMLNode node | + exists(YamlSequence sequence, YamlNode node | sequence = this and sequence.getAChildNode() = node and node.eval().toString() = name and result = node ) or - exists(YAMLScalar scalar | + exists(YamlScalar scalar | scalar = this and scalar.getValue() = name and result = scalar @@ -496,19 +547,22 @@ class YAMLMappingLikeNode extends YAMLNode { /** Gets the number of elements in this mapping or sequence. */ int getElementCount() { - exists(YAMLMapping mapping | + exists(YamlMapping mapping | mapping = this and result = mapping.getNumChild() / 2 ) or - exists(YAMLSequence sequence | + exists(YamlSequence sequence | sequence = this and result = sequence.getNumChild() ) or - exists(YAMLScalar scalar | + exists(YamlScalar scalar | scalar = this and result = 1 ) } } + +/** DEPRECATED: Alias for YamlMappingLikeNode */ +deprecated class YAMLMappingLikeNode = YamlMappingLikeNode; diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll index 94a6532b107..e616772e789 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -89,6 +89,18 @@ module CallGraph { result = getAFunctionReference(outer, 0, t.continue()).getAnInvocation() and locallyReturnedFunction(outer, function) ) + or + // dynamic dispatch to unknown property of an object + exists(DataFlow::ObjectLiteralNode obj, DataFlow::PropRead read | + getAFunctionReference(function, 0, t.continue()) = obj.getAPropertySource() and + obj.getAPropertyRead() = read and + not exists(read.getPropertyName()) and + result = read and + // there exists only local reads of the object, nothing else. + forex(DataFlow::Node ref | ref = obj.getALocalUse() and exists(ref.asExpr()) | + ref = [obj, any(DataFlow::PropRead r).getBase()] + ) + ) } private predicate locallyReturnedFunction( diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll index 6105b1b8115..2ac0c0bbad6 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll @@ -171,10 +171,10 @@ abstract class CallWithNonLocalAnalyzedReturnFlow extends DataFlow::AnalyzedValu /** * Flow analysis for the return value of IIFEs. */ -private class IIFEWithAnalyzedReturnFlow extends CallWithAnalyzedReturnFlow { +private class IifeWithAnalyzedReturnFlow extends CallWithAnalyzedReturnFlow { ImmediatelyInvokedFunctionExpr iife; - IIFEWithAnalyzedReturnFlow() { astNode = iife.getInvocation() } + IifeWithAnalyzedReturnFlow() { astNode = iife.getInvocation() } override AnalyzedFunction getACallee() { result = iife.analyze() } } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll index f2b905086c5..b55c0ddc302 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll @@ -692,10 +692,10 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa /** * Flow analysis for simple parameters of IIFEs. */ -private class IIFEWithAnalyzedParameters extends CallWithAnalyzedParameters { +private class IifeWithAnalyzedParameters extends CallWithAnalyzedParameters { ImmediatelyInvokedFunctionExpr iife; - IIFEWithAnalyzedParameters() { + IifeWithAnalyzedParameters() { this = iife and iife.getInvocationKind() = "direct" } diff --git a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll index 1f47bd3e350..024a966bf21 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll @@ -276,15 +276,15 @@ class ExternalScriptDependency extends ScriptDependency, @xmlattribute { /** * A dependency on GWT indicated by a GWT header script. */ -private class GWTDependency extends ScriptDependency { - GWTDependency() { this instanceof GWTHeader } +private class GwtDependency extends ScriptDependency { + GwtDependency() { this instanceof GwtHeader } override predicate info(string id, string v) { id = "gwt" and - exists(GWTHeader h | h = this | - v = h.getGWTVersion() + exists(GwtHeader h | h = this | + v = h.getGwtVersion() or - not exists(h.getGWTVersion()) and v = "unknown" + not exists(h.getGwtVersion()) and v = "unknown" ) } diff --git a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll index 0d4664a79f4..1b0c00f6b7b 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll @@ -904,8 +904,8 @@ private class SinonJS extends FrameworkLibraryWithGenericUrl, FrameworkLibraryWi /** * The TinyMCE framework. */ -private class TinyMCE extends FrameworkLibraryWithGenericUrl { - TinyMCE() { this = "tinymce" } +private class TinyMce extends FrameworkLibraryWithGenericUrl { + TinyMce() { this = "tinymce" } override string getAnAlias() { result = "jquery.tinymce" or result = "tinymce.jquery" } } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll index 038f4b8afb3..5ec9c8edcf9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll @@ -112,7 +112,7 @@ module Electron { */ class ProcessSender extends Process { ProcessSender() { - exists(IPCSendRegistration reg | reg.getEmitter() instanceof MainProcess | + exists(IpcSendRegistration reg | reg.getEmitter() instanceof MainProcess | this = reg.getABoundCallbackParameter(1, 0).getAPropertyRead("sender") ) } @@ -123,28 +123,31 @@ module Electron { * Does mostly the same as an EventEmitter event handler, * except that values can be returned through the `event.returnValue` property. */ - class IPCSendRegistration extends EventRegistration::DefaultEventRegistration, + class IpcSendRegistration extends EventRegistration::DefaultEventRegistration, DataFlow::MethodCallNode { override Process emitter; - IPCSendRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) } + IpcSendRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) } override DataFlow::Node getAReturnedValue() { result = this.getABoundCallbackParameter(1, 0).getAPropertyWrite("returnValue").getRhs() } - override IPCDispatch getAReturnDispatch() { result.getCalleeName() = "sendSync" } + override IpcDispatch getAReturnDispatch() { result.getCalleeName() = "sendSync" } } + /** DEPRECATED: Alias for IpcSendRegistration */ + deprecated class IPCSendRegistration = IpcSendRegistration; + /** * A dispatch of an IPC event. * An IPC event is sent from the renderer to the main process. * And a value can be returned through the `returnValue` property of the event (first parameter in the callback). */ - class IPCDispatch extends EventDispatch::DefaultEventDispatch, DataFlow::InvokeNode { + class IpcDispatch extends EventDispatch::DefaultEventDispatch, DataFlow::InvokeNode { override Process emitter; - IPCDispatch() { + IpcDispatch() { exists(string methodName | methodName = "sendSync" or methodName = "send" | this = emitter.ref().getAMemberCall(methodName) ) @@ -163,7 +166,7 @@ module Electron { /** * Gets a registration that this dispatch can send an event to. */ - override IPCSendRegistration getAReceiver() { + override IpcSendRegistration getAReceiver() { this.getEmitter() instanceof RendererProcess and result.getEmitter() instanceof MainProcess or @@ -171,6 +174,9 @@ module Electron { result.getEmitter() instanceof RendererProcess } } + + /** DEPRECATED: Alias for IpcDispatch */ + deprecated class IPCDispatch = IpcDispatch; } /** diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll index 0e5575226f7..5c0128a57c6 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll @@ -13,10 +13,13 @@ abstract class EmscriptenMarkerComment extends GeneratedCodeMarkerComment { } /** * An `EMSCRIPTEN_START_ASM` marker comment. */ -class EmscriptenStartASMComment extends EmscriptenMarkerComment { - EmscriptenStartASMComment() { getText().trim() = "EMSCRIPTEN_START_ASM" } +class EmscriptenStartAsmComment extends EmscriptenMarkerComment { + EmscriptenStartAsmComment() { getText().trim() = "EMSCRIPTEN_START_ASM" } } +/** DEPRECATED: Alias for EmscriptenStartAsmComment */ +deprecated class EmscriptenStartASMComment = EmscriptenStartAsmComment; + /** * An `EMSCRIPTEN_START_FUNCS` marker comment. */ @@ -27,10 +30,13 @@ class EmscriptenStartFuncsComment extends EmscriptenMarkerComment { /** * An `EMSCRIPTEN_END_ASM` marker comment. */ -class EmscriptenEndASMComment extends EmscriptenMarkerComment { - EmscriptenEndASMComment() { getText().trim() = "EMSCRIPTEN_END_ASM" } +class EmscriptenEndAsmComment extends EmscriptenMarkerComment { + EmscriptenEndAsmComment() { getText().trim() = "EMSCRIPTEN_END_ASM" } } +/** DEPRECATED: Alias for EmscriptenEndAsmComment */ +deprecated class EmscriptenEndASMComment = EmscriptenEndAsmComment; + /** * An `EMSCRIPTEN_END_FUNCS` marker comment. */ diff --git a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll index 608f3d8b1fd..7450c48378b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll @@ -7,32 +7,44 @@ import javascript /** * A `$gwt_version` variable. */ -class GWTVersionVariable extends GlobalVariable { - GWTVersionVariable() { getName() = "$gwt_version" } +class GwtVersionVariable extends GlobalVariable { + GwtVersionVariable() { getName() = "$gwt_version" } } +/** DEPRECATED: Alias for GwtVersionVariable */ +deprecated class GWTVersionVariable = GwtVersionVariable; + /** * A GWT header script that defines the `$gwt_version` variable. */ -class GWTHeader extends InlineScript { - GWTHeader() { - exists(GWTVersionVariable gwtVersion | gwtVersion.getADeclaration().getTopLevel() = this) +class GwtHeader extends InlineScript { + GwtHeader() { + exists(GwtVersionVariable gwtVersion | gwtVersion.getADeclaration().getTopLevel() = this) } /** * Gets the GWT version this script was generated with, if it can be determined. */ - string getGWTVersion() { + string getGwtVersion() { exists(Expr e | e.getTopLevel() = this | - e = any(GWTVersionVariable v).getAnAssignedExpr() and + e = any(GwtVersionVariable v).getAnAssignedExpr() and result = e.getStringValue() ) } + + /** DEPRECATED: Alias for getGwtVersion */ + deprecated string getGWTVersion() { result = getGwtVersion() } } +/** DEPRECATED: Alias for GwtHeader */ +deprecated class GWTHeader = GwtHeader; + /** * A toplevel in a file that appears to be GWT-generated. */ -class GWTGeneratedTopLevel extends TopLevel { - GWTGeneratedTopLevel() { exists(GWTHeader h | getFile() = h.getFile()) } +class GwtGeneratedTopLevel extends TopLevel { + GwtGeneratedTopLevel() { exists(GwtHeader h | getFile() = h.getFile()) } } + +/** DEPRECATED: Alias for GwtGeneratedTopLevel */ +deprecated class GWTGeneratedTopLevel = GwtGeneratedTopLevel; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll index 0eccacac0b7..6eace6700ae 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll @@ -15,21 +15,21 @@ private module ServerLess { * `codeURI` defaults to the empty string if no explicit value is set in the configuration. */ private predicate hasServerlessHandler(File ymlFile, string handler, string codeUri) { - exists(YAMLMapping resource | ymlFile = resource.getFile() | + exists(YamlMapping resource | ymlFile = resource.getFile() | // There exists at least "AWS::Serverless::Function" and "Aliyun::Serverless::Function" - resource.lookup("Type").(YAMLScalar).getValue().regexpMatch(".*::Serverless::Function") and - exists(YAMLMapping properties | properties = resource.lookup("Properties") | - handler = properties.lookup("Handler").(YAMLScalar).getValue() and + resource.lookup("Type").(YamlScalar).getValue().regexpMatch(".*::Serverless::Function") and + exists(YamlMapping properties | properties = resource.lookup("Properties") | + handler = properties.lookup("Handler").(YamlScalar).getValue() and if exists(properties.lookup("CodeUri")) - then codeUri = properties.lookup("CodeUri").(YAMLScalar).getValue() + then codeUri = properties.lookup("CodeUri").(YamlScalar).getValue() else codeUri = "" ) or // The `serverless` library, which specifies a top-level `functions` property - exists(YAMLMapping functions | + exists(YamlMapping functions | functions = resource.lookup("functions") and not exists(resource.getParentNode()) and - handler = functions.getValue(_).(YAMLMapping).lookup("handler").(YAMLScalar).getValue() and + handler = functions.getValue(_).(YamlMapping).lookup("handler").(YamlScalar).getValue() and codeUri = "" ) ) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll index 6923d59124f..f8f0c2126f0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll @@ -27,8 +27,8 @@ class QUnitTest extends Test, @call_expr { * that is, an invocation of a function named `it` where the first argument * is a string and the second argument is a function. */ -class BDDTest extends Test, @call_expr { - BDDTest() { +class BddTest extends Test, @call_expr { + BddTest() { exists(CallExpr call | call = this | call.getCallee().(VarAccess).getName() = "it" and exists(call.getArgument(0).getStringValue()) and @@ -37,6 +37,9 @@ class BDDTest extends Test, @call_expr { } } +/** DEPRECATED: Alias for BddTest */ +deprecated class BDDTest = BddTest; + /** * Gets the test file for `f` with stem extension `stemExt`, where `stemExt` is "test" or "spec". * That is, a file named `..` in the diff --git a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll index 0f2b36216c9..d40a356f3bc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll @@ -281,7 +281,7 @@ private module JQueryClientRequest { .getParameter(0) or result = - getAResponseNodeFromAnXHRObject(this.getOptionArgument([0 .. 1], + getAResponseNodeFromAnXhrObject(this.getOptionArgument([0 .. 1], any(string method | method = "error" or method = "complete")) .getALocalSource() .(DataFlow::FunctionNode) @@ -303,15 +303,15 @@ private module JQueryClientRequest { .getParameter(0) or result = - getAResponseNodeFromAnXHRObject(request.getAMemberCall("fail").getCallback(0).getParameter(0)) + getAResponseNodeFromAnXhrObject(request.getAMemberCall("fail").getCallback(0).getParameter(0)) } /** * Gets a node referring to the response contained in an `jqXHR` object. */ - private DataFlow::SourceNode getAResponseNodeFromAnXHRObject(DataFlow::SourceNode jqXHR) { + private DataFlow::SourceNode getAResponseNodeFromAnXhrObject(DataFlow::SourceNode jqXhr) { result = - jqXHR + jqXhr .getAPropertyRead(any(string s | s = "responseText" or s = "responseXML" diff --git a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll index 32b9f217a27..76164f25f18 100644 --- a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll +++ b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll @@ -60,7 +60,7 @@ module ESLint { } /** An `.eslintrc.yaml` file. */ - private class EslintrcYaml extends Configuration, YAMLDocument, YAMLMapping { + private class EslintrcYaml extends Configuration, YamlDocument, YamlMapping { EslintrcYaml() { exists(string n | n = getFile().getBaseName() | n = ".eslintrc.yaml" or n = ".eslintrc.yml" or n = ".eslintrc" @@ -71,11 +71,11 @@ module ESLint { } /** An ESLint configuration object in YAML format. */ - private class YamlConfigurationObject extends ConfigurationObject, YAMLMapping { + private class YamlConfigurationObject extends ConfigurationObject, YamlMapping { override Configuration getConfiguration() { this = result.(EslintrcYaml).getValue(_) } override boolean getBooleanProperty(string p) { - exists(string v | v = lookup(p).(YAMLBool).getValue() | + exists(string v | v = lookup(p).(YamlBool).getValue() | v = "true" and result = true or v = "false" and result = false diff --git a/javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll b/javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll index 3a8bf058df8..f83a6411618 100644 --- a/javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/OverlyLargeRangeQuery.qll @@ -238,8 +238,13 @@ module RangePrinter { /** Gets a char range that is overly large because of `reason`. */ RegExpCharacterRange getABadRange(string reason, int priority) { + result instanceof OverlyWideRange and priority = 0 and - reason = "is equivalent to " + result.(OverlyWideRange).printEquivalent() + exists(string equiv | equiv = result.(OverlyWideRange).printEquivalent() | + if equiv.length() <= 50 + then reason = "is equivalent to " + equiv + else reason = "is equivalent to " + equiv.substring(0, 50) + "..." + ) or priority = 1 and exists(RegExpCharacterRange other | diff --git a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll index e31b482c25f..183fca296c7 100644 --- a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll @@ -21,11 +21,11 @@ predicate config(string key, string val, Locatable valElement) { val = valElement.(JsonString).getValue() ) or - exists(YAMLMapping m, YAMLString keyElement | + exists(YamlMapping m, YamlString keyElement | m.maps(keyElement, valElement) and key = keyElement.getValue() and ( - val = valElement.(YAMLString).getValue() + val = valElement.(YamlString).getValue() or valElement.toString() = "" and val = "" diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index 3f0f569eff6..bd3aa65aa4d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -67,10 +67,10 @@ module XssThroughDom { /** * A source for text from a DOM property read by jQuery. */ - class JQueryDOMPropertySource extends DomPropertySource instanceof JQuery::MethodCall { + class JQueryDomPropertySource extends DomPropertySource instanceof JQuery::MethodCall { string prop; - JQueryDOMPropertySource() { + JQueryDomPropertySource() { exists(string methodName | this.getMethodName() = methodName and this.getNumArgument() = 1 and @@ -87,6 +87,9 @@ module XssThroughDom { override string getPropertyName() { result = prop } } + /** DEPRECATED: Alias for JQueryDomPropertySource */ + deprecated class JQueryDOMPropertySource = JQueryDomPropertySource; + /** * A source for text from the DOM from a `d3` method call. */ diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll b/javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll index 000c247fc71..d006837466b 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/ExponentialBackTracking.qll @@ -115,6 +115,7 @@ private newtype TStatePair = private int rankState(State state) { state = rank[result](State s, Location l | + stateInsideBacktracking(s) and l = s.getRepr().getLocation() | s order by l.getStartLine(), l.getStartColumn(), s.toString() diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll index fdcb10c2f85..033b8aa8cfd 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll @@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm { * Holds if this root term is relevant to the ReDoS analysis. */ predicate isRelevant() { - // there is at least one repetition - getRoot(any(InfiniteRepetitionQuantifier q)) = this and // is actually used as a RegExp this.isUsedAsRegExp() and // not excluded for library specific reasons @@ -877,6 +875,101 @@ predicate isStartState(State state) { */ signature predicate isCandidateSig(State state, string pump); +/** + * Holds if `state` is a candidate for ReDoS. + */ +signature predicate isCandidateSig(State state); + +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +module PrefixConstruction { + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + s = stateInRelevantRegexp() and + isStartState(s) and + getRoot(s.getRepr()) = root and + l = s.getRepr().getLocation() + | + s + order by + l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), + l.getEndLine() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s + order by + loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), + s.getRepr().toString() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = prefix(prev) + getCanonicalEdgeChar(prev, state) + ) + } + + /** + * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. + */ + private string getCanonicalEdgeChar(State prev, State next) { + result = + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) + } + + /** Gets a state within a regular expression that contains a candidate state. */ + pragma[noinline] + State stateInRelevantRegexp() { + exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr())) + } +} + /** * A module for pruning candidate ReDoS states. * The candidates are specified by the `isCandidate` signature predicate. @@ -910,95 +1003,9 @@ module ReDoSPruning { /** Gets a state that can reach the `accept-any` state using only epsilon steps. */ private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) } - /** - * Predicates for constructing a prefix string that leads to a given state. - */ - private module PrefixConstruction { - /** - * Holds if `state` is the textually last start state for the regular expression. - */ - private predicate lastStartState(State state) { - exists(RegExpRoot root | - state = - max(State s, Location l | - s = stateInPumpableRegexp() and - isStartState(s) and - getRoot(s.getRepr()) = root and - l = s.getRepr().getLocation() - | - s - order by - l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), - l.getEndLine() - ) - ) - } + predicate isCandidateState(State s) { isReDoSCandidate(s, _) } - /** - * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. - */ - private predicate existsTransition(State a, State b) { delta(a, _, b) } - - /** - * Gets the minimum number of transitions it takes to reach `state` from the `start` state. - */ - int prefixLength(State start, State state) = - shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) - - /** - * Gets the minimum number of transitions it takes to reach `state` from the start state. - */ - private int lengthFromStart(State state) { result = prefixLength(_, state) } - - /** - * Gets a string for which the regular expression will reach `state`. - * - * Has at most one result for any given `state`. - * This predicate will not always have a result even if there is a ReDoS issue in - * the regular expression. - */ - string prefix(State state) { - lastStartState(state) and - result = "" - or - // the search stops past the last redos candidate state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and - exists(State prev | - // select a unique predecessor (by an arbitrary measure) - prev = - min(State s, Location loc | - lengthFromStart(s) = lengthFromStart(state) - 1 and - loc = s.getRepr().getLocation() and - delta(s, _, state) - | - s - order by - loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), - s.getRepr().toString() - ) - | - // greedy search for the shortest prefix - result = prefix(prev) and delta(prev, Epsilon(), state) - or - not delta(prev, Epsilon(), state) and - result = prefix(prev) + getCanonicalEdgeChar(prev, state) - ) - } - - /** - * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. - */ - private string getCanonicalEdgeChar(State prev, State next) { - result = - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) - } - - /** Gets a state within a regular expression that has a pumpable state. */ - pragma[noinline] - State stateInPumpableRegexp() { - exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) - } - } + import PrefixConstruction as Prefix /** * Predicates for testing the presence of a rejecting suffix. @@ -1018,8 +1025,6 @@ module ReDoSPruning { * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ private module SuffixConstruction { - import PrefixConstruction - /** * Holds if all states reachable from `fork` by repeating `w` * are likely rejectable by appending some suffix. @@ -1036,7 +1041,7 @@ module ReDoSPruning { */ pragma[noinline] private predicate isLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and ( // exists a reject edge with some char. hasRejectEdge(s) @@ -1052,7 +1057,7 @@ module ReDoSPruning { * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. */ predicate isRejectState(State s) { - s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) + s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_) } /** @@ -1060,7 +1065,7 @@ module ReDoSPruning { */ pragma[noopt] predicate hasEdgeToLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | @@ -1076,7 +1081,7 @@ module ReDoSPruning { */ pragma[noinline] private string hasEdgeToLikelyRejectableHelper(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and not hasRejectEdge(s) and not isRejectState(s) and deltaClosedChar(s, result, _) @@ -1088,8 +1093,8 @@ module ReDoSPruning { * `prev` to `next` that the character symbol `char`. */ predicate deltaClosedChar(State prev, string char, State next) { - prev = stateInPumpableRegexp() and - next = stateInPumpableRegexp() and + prev = Prefix::stateInRelevantRegexp() and + next = Prefix::stateInRelevantRegexp() and deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) } @@ -1099,18 +1104,28 @@ module ReDoSPruning { result = getAnInputSymbolMatching(char) } + pragma[noinline] + RegExpRoot relevantRoot() { + exists(RegExpTerm term, State s | + s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm() + ) + } + /** * Gets a char used for finding possible suffixes inside `root`. */ pragma[noinline] private string relevant(RegExpRoot root) { - exists(ascii(result)) and exists(root) - or - exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) - or - // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). - // The three chars must be kept in sync with `hasSimpleRejectEdge`. - result = ["|", "\n", "Z"] and exists(root) + root = relevantRoot() and + ( + exists(ascii(result)) and exists(root) + or + exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + or + // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). + // The three chars must be kept in sync with `hasSimpleRejectEdge`. + result = ["|", "\n", "Z"] and exists(root) + ) } /** @@ -1208,12 +1223,12 @@ module ReDoSPruning { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { isReDoSAttackable(t, pump, s) and ( - prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and - not PrefixConstruction::prefix(s) = "" + prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and + not Prefix::prefix(s) = "" or - PrefixConstruction::prefix(s) = "" and prefixMsg = "" + Prefix::prefix(s) = "" and prefixMsg = "" or - not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + not exists(Prefix::prefix(s)) and prefixMsg = "" ) } diff --git a/javascript/ql/src/Declarations/UnusedParameter.ql b/javascript/ql/src/Declarations/UnusedParameter.ql index 464c6762e06..d48dc11ed2a 100644 --- a/javascript/ql/src/Declarations/UnusedParameter.ql +++ b/javascript/ql/src/Declarations/UnusedParameter.ql @@ -13,4 +13,4 @@ import UnusedParameter from Parameter p where isAnAccidentallyUnusedParameter(p) -select p, "Unused parameter " + p.getAVariable().getName() + "." +select p, "The parameter '" + p.getVariable().getName() + "' is never used." diff --git a/javascript/ql/src/Expressions/BitwiseSignCheck.ql b/javascript/ql/src/Expressions/BitwiseSignCheck.ql index 658960e39af..a26e846ee7b 100644 --- a/javascript/ql/src/Expressions/BitwiseSignCheck.ql +++ b/javascript/ql/src/Expressions/BitwiseSignCheck.ql @@ -53,4 +53,4 @@ where not e instanceof EqualityTest and e.getRightOperand().getIntValue() = 0 and not acceptableSignCheck(b) -select e, "Sign check of a bitwise operation" +select e, "Potentially unsafe sign check of a bitwise operation." diff --git a/javascript/ql/src/Security/CWE-022/TaintedPath.ql b/javascript/ql/src/Security/CWE-022/TaintedPath.ql index 0c19137f38c..a788b13bb03 100644 --- a/javascript/ql/src/Security/CWE-022/TaintedPath.ql +++ b/javascript/ql/src/Security/CWE-022/TaintedPath.ql @@ -21,5 +21,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(), + "User-provided value" diff --git a/javascript/ql/src/Security/CWE-022/ZipSlip.ql b/javascript/ql/src/Security/CWE-022/ZipSlip.ql index 6daa4f01969..0380031ad66 100644 --- a/javascript/ql/src/Security/CWE-022/ZipSlip.ql +++ b/javascript/ql/src/Security/CWE-022/ZipSlip.ql @@ -18,6 +18,6 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "Unsanitized zip archive $@, which may contain '..', is used in a file system operation.", - source.getNode(), "item path" +select source.getNode(), source, sink, + "Unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(), + "file system operation" diff --git a/javascript/ql/src/Security/CWE-078/CommandInjection.ql b/javascript/ql/src/Security/CWE-078/CommandInjection.ql index 7bb57bfa6da..dd9ebce6b72 100644 --- a/javascript/ql/src/Security/CWE-078/CommandInjection.ql +++ b/javascript/ql/src/Security/CWE-078/CommandInjection.ql @@ -28,5 +28,5 @@ where else highlight = sink.getNode() ) and sourceNode = source.getNode() -select highlight, source, sink, "This command depends on $@.", sourceNode, +select highlight, source, sink, "$@ flows to here and is used in a command.", source.getNode(), sourceNode.getSourceType() diff --git a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql index 06f44703a5d..b0462bd3668 100644 --- a/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql +++ b/javascript/ql/src/Security/CWE-134/TaintedFormatString.ql @@ -16,5 +16,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows here and is used in a format string.", +select sink.getNode(), source, sink, "$@ flows to here and is used in a format string.", source.getNode(), "User-provided value" diff --git a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql index ccf659bf024..e8835436c72 100644 --- a/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql +++ b/javascript/ql/src/Security/CWE-178/CaseSensitiveMiddlewarePath.ql @@ -20,55 +20,29 @@ string toOtherCase(string s) { if s.regexpMatch(".*[a-z].*") then result = s.toUpperCase() else result = s.toLowerCase() } -RegExpCharacterClass getEnclosingClass(RegExpTerm term) { - term = result.getAChild() - or - term = result.getAChild().(RegExpRange).getAChild() -} +import semmle.javascript.security.regexp.NfaUtils as NfaUtils -/** - * Holds if `term` seems to distinguish between upper and lower case letters, assuming the `i` flag is not present. - */ -pragma[inline] -predicate isLikelyCaseSensitiveRegExp(RegExpTerm term) { - exists(RegExpConstant const | - const = term.getAChild*() and - const.getValue().regexpMatch(".*[a-zA-Z].*") and - not getEnclosingClass(const).getAChild().(RegExpConstant).getValue() = - toOtherCase(const.getValue()) and - not const.getParent*() instanceof RegExpNegativeLookahead and - not const.getParent*() instanceof RegExpNegativeLookbehind +/** Holds if `s` is a relevant regexp term were we want to compute a string that matches the term (for `getCaseSensitiveBypassExample`). */ +predicate isCand(NfaUtils::State s) { + s.getRepr() instanceof NfaUtils::RegExpRoot and + exists(DataFlow::RegExpCreationNode creation | + isCaseSensitiveMiddleware(_, creation, _) and + s.getRepr().getRootTerm() = creation.getRoot() ) } -/** - * Gets a string matched by `term`, or part of such a string. - */ +import NfaUtils::PrefixConstruction as Prefix + +/** Gets a string matched by `term`. */ string getExampleString(RegExpTerm term) { - result = term.getAMatchedString() - or - // getAMatchedString does not recurse into sequences. Perform one step manually. - exists(RegExpSequence seq | seq = term | - result = - strictconcat(RegExpTerm child, int i, string text | - child = seq.getChild(i) and - ( - text = child.getAMatchedString() - or - not exists(child.getAMatchedString()) and - text = "" - ) - | - text order by i - ) - ) + result = Prefix::prefix(any(NfaUtils::State s | s.getRepr() = term)) } string getCaseSensitiveBypassExample(RegExpTerm term) { - exists(string example | - example = getExampleString(term) and - result = toOtherCase(example) and - result != example // getting an example string is approximate; ensure we got a proper case-change example + exists(string byPassExample | + byPassExample = getExampleString(term) and + result = toOtherCase(byPassExample) and + result != byPassExample // getting an byPassExample string is approximate; ensure we got a proper case-change byPassExample ) } @@ -89,7 +63,6 @@ predicate isCaseSensitiveMiddleware( ) and arg = call.getArgument(0) and regexp.getAReference().flowsTo(arg) and - isLikelyCaseSensitiveRegExp(regexp.getRoot()) and exists(string flags | flags = regexp.getFlags() and not RegExp::isIgnoreCase(flags) @@ -108,14 +81,64 @@ predicate isGuardedCaseInsensitiveEndpoint( ) } +/** + * Gets an example path that will hit `endpoint`. + * Query parameters (e.g. the ":param" in "/foo/:param") have been replaced with example values. + */ +string getAnEndpointExample(Routing::RouteSetup endpoint) { + exists(string raw | + raw = endpoint.getRelativePath() and + result = raw.regexpReplaceAll(":\\w+\\b|\\*", ["a", "1"]) + ) +} + +import semmle.javascript.security.regexp.RegexpMatching as RegexpMatching + +NfaUtils::RegExpRoot getARoot(DataFlow::RegExpCreationNode creator) { + result.getRootTerm() = creator.getRoot() +} + +/** + * Holds if the regexp matcher should test whether `root` matches `str`. + * The result is used to test whether a case-sensitive bypass exists. + */ +predicate isMatchingCandidate( + RegexpMatching::RootTerm root, string str, boolean ignorePrefix, boolean testWithGroups +) { + exists( + Routing::RouteSetup middleware, Routing::RouteSetup endPoint, + DataFlow::RegExpCreationNode regexp + | + isCaseSensitiveMiddleware(middleware, regexp, _) and + isGuardedCaseInsensitiveEndpoint(endPoint, middleware) + | + root = regexp.getRoot() and + exists(getCaseSensitiveBypassExample(getARoot(regexp))) and + ignorePrefix = true and + testWithGroups = false and + str = + [ + getCaseSensitiveBypassExample(getARoot(regexp)), getAnEndpointExample(endPoint), + toOtherCase(getAnEndpointExample(endPoint)) + ] + ) +} + +import RegexpMatching::RegexpMatching as Matcher + from DataFlow::RegExpCreationNode regexp, Routing::RouteSetup middleware, Routing::RouteSetup endpoint, - DataFlow::Node arg, string example + DataFlow::Node arg, string byPassExample, string endpointExample, string byPassEndPoint where isCaseSensitiveMiddleware(middleware, regexp, arg) and - example = getCaseSensitiveBypassExample(regexp.getRoot()) and + byPassExample = getCaseSensitiveBypassExample(getARoot(regexp)) and isGuardedCaseInsensitiveEndpoint(endpoint, middleware) and - exists(endpoint.getRelativePath().toLowerCase().indexOf(example.toLowerCase())) + // only report one example. + endpointExample = + min(string ex | ex = getAnEndpointExample(endpoint) and Matcher::matches(regexp.getRoot(), ex)) and + not Matcher::matches(regexp.getRoot(), byPassExample) and + byPassEndPoint = toOtherCase(endpointExample) and + not Matcher::matches(regexp.getRoot(), byPassEndPoint) select arg, "This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '" - + example + "' will bypass the middleware.", regexp, "pattern", endpoint, "here" + + byPassEndPoint + "' will bypass the middleware.", regexp, "pattern", endpoint, "here" diff --git a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql index 7de72260d33..babc9e69716 100644 --- a/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql +++ b/javascript/ql/src/Security/CWE-338/InsecureRandomness.ql @@ -18,5 +18,6 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Cryptographically insecure $@ in a security context.", - source.getNode(), "random value" +select sink.getNode(), source, sink, + "Cryptographically insecure random number is generated at $@ and used here in a security context.", + source.getNode(), source.getNode().toString() diff --git a/javascript/ql/src/Security/CWE-643/XpathInjection.ql b/javascript/ql/src/Security/CWE-643/XpathInjection.ql index 58e96a6dfc1..43f16b5b840 100644 --- a/javascript/ql/src/Security/CWE-643/XpathInjection.ql +++ b/javascript/ql/src/Security/CWE-643/XpathInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ flows here and is used in an XPath expression.", +select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.", source.getNode(), "User-provided value" diff --git a/javascript/ql/src/Security/CWE-830/FunctionalityFromUntrustedSource.ql b/javascript/ql/src/Security/CWE-830/FunctionalityFromUntrustedSource.ql index 98ab953ff61..a801420b44f 100644 --- a/javascript/ql/src/Security/CWE-830/FunctionalityFromUntrustedSource.ql +++ b/javascript/ql/src/Security/CWE-830/FunctionalityFromUntrustedSource.ql @@ -61,8 +61,8 @@ module StaticCreation { } /** A script element that refers to untrusted content. */ - class CDNScriptElementWithUntrustedContent extends AddsUntrustedUrl, HTML::ScriptElement { - CDNScriptElementWithUntrustedContent() { + class CdnScriptElementWithUntrustedContent extends AddsUntrustedUrl, HTML::ScriptElement { + CdnScriptElementWithUntrustedContent() { not exists(string digest | not digest = "" | this.getIntegrityDigest() = digest) and isCdnUrlWithCheckingRequired(this.getSourcePath()) } diff --git a/javascript/ql/src/Statements/NestedLoopsSameVariable.ql b/javascript/ql/src/Statements/NestedLoopsSameVariable.ql index f3cbb30644f..f077bd7c09d 100644 --- a/javascript/ql/src/Statements/NestedLoopsSameVariable.ql +++ b/javascript/ql/src/Statements/NestedLoopsSameVariable.ql @@ -15,16 +15,17 @@ import javascript /** * Gets an iteration variable that loop `for` tests and updates. */ -Variable getAnIterationVariable(ForStmt for) { +Variable getAnIterationVariable(ForStmt for, Expr upAccess) { result.getAnAccess().getParentExpr*() = for.getTest() and exists(UpdateExpr upd | upd.getParentExpr*() = for.getUpdate() | - upd.getOperand() = result.getAnAccess() + upAccess = upd.getOperand() and upAccess = result.getAnAccess() ) } -from ForStmt outer, ForStmt inner +from ForStmt outer, ForStmt inner, Variable iteration, Expr upAccess where inner.nestedIn(outer) and - getAnIterationVariable(outer) = getAnIterationVariable(inner) -select inner.getTest(), "This for statement uses the same loop variable as an enclosing $@.", outer, - "for statement" + iteration = getAnIterationVariable(outer, _) and + iteration = getAnIterationVariable(inner, upAccess) +select inner.getTest(), "Nested for statement uses loop variable $@ of enclosing $@.", upAccess, + iteration.getName(), outer, "for statement" diff --git a/javascript/ql/src/change-notes/2022-08-23-alert-messages.md b/javascript/ql/src/change-notes/2022-08-23-alert-messages.md new file mode 100644 index 00000000000..22f4c5c6682 --- /dev/null +++ b/javascript/ql/src/change-notes/2022-08-23-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to make the message consistent with other languages. \ No newline at end of file diff --git a/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql b/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql index ee410fe9245..dc89f8530aa 100644 --- a/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql +++ b/javascript/ql/src/experimental/Security/CWE-094/UntrustedCheckout.ql @@ -78,9 +78,9 @@ class ProbableJob extends Actions::Job { /** * An action step that doesn't contain `actor` or `label` check in `if:` or */ -class ProbablePullRequestTarget extends Actions::On, YAMLMappingLikeNode { +class ProbablePullRequestTarget extends Actions::On, YamlMappingLikeNode { ProbablePullRequestTarget() { - exists(YAMLNode prtNode | + exists(YamlNode prtNode | // The `on:` is triggered on `pull_request_target` this.getNode("pull_request_target") = prtNode and ( @@ -88,7 +88,7 @@ class ProbablePullRequestTarget extends Actions::On, YAMLMappingLikeNode { not exists(prtNode.getAChild()) or // or has the filter, that is something else than just [labeled] - exists(YAMLMappingLikeNode prt, YAMLMappingLikeNode types | + exists(YamlMappingLikeNode prt, YamlMappingLikeNode types | types = prt.getNode("types") and prtNode = prt and ( diff --git a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected index 9f4f6c6aba5..9c271410ecf 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/printAst.expected @@ -99,6 +99,7 @@ nodes | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | +| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | @@ -132,6 +133,9 @@ nodes | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | | file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) | +| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | +| file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | | file://:0:0:0:0 | (TypeParameters) | semmle.label | (TypeParameters) | @@ -1381,8 +1385,47 @@ nodes | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | [DotExpr] B.resolvedFile | | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | [MethodCallExpr] B.resolvedFile() | | tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.label | [Label] resolvedFile | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | semmle.label | [NamespaceDeclaration] module ... ; } | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | semmle.order | 84 | +| tst.ts:379:8:379:11 | [VarDecl] TS48 | semmle.label | [VarDecl] TS48 | +| tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type So ... never; | +| tst.ts:381:10:381:16 | [Identifier] SomeNum | semmle.label | [Identifier] SomeNum | +| tst.ts:381:20:381:24 | [LiteralTypeExpr] "100" | semmle.label | [LiteralTypeExpr] "100" | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | semmle.label | [ConditionalTypeExpr] "100" e ... : never | +| tst.ts:381:34:381:60 | [TemplateLiteralTypeExpr] `${infe ... umber}` | semmle.label | [TemplateLiteralTypeExpr] `${infe ... umber}` | +| tst.ts:381:37:381:58 | [InferTypeExpr] infer U ... number | semmle.label | [InferTypeExpr] infer U ... number | +| tst.ts:381:43:381:43 | [Identifier] U | semmle.label | [Identifier] U | +| tst.ts:381:43:381:58 | [TypeParameter] U extends number | semmle.label | [TypeParameter] U extends number | +| tst.ts:381:53:381:58 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | +| tst.ts:381:64:381:64 | [LocalTypeAccess] U | semmle.label | [LocalTypeAccess] U | +| tst.ts:381:68:381:72 | [KeywordTypeExpr] never | semmle.label | [KeywordTypeExpr] never | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | semmle.label | [FunctionDeclStmt] declare ... T): T; | +| tst.ts:383:22:383:35 | [VarDecl] chooseRandomly | semmle.label | [VarDecl] chooseRandomly | +| tst.ts:383:37:383:37 | [Identifier] T | semmle.label | [Identifier] T | +| tst.ts:383:37:383:37 | [TypeParameter] T | semmle.label | [TypeParameter] T | +| tst.ts:383:40:383:40 | [SimpleParameter] x | semmle.label | [SimpleParameter] x | +| tst.ts:383:43:383:43 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | +| tst.ts:383:46:383:46 | [SimpleParameter] y | semmle.label | [SimpleParameter] y | +| tst.ts:383:49:383:49 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | +| tst.ts:383:53:383:53 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | +| tst.ts:385:5:385:74 | [DeclStmt] let [a, ... ye!"]); | semmle.label | [DeclStmt] let [a, ... ye!"]); | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | semmle.label | [ArrayPattern] [a, b, c] | +| tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | semmle.label | [VariableDeclarator] [a, b, ... bye!"]) | +| tst.ts:385:10:385:10 | [VarDecl] a | semmle.label | [VarDecl] a | +| tst.ts:385:13:385:13 | [VarDecl] b | semmle.label | [VarDecl] b | +| tst.ts:385:16:385:16 | [VarDecl] c | semmle.label | [VarDecl] c | +| tst.ts:385:21:385:34 | [VarRef] chooseRandomly | semmle.label | [VarRef] chooseRandomly | +| tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | semmle.label | [CallExpr] chooseR ... bye!"]) | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | semmle.label | [ArrayExpr] [42, true, "hi!"] | +| tst.ts:385:37:385:38 | [Literal] 42 | semmle.label | [Literal] 42 | +| tst.ts:385:41:385:44 | [Literal] true | semmle.label | [Literal] true | +| tst.ts:385:47:385:51 | [Literal] "hi!" | semmle.label | [Literal] "hi!" | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | semmle.label | [ArrayExpr] [0, false, "bye!"] | +| tst.ts:385:56:385:56 | [Literal] 0 | semmle.label | [Literal] 0 | +| tst.ts:385:59:385:63 | [Literal] false | semmle.label | [Literal] false | +| tst.ts:385:66:385:71 | [Literal] "bye!" | semmle.label | [Literal] "bye!" | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 84 | +| tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 85 | | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | [VarDecl] tstModuleCJS | | tstModuleCJS.cts:1:33:1:35 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1400,7 +1443,7 @@ nodes | tstModuleCJS.cts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleCJS.cts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.label | [ExportDeclaration] export ... 'b'; } | -| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 85 | +| tstModuleES.mts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | semmle.order | 86 | | tstModuleES.mts:1:16:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | [FunctionDeclStmt] functio ... 'b'; } | | tstModuleES.mts:1:25:1:35 | [VarDecl] tstModuleES | semmle.label | [VarDecl] tstModuleES | | tstModuleES.mts:1:40:1:42 | [LiteralTypeExpr] 'a' | semmle.label | [LiteralTypeExpr] 'a' | @@ -1418,7 +1461,7 @@ nodes | tstModuleES.mts:2:34:2:36 | [Literal] 'a' | semmle.label | [Literal] 'a' | | tstModuleES.mts:2:40:2:42 | [Literal] 'b' | semmle.label | [Literal] 'b' | | tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 86 | +| tstSuffixA.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 87 | | tstSuffixA.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixA.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixA.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixA.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixA.ts' | @@ -1426,7 +1469,7 @@ nodes | tstSuffixA.ts:2:5:2:27 | [ReturnStmt] return ... xA.ts'; | semmle.label | [ReturnStmt] return ... xA.ts'; | | tstSuffixA.ts:2:12:2:26 | [Literal] 'tstSuffixA.ts' | semmle.label | [Literal] 'tstSuffixA.ts' | | tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 87 | +| tstSuffixB.ios.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 88 | | tstSuffixB.ios.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ios.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ios.ts:1:33:1:51 | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ios.ts' | @@ -1434,7 +1477,7 @@ nodes | tstSuffixB.ios.ts:2:5:2:31 | [ReturnStmt] return ... os.ts'; | semmle.label | [ReturnStmt] return ... os.ts'; | | tstSuffixB.ios.ts:2:12:2:30 | [Literal] 'tstSuffixB.ios.ts' | semmle.label | [Literal] 'tstSuffixB.ios.ts' | | tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.label | [ExportDeclaration] export ... .ts'; } | -| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 88 | +| tstSuffixB.ts:1:1:3:1 | [ExportDeclaration] export ... .ts'; } | semmle.order | 89 | | tstSuffixB.ts:1:8:3:1 | [FunctionDeclStmt] functio ... .ts'; } | semmle.label | [FunctionDeclStmt] functio ... .ts'; } | | tstSuffixB.ts:1:17:1:28 | [VarDecl] resolvedFile | semmle.label | [VarDecl] resolvedFile | | tstSuffixB.ts:1:33:1:47 | [LiteralTypeExpr] 'tstSuffixB.ts' | semmle.label | [LiteralTypeExpr] 'tstSuffixB.ts' | @@ -1442,16 +1485,16 @@ nodes | tstSuffixB.ts:2:5:2:27 | [ReturnStmt] return ... xB.ts'; | semmle.label | [ReturnStmt] return ... xB.ts'; | | tstSuffixB.ts:2:12:2:26 | [Literal] 'tstSuffixB.ts' | semmle.label | [Literal] 'tstSuffixB.ts' | | type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | -| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 89 | +| type_alias.ts:1:1:1:17 | [TypeAliasDeclaration,TypeDefinition] type B = boolean; | semmle.order | 90 | | type_alias.ts:1:6:1:6 | [Identifier] B | semmle.label | [Identifier] B | | type_alias.ts:1:10:1:16 | [KeywordTypeExpr] boolean | semmle.label | [KeywordTypeExpr] boolean | | type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.label | [DeclStmt] var b = ... | -| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 90 | +| type_alias.ts:3:1:3:9 | [DeclStmt] var b = ... | semmle.order | 91 | | type_alias.ts:3:5:3:5 | [VarDecl] b | semmle.label | [VarDecl] b | | type_alias.ts:3:5:3:8 | [VariableDeclarator] b: B | semmle.label | [VariableDeclarator] b: B | | type_alias.ts:3:8:3:8 | [LocalTypeAccess] B | semmle.label | [LocalTypeAccess] B | | type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | -| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 91 | +| type_alias.ts:5:1:5:50 | [TypeAliasDeclaration,TypeDefinition] type Va ... ay>; | semmle.order | 92 | | type_alias.ts:5:6:5:17 | [Identifier] ValueOrArray | semmle.label | [Identifier] ValueOrArray | | type_alias.ts:5:19:5:19 | [Identifier] T | semmle.label | [Identifier] T | | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | [TypeParameter] T | @@ -1463,14 +1506,14 @@ nodes | type_alias.ts:5:34:5:48 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:5:47:5:47 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.label | [DeclStmt] var c = ... | -| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 92 | +| type_alias.ts:7:1:7:28 | [DeclStmt] var c = ... | semmle.order | 93 | | type_alias.ts:7:5:7:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_alias.ts:7:5:7:27 | [VariableDeclarator] c: Valu ... number> | semmle.label | [VariableDeclarator] c: Valu ... number> | | type_alias.ts:7:8:7:19 | [LocalTypeAccess] ValueOrArray | semmle.label | [LocalTypeAccess] ValueOrArray | | type_alias.ts:7:8:7:27 | [GenericTypeExpr] ValueOrArray | semmle.label | [GenericTypeExpr] ValueOrArray | | type_alias.ts:7:21:7:26 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | -| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 93 | +| type_alias.ts:9:1:15:13 | [TypeAliasDeclaration,TypeDefinition] type Js ... Json[]; | semmle.order | 94 | | type_alias.ts:9:6:9:9 | [Identifier] Json | semmle.label | [Identifier] Json | | type_alias.ts:10:5:15:12 | [UnionTypeExpr] \| strin ... Json[] | semmle.label | [UnionTypeExpr] \| strin ... Json[] | | type_alias.ts:10:7:10:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -1486,12 +1529,12 @@ nodes | type_alias.ts:15:7:15:10 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:15:7:15:12 | [ArrayTypeExpr] Json[] | semmle.label | [ArrayTypeExpr] Json[] | | type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.label | [DeclStmt] var json = ... | -| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 94 | +| type_alias.ts:17:1:17:15 | [DeclStmt] var json = ... | semmle.order | 95 | | type_alias.ts:17:5:17:8 | [VarDecl] json | semmle.label | [VarDecl] json | | type_alias.ts:17:5:17:14 | [VariableDeclarator] json: Json | semmle.label | [VariableDeclarator] json: Json | | type_alias.ts:17:11:17:14 | [LocalTypeAccess] Json | semmle.label | [LocalTypeAccess] Json | | type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | -| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 95 | +| type_alias.ts:19:1:21:57 | [TypeAliasDeclaration,TypeDefinition] type Vi ... ode[]]; | semmle.order | 96 | | type_alias.ts:19:6:19:16 | [Identifier] VirtualNode | semmle.label | [Identifier] VirtualNode | | type_alias.ts:20:5:21:56 | [UnionTypeExpr] \| strin ... Node[]] | semmle.label | [UnionTypeExpr] \| strin ... Node[]] | | type_alias.ts:20:7:20:12 | [KeywordTypeExpr] string | semmle.label | [KeywordTypeExpr] string | @@ -1507,7 +1550,7 @@ nodes | type_alias.ts:21:43:21:53 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | | type_alias.ts:21:43:21:55 | [ArrayTypeExpr] VirtualNode[] | semmle.label | [ArrayTypeExpr] VirtualNode[] | | type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.label | [DeclStmt] const myNode = ... | -| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 96 | +| type_alias.ts:23:1:27:6 | [DeclStmt] const myNode = ... | semmle.order | 97 | | type_alias.ts:23:7:23:12 | [VarDecl] myNode | semmle.label | [VarDecl] myNode | | type_alias.ts:23:7:27:5 | [VariableDeclarator] myNode: ... ] ] | semmle.label | [VariableDeclarator] myNode: ... ] ] | | type_alias.ts:23:15:23:25 | [LocalTypeAccess] VirtualNode | semmle.label | [LocalTypeAccess] VirtualNode | @@ -1532,12 +1575,12 @@ nodes | type_alias.ts:26:23:26:36 | [Literal] "second-child" | semmle.label | [Literal] "second-child" | | type_alias.ts:26:41:26:62 | [Literal] "I'm the second child" | semmle.label | [Literal] "I'm the second child" | | type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 97 | +| type_definition_objects.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 98 | | type_definition_objects.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definition_objects.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definition_objects.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.label | [ExportDeclaration] export class C {} | -| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 98 | +| type_definition_objects.ts:3:1:3:17 | [ExportDeclaration] export class C {} | semmle.order | 99 | | type_definition_objects.ts:3:8:3:17 | [ClassDefinition,TypeDefinition] class C {} | semmle.label | [ClassDefinition,TypeDefinition] class C {} | | type_definition_objects.ts:3:14:3:14 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definition_objects.ts:3:16:3:15 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | @@ -1545,36 +1588,36 @@ nodes | type_definition_objects.ts:3:16:3:15 | [FunctionExpr] () {} | semmle.label | [FunctionExpr] () {} | | type_definition_objects.ts:3:16:3:15 | [Label] constructor | semmle.label | [Label] constructor | | type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.label | [DeclStmt] let classObj = ... | -| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 99 | +| type_definition_objects.ts:4:1:4:17 | [DeclStmt] let classObj = ... | semmle.order | 100 | | type_definition_objects.ts:4:5:4:12 | [VarDecl] classObj | semmle.label | [VarDecl] classObj | | type_definition_objects.ts:4:5:4:16 | [VariableDeclarator] classObj = C | semmle.label | [VariableDeclarator] classObj = C | | type_definition_objects.ts:4:16:4:16 | [VarRef] C | semmle.label | [VarRef] C | | type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.label | [ExportDeclaration] export enum E {} | -| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 100 | +| type_definition_objects.ts:6:1:6:16 | [ExportDeclaration] export enum E {} | semmle.order | 101 | | type_definition_objects.ts:6:8:6:16 | [EnumDeclaration,TypeDefinition] enum E {} | semmle.label | [EnumDeclaration,TypeDefinition] enum E {} | | type_definition_objects.ts:6:13:6:13 | [VarDecl] E | semmle.label | [VarDecl] E | | type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.label | [DeclStmt] let enumObj = ... | -| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 101 | +| type_definition_objects.ts:7:1:7:16 | [DeclStmt] let enumObj = ... | semmle.order | 102 | | type_definition_objects.ts:7:5:7:11 | [VarDecl] enumObj | semmle.label | [VarDecl] enumObj | | type_definition_objects.ts:7:5:7:15 | [VariableDeclarator] enumObj = E | semmle.label | [VariableDeclarator] enumObj = E | | type_definition_objects.ts:7:15:7:15 | [VarRef] E | semmle.label | [VarRef] E | | type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.label | [ExportDeclaration] export ... e N {;} | -| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 102 | +| type_definition_objects.ts:9:1:9:22 | [ExportDeclaration] export ... e N {;} | semmle.order | 103 | | type_definition_objects.ts:9:8:9:22 | [NamespaceDeclaration] namespace N {;} | semmle.label | [NamespaceDeclaration] namespace N {;} | | type_definition_objects.ts:9:18:9:18 | [VarDecl] N | semmle.label | [VarDecl] N | | type_definition_objects.ts:9:21:9:21 | [EmptyStmt] ; | semmle.label | [EmptyStmt] ; | | type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.label | [DeclStmt] let namespaceObj = ... | -| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 103 | +| type_definition_objects.ts:10:1:10:21 | [DeclStmt] let namespaceObj = ... | semmle.order | 104 | | type_definition_objects.ts:10:5:10:16 | [VarDecl] namespaceObj | semmle.label | [VarDecl] namespaceObj | | type_definition_objects.ts:10:5:10:20 | [VariableDeclarator] namespaceObj = N | semmle.label | [VariableDeclarator] namespaceObj = N | | type_definition_objects.ts:10:20:10:20 | [VarRef] N | semmle.label | [VarRef] N | | type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.label | [ImportDeclaration] import ... dummy"; | -| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 104 | +| type_definitions.ts:1:1:1:33 | [ImportDeclaration] import ... dummy"; | semmle.order | 105 | | type_definitions.ts:1:8:1:17 | [ImportSpecifier] * as dummy | semmle.label | [ImportSpecifier] * as dummy | | type_definitions.ts:1:13:1:17 | [VarDecl] dummy | semmle.label | [VarDecl] dummy | | type_definitions.ts:1:24:1:32 | [Literal] "./dummy" | semmle.label | [Literal] "./dummy" | | type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.label | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | -| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 105 | +| type_definitions.ts:3:1:5:1 | [InterfaceDeclaration,TypeDefinition] interfa ... x: S; } | semmle.order | 106 | | type_definitions.ts:3:11:3:11 | [Identifier] I | semmle.label | [Identifier] I | | type_definitions.ts:3:13:3:13 | [Identifier] S | semmle.label | [Identifier] S | | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | [TypeParameter] S | @@ -1582,14 +1625,14 @@ nodes | type_definitions.ts:4:3:4:7 | [FieldDeclaration] x: S; | semmle.label | [FieldDeclaration] x: S; | | type_definitions.ts:4:6:4:6 | [LocalTypeAccess] S | semmle.label | [LocalTypeAccess] S | | type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.label | [DeclStmt] let i = ... | -| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 106 | +| type_definitions.ts:6:1:6:16 | [DeclStmt] let i = ... | semmle.order | 107 | | type_definitions.ts:6:5:6:5 | [VarDecl] i | semmle.label | [VarDecl] i | | type_definitions.ts:6:5:6:16 | [VariableDeclarator] i: I | semmle.label | [VariableDeclarator] i: I | | type_definitions.ts:6:8:6:8 | [LocalTypeAccess] I | semmle.label | [LocalTypeAccess] I | | type_definitions.ts:6:8:6:16 | [GenericTypeExpr] I | semmle.label | [GenericTypeExpr] I | | type_definitions.ts:6:10:6:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.label | [ClassDefinition,TypeDefinition] class C ... x: T } | -| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 107 | +| type_definitions.ts:8:1:10:1 | [ClassDefinition,TypeDefinition] class C ... x: T } | semmle.order | 108 | | type_definitions.ts:8:7:8:7 | [VarDecl] C | semmle.label | [VarDecl] C | | type_definitions.ts:8:8:8:7 | [BlockStmt] {} | semmle.label | [BlockStmt] {} | | type_definitions.ts:8:8:8:7 | [ClassInitializedMember,ConstructorDefinition] constructor() {} | semmle.label | [ClassInitializedMember,ConstructorDefinition] constructor() {} | @@ -1601,14 +1644,14 @@ nodes | type_definitions.ts:9:3:9:6 | [FieldDeclaration] x: T | semmle.label | [FieldDeclaration] x: T | | type_definitions.ts:9:6:9:6 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.label | [DeclStmt] let c = ... | -| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 108 | +| type_definitions.ts:11:1:11:17 | [DeclStmt] let c = ... | semmle.order | 109 | | type_definitions.ts:11:5:11:5 | [VarDecl] c | semmle.label | [VarDecl] c | | type_definitions.ts:11:5:11:16 | [VariableDeclarator] c: C | semmle.label | [VariableDeclarator] c: C | | type_definitions.ts:11:8:11:8 | [LocalTypeAccess] C | semmle.label | [LocalTypeAccess] C | | type_definitions.ts:11:8:11:16 | [GenericTypeExpr] C | semmle.label | [GenericTypeExpr] C | | type_definitions.ts:11:10:11:15 | [KeywordTypeExpr] number | semmle.label | [KeywordTypeExpr] number | | type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.label | [EnumDeclaration,TypeDefinition] enum Co ... blue } | -| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 109 | +| type_definitions.ts:13:1:15:1 | [EnumDeclaration,TypeDefinition] enum Co ... blue } | semmle.order | 110 | | type_definitions.ts:13:6:13:10 | [VarDecl] Color | semmle.label | [VarDecl] Color | | type_definitions.ts:14:3:14:5 | [EnumMember,TypeDefinition] red | semmle.label | [EnumMember,TypeDefinition] red | | type_definitions.ts:14:3:14:5 | [VarDecl] red | semmle.label | [VarDecl] red | @@ -1617,29 +1660,29 @@ nodes | type_definitions.ts:14:15:14:18 | [EnumMember,TypeDefinition] blue | semmle.label | [EnumMember,TypeDefinition] blue | | type_definitions.ts:14:15:14:18 | [VarDecl] blue | semmle.label | [VarDecl] blue | | type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.label | [DeclStmt] let color = ... | -| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 110 | +| type_definitions.ts:16:1:16:17 | [DeclStmt] let color = ... | semmle.order | 111 | | type_definitions.ts:16:5:16:9 | [VarDecl] color | semmle.label | [VarDecl] color | | type_definitions.ts:16:5:16:16 | [VariableDeclarator] color: Color | semmle.label | [VariableDeclarator] color: Color | | type_definitions.ts:16:12:16:16 | [LocalTypeAccess] Color | semmle.label | [LocalTypeAccess] Color | | type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.label | [EnumDeclaration,TypeDefinition] enum En ... ember } | -| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 111 | +| type_definitions.ts:18:1:18:33 | [EnumDeclaration,TypeDefinition] enum En ... ember } | semmle.order | 112 | | type_definitions.ts:18:6:18:22 | [VarDecl] EnumWithOneMember | semmle.label | [VarDecl] EnumWithOneMember | | type_definitions.ts:18:26:18:31 | [EnumMember,TypeDefinition] member | semmle.label | [EnumMember,TypeDefinition] member | | type_definitions.ts:18:26:18:31 | [VarDecl] member | semmle.label | [VarDecl] member | | type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.label | [DeclStmt] let e = ... | -| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 112 | +| type_definitions.ts:19:1:19:25 | [DeclStmt] let e = ... | semmle.order | 113 | | type_definitions.ts:19:5:19:5 | [VarDecl] e | semmle.label | [VarDecl] e | | type_definitions.ts:19:5:19:24 | [VariableDeclarator] e: EnumWithOneMember | semmle.label | [VariableDeclarator] e: EnumWithOneMember | | type_definitions.ts:19:8:19:24 | [LocalTypeAccess] EnumWithOneMember | semmle.label | [LocalTypeAccess] EnumWithOneMember | | type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.label | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | -| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 113 | +| type_definitions.ts:21:1:21:20 | [TypeAliasDeclaration,TypeDefinition] type Alias = T[]; | semmle.order | 114 | | type_definitions.ts:21:6:21:10 | [Identifier] Alias | semmle.label | [Identifier] Alias | | type_definitions.ts:21:12:21:12 | [Identifier] T | semmle.label | [Identifier] T | | type_definitions.ts:21:12:21:12 | [TypeParameter] T | semmle.label | [TypeParameter] T | | type_definitions.ts:21:17:21:17 | [LocalTypeAccess] T | semmle.label | [LocalTypeAccess] T | | type_definitions.ts:21:17:21:19 | [ArrayTypeExpr] T[] | semmle.label | [ArrayTypeExpr] T[] | | type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.label | [DeclStmt] let aliasForNumberArray = ... | -| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 114 | +| type_definitions.ts:22:1:22:39 | [DeclStmt] let aliasForNumberArray = ... | semmle.order | 115 | | type_definitions.ts:22:5:22:23 | [VarDecl] aliasForNumberArray | semmle.label | [VarDecl] aliasForNumberArray | | type_definitions.ts:22:5:22:38 | [VariableDeclarator] aliasFo ... number> | semmle.label | [VariableDeclarator] aliasFo ... number> | | type_definitions.ts:22:26:22:30 | [LocalTypeAccess] Alias | semmle.label | [LocalTypeAccess] Alias | @@ -1794,6 +1837,10 @@ edges | file://:0:0:0:0 | (Arguments) | tst.ts:370:13:370:28 | [MethodCallExpr] A.resolvedFile() | semmle.order | 0 | | file://:0:0:0:0 | (Arguments) | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.label | 0 | | file://:0:0:0:0 | (Arguments) | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | semmle.label | 0 | +| file://:0:0:0:0 | (Arguments) | tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | semmle.order | 0 | +| file://:0:0:0:0 | (Arguments) | tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | semmle.label | 1 | +| file://:0:0:0:0 | (Arguments) | tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | semmle.order | 1 | | file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.label | 0 | | file://:0:0:0:0 | (Parameters) | tst.ts:14:17:14:17 | [SimpleParameter] x | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | tst.ts:14:28:14:28 | [SimpleParameter] y | semmle.label | 1 | @@ -1866,6 +1913,10 @@ edges | file://:0:0:0:0 | (Parameters) | tst.ts:344:9:344:13 | [SimpleParameter] value | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.label | 0 | | file://:0:0:0:0 | (Parameters) | tst.ts:349:9:349:13 | [SimpleParameter] value | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | tst.ts:383:40:383:40 | [SimpleParameter] x | semmle.label | 0 | +| file://:0:0:0:0 | (Parameters) | tst.ts:383:40:383:40 | [SimpleParameter] x | semmle.order | 0 | +| file://:0:0:0:0 | (Parameters) | tst.ts:383:46:383:46 | [SimpleParameter] y | semmle.label | 1 | +| file://:0:0:0:0 | (Parameters) | tst.ts:383:46:383:46 | [SimpleParameter] y | semmle.order | 1 | | file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.label | 0 | | file://:0:0:0:0 | (Parameters) | type_alias.ts:14:10:14:17 | [SimpleParameter] property | semmle.order | 0 | | file://:0:0:0:0 | (Parameters) | type_alias.ts:21:19:21:21 | [SimpleParameter] key | semmle.label | 0 | @@ -1884,6 +1935,10 @@ edges | file://:0:0:0:0 | (TypeParameters) | tst.ts:332:20:332:35 | [TypeParameter] S extends string | semmle.order | 0 | | file://:0:0:0:0 | (TypeParameters) | tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.label | 0 | | file://:0:0:0:0 | (TypeParameters) | tst.ts:342:17:342:24 | [TypeParameter] in out T | semmle.order | 0 | +| file://:0:0:0:0 | (TypeParameters) | tst.ts:381:43:381:58 | [TypeParameter] U extends number | semmle.label | 0 | +| file://:0:0:0:0 | (TypeParameters) | tst.ts:381:43:381:58 | [TypeParameter] U extends number | semmle.order | 0 | +| file://:0:0:0:0 | (TypeParameters) | tst.ts:383:37:383:37 | [TypeParameter] T | semmle.label | 0 | +| file://:0:0:0:0 | (TypeParameters) | tst.ts:383:37:383:37 | [TypeParameter] T | semmle.order | 0 | | file://:0:0:0:0 | (TypeParameters) | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.label | 0 | | file://:0:0:0:0 | (TypeParameters) | type_alias.ts:5:19:5:19 | [TypeParameter] T | semmle.order | 0 | | file://:0:0:0:0 | (TypeParameters) | type_definitions.ts:3:13:3:13 | [TypeParameter] S | semmle.label | 0 | @@ -4078,6 +4133,76 @@ edges | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | tst.ts:374:15:374:26 | [Label] resolvedFile | semmle.order | 2 | | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.label | 0 | | tst.ts:374:13:374:28 | [MethodCallExpr] B.resolvedFile() | tst.ts:374:13:374:26 | [DotExpr] B.resolvedFile | semmle.order | 0 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:379:8:379:11 | [VarDecl] TS48 | semmle.label | 1 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:379:8:379:11 | [VarDecl] TS48 | semmle.order | 1 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | semmle.label | 2 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | semmle.order | 2 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | semmle.label | 3 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | semmle.order | 3 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:385:5:385:74 | [DeclStmt] let [a, ... ye!"]); | semmle.label | 4 | +| tst.ts:379:1:386:1 | [NamespaceDeclaration] module ... ; } | tst.ts:385:5:385:74 | [DeclStmt] let [a, ... ye!"]); | semmle.order | 4 | +| tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | tst.ts:381:10:381:16 | [Identifier] SomeNum | semmle.label | 1 | +| tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | tst.ts:381:10:381:16 | [Identifier] SomeNum | semmle.order | 1 | +| tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | semmle.label | 2 | +| tst.ts:381:5:381:73 | [TypeAliasDeclaration,TypeDefinition] type So ... never; | tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | semmle.order | 2 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:20:381:24 | [LiteralTypeExpr] "100" | semmle.label | 1 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:20:381:24 | [LiteralTypeExpr] "100" | semmle.order | 1 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:34:381:60 | [TemplateLiteralTypeExpr] `${infe ... umber}` | semmle.label | 2 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:34:381:60 | [TemplateLiteralTypeExpr] `${infe ... umber}` | semmle.order | 2 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:64:381:64 | [LocalTypeAccess] U | semmle.label | 3 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:64:381:64 | [LocalTypeAccess] U | semmle.order | 3 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:68:381:72 | [KeywordTypeExpr] never | semmle.label | 4 | +| tst.ts:381:20:381:72 | [ConditionalTypeExpr] "100" e ... : never | tst.ts:381:68:381:72 | [KeywordTypeExpr] never | semmle.order | 4 | +| tst.ts:381:34:381:60 | [TemplateLiteralTypeExpr] `${infe ... umber}` | tst.ts:381:37:381:58 | [InferTypeExpr] infer U ... number | semmle.label | 1 | +| tst.ts:381:34:381:60 | [TemplateLiteralTypeExpr] `${infe ... umber}` | tst.ts:381:37:381:58 | [InferTypeExpr] infer U ... number | semmle.order | 1 | +| tst.ts:381:37:381:58 | [InferTypeExpr] infer U ... number | file://:0:0:0:0 | (TypeParameters) | semmle.label | -100 | +| tst.ts:381:37:381:58 | [InferTypeExpr] infer U ... number | file://:0:0:0:0 | (TypeParameters) | semmle.order | -100 | +| tst.ts:381:43:381:58 | [TypeParameter] U extends number | tst.ts:381:43:381:43 | [Identifier] U | semmle.label | 1 | +| tst.ts:381:43:381:58 | [TypeParameter] U extends number | tst.ts:381:43:381:43 | [Identifier] U | semmle.order | 1 | +| tst.ts:381:43:381:58 | [TypeParameter] U extends number | tst.ts:381:53:381:58 | [KeywordTypeExpr] number | semmle.label | 2 | +| tst.ts:381:43:381:58 | [TypeParameter] U extends number | tst.ts:381:53:381:58 | [KeywordTypeExpr] number | semmle.order | 2 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | file://:0:0:0:0 | (Parameters) | semmle.label | 1 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | file://:0:0:0:0 | (Parameters) | semmle.order | 1 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | file://:0:0:0:0 | (TypeParameters) | semmle.label | 2 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | file://:0:0:0:0 | (TypeParameters) | semmle.order | 2 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | tst.ts:383:22:383:35 | [VarDecl] chooseRandomly | semmle.label | 0 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | tst.ts:383:22:383:35 | [VarDecl] chooseRandomly | semmle.order | 0 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | tst.ts:383:53:383:53 | [LocalTypeAccess] T | semmle.label | 4 | +| tst.ts:383:5:383:54 | [FunctionDeclStmt] declare ... T): T; | tst.ts:383:53:383:53 | [LocalTypeAccess] T | semmle.order | 4 | +| tst.ts:383:37:383:37 | [TypeParameter] T | tst.ts:383:37:383:37 | [Identifier] T | semmle.label | 1 | +| tst.ts:383:37:383:37 | [TypeParameter] T | tst.ts:383:37:383:37 | [Identifier] T | semmle.order | 1 | +| tst.ts:383:40:383:40 | [SimpleParameter] x | tst.ts:383:43:383:43 | [LocalTypeAccess] T | semmle.label | 0 | +| tst.ts:383:40:383:40 | [SimpleParameter] x | tst.ts:383:43:383:43 | [LocalTypeAccess] T | semmle.order | 0 | +| tst.ts:383:46:383:46 | [SimpleParameter] y | tst.ts:383:49:383:49 | [LocalTypeAccess] T | semmle.label | 0 | +| tst.ts:383:46:383:46 | [SimpleParameter] y | tst.ts:383:49:383:49 | [LocalTypeAccess] T | semmle.order | 0 | +| tst.ts:385:5:385:74 | [DeclStmt] let [a, ... ye!"]); | tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | semmle.label | 1 | +| tst.ts:385:5:385:74 | [DeclStmt] let [a, ... ye!"]); | tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | semmle.order | 1 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:10:385:10 | [VarDecl] a | semmle.label | 1 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:10:385:10 | [VarDecl] a | semmle.order | 1 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:13:385:13 | [VarDecl] b | semmle.label | 2 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:13:385:13 | [VarDecl] b | semmle.order | 2 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:16:385:16 | [VarDecl] c | semmle.label | 3 | +| tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | tst.ts:385:16:385:16 | [VarDecl] c | semmle.order | 3 | +| tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | semmle.label | 1 | +| tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | tst.ts:385:9:385:17 | [ArrayPattern] [a, b, c] | semmle.order | 1 | +| tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | semmle.label | 2 | +| tst.ts:385:9:385:73 | [VariableDeclarator] [a, b, ... bye!"]) | tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | semmle.order | 2 | +| tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 | +| tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 | +| tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | tst.ts:385:21:385:34 | [VarRef] chooseRandomly | semmle.label | 0 | +| tst.ts:385:21:385:73 | [CallExpr] chooseR ... bye!"]) | tst.ts:385:21:385:34 | [VarRef] chooseRandomly | semmle.order | 0 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:37:385:38 | [Literal] 42 | semmle.label | 1 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:37:385:38 | [Literal] 42 | semmle.order | 1 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:41:385:44 | [Literal] true | semmle.label | 2 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:41:385:44 | [Literal] true | semmle.order | 2 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:47:385:51 | [Literal] "hi!" | semmle.label | 3 | +| tst.ts:385:36:385:52 | [ArrayExpr] [42, true, "hi!"] | tst.ts:385:47:385:51 | [Literal] "hi!" | semmle.order | 3 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:56:385:56 | [Literal] 0 | semmle.label | 1 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:56:385:56 | [Literal] 0 | semmle.order | 1 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:59:385:63 | [Literal] false | semmle.label | 2 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:59:385:63 | [Literal] false | semmle.order | 2 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:66:385:71 | [Literal] "bye!" | semmle.label | 3 | +| tst.ts:385:55:385:72 | [ArrayExpr] [0, false, "bye!"] | tst.ts:385:66:385:71 | [Literal] "bye!" | semmle.order | 3 | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.label | 1 | | tstModuleCJS.cts:1:1:3:1 | [ExportDeclaration] export ... 'b'; } | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | semmle.order | 1 | | tstModuleCJS.cts:1:8:3:1 | [FunctionDeclStmt] functio ... 'b'; } | tstModuleCJS.cts:1:17:1:28 | [VarDecl] tstModuleCJS | semmle.label | 0 | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected index ce517db8d6d..6727ab01b13 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tests.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/tests.expected @@ -441,7 +441,7 @@ getExprType | tst.ts:320:19:320:29 | toLowerCase | () => string | | tst.ts:325:7:325:14 | ErrorMap | { new (entries?: readonly (readonly [string, Er... | | tst.ts:325:18:325:20 | Map | MapConstructor | -| tst.ts:325:18:325:35 | Map | any | +| tst.ts:325:18:325:35 | Map | { new (entries?: readonly (readonly [string, Er... | | tst.ts:327:7:327:14 | errorMap | Map | | tst.ts:327:18:327:31 | new ErrorMap() | Map | | tst.ts:327:22:327:29 | ErrorMap | { new (entries?: readonly (readonly [string, Er... | @@ -502,6 +502,23 @@ getExprType | tst.ts:374:13:374:26 | B.resolvedFile | () => "tstSuffixB.ios.ts" | | tst.ts:374:13:374:28 | B.resolvedFile() | "tstSuffixB.ios.ts" | | tst.ts:374:15:374:26 | resolvedFile | () => "tstSuffixB.ios.ts" | +| tst.ts:379:8:379:11 | TS48 | typeof TS48 in library-tests/TypeScript/Types/tst.ts | +| tst.ts:383:22:383:35 | chooseRandomly | (x: T, y: T) => T | +| tst.ts:383:40:383:40 | x | T | +| tst.ts:383:46:383:46 | y | T | +| tst.ts:385:10:385:10 | a | number | +| tst.ts:385:13:385:13 | b | boolean | +| tst.ts:385:16:385:16 | c | string | +| tst.ts:385:21:385:34 | chooseRandomly | (x: T, y: T) => T | +| tst.ts:385:21:385:73 | chooseR ... bye!"]) | [number, boolean, string] | +| tst.ts:385:36:385:52 | [42, true, "hi!"] | [number, boolean, string] | +| tst.ts:385:37:385:38 | 42 | 42 | +| tst.ts:385:41:385:44 | true | true | +| tst.ts:385:47:385:51 | "hi!" | "hi!" | +| tst.ts:385:55:385:72 | [0, false, "bye!"] | [number, boolean, string] | +| tst.ts:385:56:385:56 | 0 | 0 | +| tst.ts:385:59:385:63 | false | false | +| tst.ts:385:66:385:71 | "bye!" | "bye!" | | tstModuleCJS.cts:1:17:1:28 | tstModuleCJS | () => "a" \| "b" | | tstModuleCJS.cts:2:12:2:15 | Math | Math | | tstModuleCJS.cts:2:12:2:22 | Math.random | () => number | @@ -606,6 +623,7 @@ getTypeDefinitionType | tst.ts:331:1:334:14 | type Fi ... never; | FirstString | | tst.ts:336:1:336:51 | type F ... lean]>; | "a" \| "b" | | tst.ts:342:1:345:1 | interfa ... void;\\n} | State | +| tst.ts:381:5:381:73 | type So ... never; | 100 | | type_alias.ts:1:1:1:17 | type B = boolean; | boolean | | type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray | | type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json | @@ -861,6 +879,16 @@ getTypeExprType | tst.ts:325:30:325:34 | Error | Error | | tst.ts:331:6:331:16 | FirstString | FirstString | | tst.ts:331:18:331:18 | T | T | +| tst.ts:332:3:332:3 | T | T | +| tst.ts:332:13:332:50 | [infer ... nown[]] | [S, ...unknown[]] | +| tst.ts:332:14:332:35 | infer S ... string | S | +| tst.ts:332:20:332:20 | S | S | +| tst.ts:332:30:332:35 | string | string | +| tst.ts:332:38:332:49 | ...unknown[] | unknown | +| tst.ts:332:41:332:47 | unknown | unknown | +| tst.ts:332:41:332:49 | unknown[] | unknown[] | +| tst.ts:333:9:333:9 | S | S | +| tst.ts:334:9:334:13 | never | never | | tst.ts:336:6:336:6 | F | "a" \| "b" | | tst.ts:336:10:336:20 | FirstString | FirstString | | tst.ts:336:10:336:50 | FirstSt ... olean]> | "a" \| "b" | @@ -881,6 +909,18 @@ getTypeExprType | tst.ts:347:14:347:18 | State | State | | tst.ts:347:14:347:26 | State | State | | tst.ts:347:20:347:25 | number | number | +| tst.ts:381:10:381:16 | SomeNum | 100 | +| tst.ts:381:20:381:24 | "100" | "100" | +| tst.ts:381:20:381:72 | "100" e ... : never | 100 | +| tst.ts:381:37:381:58 | infer U ... number | U | +| tst.ts:381:43:381:43 | U | U | +| tst.ts:381:53:381:58 | number | number | +| tst.ts:381:64:381:64 | U | U | +| tst.ts:381:68:381:72 | never | never | +| tst.ts:383:37:383:37 | T | T | +| tst.ts:383:43:383:43 | T | T | +| tst.ts:383:49:383:49 | T | T | +| tst.ts:383:53:383:53 | T | T | | tstModuleCJS.cts:1:33:1:35 | 'a' | "a" | | tstModuleCJS.cts:1:33:1:41 | 'a' \| 'b' | "a" \| "b" | | tstModuleCJS.cts:1:39:1:41 | 'b' | "b" | @@ -1027,6 +1067,15 @@ tupleTypes | tst.ts:42:25:42:30 | [1, 2] | readonly [1, 2] | 1 | 2 | 2 | no-rest | | tst.ts:42:25:42:39 | [1, 2] as const | readonly [1, 2] | 0 | 1 | 2 | no-rest | | tst.ts:42:25:42:39 | [1, 2] as const | readonly [1, 2] | 1 | 2 | 2 | no-rest | +| tst.ts:385:21:385:73 | chooseR ... bye!"]) | [number, boolean, string] | 0 | number | 3 | no-rest | +| tst.ts:385:21:385:73 | chooseR ... bye!"]) | [number, boolean, string] | 1 | boolean | 3 | no-rest | +| tst.ts:385:21:385:73 | chooseR ... bye!"]) | [number, boolean, string] | 2 | string | 3 | no-rest | +| tst.ts:385:36:385:52 | [42, true, "hi!"] | [number, boolean, string] | 0 | number | 3 | no-rest | +| tst.ts:385:36:385:52 | [42, true, "hi!"] | [number, boolean, string] | 1 | boolean | 3 | no-rest | +| tst.ts:385:36:385:52 | [42, true, "hi!"] | [number, boolean, string] | 2 | string | 3 | no-rest | +| tst.ts:385:55:385:72 | [0, false, "bye!"] | [number, boolean, string] | 0 | number | 3 | no-rest | +| tst.ts:385:55:385:72 | [0, false, "bye!"] | [number, boolean, string] | 1 | boolean | 3 | no-rest | +| tst.ts:385:55:385:72 | [0, false, "bye!"] | [number, boolean, string] | 2 | string | 3 | no-rest | unknownType | tst.ts:40:5:40:15 | unknownType | unknown | | tst.ts:47:8:47:8 | e | unknown | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts index ed8787112d3..67e31b27afa 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Types/tst.ts @@ -373,3 +373,14 @@ import * as B from './tstSuffixB'; console.log(B.resolvedFile()); // <- 'tstSuffixB.ios.ts' + +///////////////// + +module TS48 { + // SomeNum used to be 'number'; now it's '100'. + type SomeNum = "100" extends `${infer U extends number}` ? U : never; + + declare function chooseRandomly(x: T, y: T): T; + + let [a, b, c] = chooseRandomly([42, true, "hi!"], [0, false, "bye!"]); +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/YAML/printAst.expected b/javascript/ql/test/library-tests/YAML/printAst.expected index 765288fe38e..1be958a78a4 100644 --- a/javascript/ql/test/library-tests/YAML/printAst.expected +++ b/javascript/ql/test/library-tests/YAML/printAst.expected @@ -1,6 +1,6 @@ nodes -| external.yml:1:1:1:2 | [YAMLScalar] 42 | semmle.label | [YAMLScalar] 42 | -| external.yml:1:1:1:2 | [YAMLScalar] 42 | semmle.order | 1 | +| external.yml:1:1:1:2 | [YamlScalar] 42 | semmle.label | [YamlScalar] 42 | +| external.yml:1:1:1:2 | [YamlScalar] 42 | semmle.order | 1 | | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | (Mapping 0) name: | | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | (Mapping 0) name: | | file://:0:0:0:0 | (Mapping 0) street: | semmle.label | (Mapping 0) street: | @@ -15,137 +15,137 @@ nodes | file://:0:0:0:0 | (Mapping 1) y: | semmle.label | (Mapping 1) y: | | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | (Mapping 2) country: | | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | (Mapping 2) country: | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | semmle.label | [YAMLSequence] - &A { ... y: 42 } | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | semmle.order | 2 | -| merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | semmle.label | [YAMLMapping] &A { x: 23, y: 42 } | -| merge.yaml:1:8:1:8 | [YAMLScalar] x | semmle.label | [YAMLScalar] x | -| merge.yaml:1:11:1:12 | [YAMLScalar] 23 | semmle.label | [YAMLScalar] 23 | -| merge.yaml:1:15:1:15 | [YAMLScalar] y | semmle.label | [YAMLScalar] y | -| merge.yaml:1:18:1:19 | [YAMLScalar] 42 | semmle.label | [YAMLScalar] 42 | -| merge.yaml:2:3:2:3 | [YAMLScalar] x | semmle.label | [YAMLScalar] x | -| merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | semmle.label | [YAMLMapping] x: 56 | -| merge.yaml:2:6:2:7 | [YAMLScalar] 56 | semmle.label | [YAMLScalar] 56 | -| merge.yaml:3:3:3:4 | [YAMLScalar] << | semmle.label | [YAMLScalar] << | -| merge.yaml:3:7:3:8 | [YAMLAliasNode] *A | semmle.label | [YAMLAliasNode] *A | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | semmle.label | [YAMLSequence] - "name ... Knopf" | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | semmle.order | 3 | -| tst.yml:1:3:1:8 | [YAMLScalar] "name" | semmle.label | [YAMLScalar] "name" | -| tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | semmle.label | [YAMLMapping] "name": "Jim Knopf" | -| tst.yml:1:11:1:21 | [YAMLScalar] "Jim Knopf" | semmle.label | [YAMLScalar] "Jim Knopf" | -| tst.yml:2:3:2:9 | [YAMLScalar] address | semmle.label | [YAMLScalar] address | -| tst.yml:2:12:6:3 | [YAMLMapping] { | semmle.label | [YAMLMapping] { | -| tst.yml:3:5:3:12 | [YAMLScalar] "street" | semmle.label | [YAMLScalar] "street" | -| tst.yml:3:14:3:13 | [YAMLScalar] | semmle.label | [YAMLScalar] | -| tst.yml:4:5:4:12 | [YAMLScalar] "number" | semmle.label | [YAMLScalar] "number" | -| tst.yml:4:15:4:16 | [YAMLScalar] -1 | semmle.label | [YAMLScalar] -1 | -| tst.yml:5:5:5:13 | [YAMLScalar] "country" | semmle.label | [YAMLScalar] "country" | -| tst.yml:5:16:5:27 | [YAMLScalar] "Lummerland" | semmle.label | [YAMLScalar] "Lummerland" | -| tst.yml:7:3:7:6 | [YAMLScalar] name | semmle.label | [YAMLScalar] name | -| tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | semmle.label | [YAMLMapping] name: Frau Mahlzahn | -| tst.yml:7:9:7:21 | [YAMLScalar] Frau Mahlzahn | semmle.label | [YAMLScalar] Frau Mahlzahn | -| tst.yml:8:3:8:9 | [YAMLScalar] address | semmle.label | [YAMLScalar] address | -| tst.yml:9:5:9:10 | [YAMLScalar] street | semmle.label | [YAMLScalar] street | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | semmle.label | [YAMLMapping] street: \| | -| tst.yml:9:13:11:0 | [YAMLScalar] \| | semmle.label | [YAMLScalar] \| | -| tst.yml:11:5:11:10 | [YAMLScalar] number | semmle.label | [YAMLScalar] number | -| tst.yml:11:13:11:15 | [YAMLScalar] 133 | semmle.label | [YAMLScalar] 133 | -| tst.yml:12:5:12:11 | [YAMLScalar] country | semmle.label | [YAMLScalar] country | -| tst.yml:12:14:13:18 | [YAMLScalar] < | semmle.label | [YAMLScalar] < | -| tst.yml:14:3:14:23 | [YAMLScalar] !includ ... nal.yml | semmle.label | [YAMLScalar] !includ ... nal.yml | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | semmle.label | [YamlSequence] - &A { ... y: 42 } | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | semmle.order | 2 | +| merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | semmle.label | [YamlMapping] &A { x: 23, y: 42 } | +| merge.yaml:1:8:1:8 | [YamlScalar] x | semmle.label | [YamlScalar] x | +| merge.yaml:1:11:1:12 | [YamlScalar] 23 | semmle.label | [YamlScalar] 23 | +| merge.yaml:1:15:1:15 | [YamlScalar] y | semmle.label | [YamlScalar] y | +| merge.yaml:1:18:1:19 | [YamlScalar] 42 | semmle.label | [YamlScalar] 42 | +| merge.yaml:2:3:2:3 | [YamlScalar] x | semmle.label | [YamlScalar] x | +| merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | semmle.label | [YamlMapping] x: 56 | +| merge.yaml:2:6:2:7 | [YamlScalar] 56 | semmle.label | [YamlScalar] 56 | +| merge.yaml:3:3:3:4 | [YamlScalar] << | semmle.label | [YamlScalar] << | +| merge.yaml:3:7:3:8 | [YamlAliasNode] *A | semmle.label | [YamlAliasNode] *A | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | semmle.label | [YamlSequence] - "name ... Knopf" | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | semmle.order | 3 | +| tst.yml:1:3:1:8 | [YamlScalar] "name" | semmle.label | [YamlScalar] "name" | +| tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | semmle.label | [YamlMapping] "name": "Jim Knopf" | +| tst.yml:1:11:1:21 | [YamlScalar] "Jim Knopf" | semmle.label | [YamlScalar] "Jim Knopf" | +| tst.yml:2:3:2:9 | [YamlScalar] address | semmle.label | [YamlScalar] address | +| tst.yml:2:12:6:3 | [YamlMapping] { | semmle.label | [YamlMapping] { | +| tst.yml:3:5:3:12 | [YamlScalar] "street" | semmle.label | [YamlScalar] "street" | +| tst.yml:3:14:3:13 | [YamlScalar] | semmle.label | [YamlScalar] | +| tst.yml:4:5:4:12 | [YamlScalar] "number" | semmle.label | [YamlScalar] "number" | +| tst.yml:4:15:4:16 | [YamlScalar] -1 | semmle.label | [YamlScalar] -1 | +| tst.yml:5:5:5:13 | [YamlScalar] "country" | semmle.label | [YamlScalar] "country" | +| tst.yml:5:16:5:27 | [YamlScalar] "Lummerland" | semmle.label | [YamlScalar] "Lummerland" | +| tst.yml:7:3:7:6 | [YamlScalar] name | semmle.label | [YamlScalar] name | +| tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | semmle.label | [YamlMapping] name: Frau Mahlzahn | +| tst.yml:7:9:7:21 | [YamlScalar] Frau Mahlzahn | semmle.label | [YamlScalar] Frau Mahlzahn | +| tst.yml:8:3:8:9 | [YamlScalar] address | semmle.label | [YamlScalar] address | +| tst.yml:9:5:9:10 | [YamlScalar] street | semmle.label | [YamlScalar] street | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | semmle.label | [YamlMapping] street: \| | +| tst.yml:9:13:11:0 | [YamlScalar] \| | semmle.label | [YamlScalar] \| | +| tst.yml:11:5:11:10 | [YamlScalar] number | semmle.label | [YamlScalar] number | +| tst.yml:11:13:11:15 | [YamlScalar] 133 | semmle.label | [YamlScalar] 133 | +| tst.yml:12:5:12:11 | [YamlScalar] country | semmle.label | [YamlScalar] country | +| tst.yml:12:14:13:18 | [YamlScalar] < | semmle.label | [YamlScalar] < | +| tst.yml:14:3:14:23 | [YamlScalar] !includ ... nal.yml | semmle.label | [YamlScalar] !includ ... nal.yml | edges -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:3:1:8 | [YAMLScalar] "name" | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:3:1:8 | [YAMLScalar] "name" | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:11:1:21 | [YAMLScalar] "Jim Knopf" | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:11:1:21 | [YAMLScalar] "Jim Knopf" | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:3:7:6 | [YAMLScalar] name | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:3:7:6 | [YAMLScalar] name | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:9:7:21 | [YAMLScalar] Frau Mahlzahn | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:9:7:21 | [YAMLScalar] Frau Mahlzahn | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:5:3:12 | [YAMLScalar] "street" | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:5:3:12 | [YAMLScalar] "street" | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:14:3:13 | [YAMLScalar] | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:14:3:13 | [YAMLScalar] | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:5:9:10 | [YAMLScalar] street | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:5:9:10 | [YAMLScalar] street | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:13:11:0 | [YAMLScalar] \| | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:13:11:0 | [YAMLScalar] \| | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:8:1:8 | [YAMLScalar] x | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:8:1:8 | [YAMLScalar] x | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:11:1:12 | [YAMLScalar] 23 | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:11:1:12 | [YAMLScalar] 23 | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:3:2:3 | [YAMLScalar] x | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:3:2:3 | [YAMLScalar] x | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:6:2:7 | [YAMLScalar] 56 | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:6:2:7 | [YAMLScalar] 56 | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:3:3:4 | [YAMLScalar] << | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:3:3:4 | [YAMLScalar] << | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:7:3:8 | [YAMLAliasNode] *A | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:7:3:8 | [YAMLAliasNode] *A | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:3:2:9 | [YAMLScalar] address | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:3:2:9 | [YAMLScalar] address | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:12:6:3 | [YAMLMapping] { | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:12:6:3 | [YAMLMapping] { | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:8:3:8:9 | [YAMLScalar] address | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:8:3:8:9 | [YAMLScalar] address | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:9:5:14:0 | [YAMLMapping] street: \| | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:9:5:14:0 | [YAMLMapping] street: \| | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:5:4:12 | [YAMLScalar] "number" | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:5:4:12 | [YAMLScalar] "number" | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:15:4:16 | [YAMLScalar] -1 | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:15:4:16 | [YAMLScalar] -1 | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:5:11:10 | [YAMLScalar] number | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:5:11:10 | [YAMLScalar] number | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:13:11:15 | [YAMLScalar] 133 | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:13:11:15 | [YAMLScalar] 133 | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:15:1:15 | [YAMLScalar] y | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:15:1:15 | [YAMLScalar] y | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:18:1:19 | [YAMLScalar] 42 | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:18:1:19 | [YAMLScalar] 42 | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:5:5:13 | [YAMLScalar] "country" | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:5:5:13 | [YAMLScalar] "country" | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:16:5:27 | [YAMLScalar] "Lummerland" | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:16:5:27 | [YAMLScalar] "Lummerland" | semmle.order | 1 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:5:12:11 | [YAMLScalar] country | semmle.label | 0 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:5:12:11 | [YAMLScalar] country | semmle.order | 0 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:14:13:18 | [YAMLScalar] < | semmle.label | 1 | -| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:14:13:18 | [YAMLScalar] < | semmle.order | 1 | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | semmle.label | 0 | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | semmle.order | 0 | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | semmle.label | 1 | -| merge.yaml:1:1:3:8 | [YAMLSequence] - &A { ... y: 42 } | merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | semmle.order | 1 | -| merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 0) x: | semmle.label | 0 | -| merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 0) x: | semmle.order | 0 | -| merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 1) y: | semmle.label | 1 | -| merge.yaml:1:3:1:21 | [YAMLMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 1) y: | semmle.order | 1 | -| merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | file://:0:0:0:0 | (Mapping 0) x: | semmle.label | 0 | -| merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | file://:0:0:0:0 | (Mapping 0) x: | semmle.order | 0 | -| merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | file://:0:0:0:0 | (Mapping 1) <<: | semmle.label | 1 | -| merge.yaml:2:3:3:8 | [YAMLMapping] x: 56 | file://:0:0:0:0 | (Mapping 1) <<: | semmle.order | 1 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | semmle.label | 0 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | semmle.order | 0 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | semmle.label | 1 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | semmle.order | 1 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:14:3:14:23 | [YAMLScalar] !includ ... nal.yml | semmle.label | 2 | -| tst.yml:1:1:14:23 | [YAMLSequence] - "name ... Knopf" | tst.yml:14:3:14:23 | [YAMLScalar] !includ ... nal.yml | semmle.order | 2 | -| tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | 0 | -| tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 0) name: | semmle.order | 0 | -| tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 1) address: | semmle.label | 1 | -| tst.yml:1:3:7:0 | [YAMLMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 1) address: | semmle.order | 1 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 0) street: | semmle.label | 0 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 0) street: | semmle.order | 0 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 1) number: | semmle.label | 1 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 1) number: | semmle.order | 1 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | 2 | -| tst.yml:2:12:6:3 | [YAMLMapping] { | file://:0:0:0:0 | (Mapping 2) country: | semmle.order | 2 | -| tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | 0 | -| tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 0) name: | semmle.order | 0 | -| tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 1) address: | semmle.label | 1 | -| tst.yml:7:3:14:0 | [YAMLMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 1) address: | semmle.order | 1 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 0) street: | semmle.label | 0 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 0) street: | semmle.order | 0 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 1) number: | semmle.label | 1 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 1) number: | semmle.order | 1 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | 2 | -| tst.yml:9:5:14:0 | [YAMLMapping] street: \| | file://:0:0:0:0 | (Mapping 2) country: | semmle.order | 2 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:3:1:8 | [YamlScalar] "name" | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:3:1:8 | [YamlScalar] "name" | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:11:1:21 | [YamlScalar] "Jim Knopf" | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:1:11:1:21 | [YamlScalar] "Jim Knopf" | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:3:7:6 | [YamlScalar] name | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:3:7:6 | [YamlScalar] name | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:9:7:21 | [YamlScalar] Frau Mahlzahn | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) name: | tst.yml:7:9:7:21 | [YamlScalar] Frau Mahlzahn | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:5:3:12 | [YamlScalar] "street" | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:5:3:12 | [YamlScalar] "street" | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:14:3:13 | [YamlScalar] | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:3:14:3:13 | [YamlScalar] | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:5:9:10 | [YamlScalar] street | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:5:9:10 | [YamlScalar] street | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:13:11:0 | [YamlScalar] \| | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) street: | tst.yml:9:13:11:0 | [YamlScalar] \| | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:8:1:8 | [YamlScalar] x | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:8:1:8 | [YamlScalar] x | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:11:1:12 | [YamlScalar] 23 | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:1:11:1:12 | [YamlScalar] 23 | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:3:2:3 | [YamlScalar] x | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:3:2:3 | [YamlScalar] x | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:6:2:7 | [YamlScalar] 56 | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 0) x: | merge.yaml:2:6:2:7 | [YamlScalar] 56 | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:3:3:4 | [YamlScalar] << | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:3:3:4 | [YamlScalar] << | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:7:3:8 | [YamlAliasNode] *A | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) <<: | merge.yaml:3:7:3:8 | [YamlAliasNode] *A | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:3:2:9 | [YamlScalar] address | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:3:2:9 | [YamlScalar] address | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:12:6:3 | [YamlMapping] { | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:2:12:6:3 | [YamlMapping] { | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:8:3:8:9 | [YamlScalar] address | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:8:3:8:9 | [YamlScalar] address | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:9:5:14:0 | [YamlMapping] street: \| | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) address: | tst.yml:9:5:14:0 | [YamlMapping] street: \| | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:5:4:12 | [YamlScalar] "number" | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:5:4:12 | [YamlScalar] "number" | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:15:4:16 | [YamlScalar] -1 | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:4:15:4:16 | [YamlScalar] -1 | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:5:11:10 | [YamlScalar] number | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:5:11:10 | [YamlScalar] number | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:13:11:15 | [YamlScalar] 133 | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) number: | tst.yml:11:13:11:15 | [YamlScalar] 133 | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:15:1:15 | [YamlScalar] y | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:15:1:15 | [YamlScalar] y | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:18:1:19 | [YamlScalar] 42 | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 1) y: | merge.yaml:1:18:1:19 | [YamlScalar] 42 | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:5:5:13 | [YamlScalar] "country" | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:5:5:13 | [YamlScalar] "country" | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:16:5:27 | [YamlScalar] "Lummerland" | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:5:16:5:27 | [YamlScalar] "Lummerland" | semmle.order | 1 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:5:12:11 | [YamlScalar] country | semmle.label | 0 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:5:12:11 | [YamlScalar] country | semmle.order | 0 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:14:13:18 | [YamlScalar] < | semmle.label | 1 | +| file://:0:0:0:0 | (Mapping 2) country: | tst.yml:12:14:13:18 | [YamlScalar] < | semmle.order | 1 | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | semmle.label | 0 | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | semmle.order | 0 | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | semmle.label | 1 | +| merge.yaml:1:1:3:8 | [YamlSequence] - &A { ... y: 42 } | merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | semmle.order | 1 | +| merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 0) x: | semmle.label | 0 | +| merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 0) x: | semmle.order | 0 | +| merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 1) y: | semmle.label | 1 | +| merge.yaml:1:3:1:21 | [YamlMapping] &A { x: 23, y: 42 } | file://:0:0:0:0 | (Mapping 1) y: | semmle.order | 1 | +| merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | file://:0:0:0:0 | (Mapping 0) x: | semmle.label | 0 | +| merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | file://:0:0:0:0 | (Mapping 0) x: | semmle.order | 0 | +| merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | file://:0:0:0:0 | (Mapping 1) <<: | semmle.label | 1 | +| merge.yaml:2:3:3:8 | [YamlMapping] x: 56 | file://:0:0:0:0 | (Mapping 1) <<: | semmle.order | 1 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | semmle.label | 0 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | semmle.order | 0 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | semmle.label | 1 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | semmle.order | 1 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:14:3:14:23 | [YamlScalar] !includ ... nal.yml | semmle.label | 2 | +| tst.yml:1:1:14:23 | [YamlSequence] - "name ... Knopf" | tst.yml:14:3:14:23 | [YamlScalar] !includ ... nal.yml | semmle.order | 2 | +| tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | 0 | +| tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 0) name: | semmle.order | 0 | +| tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 1) address: | semmle.label | 1 | +| tst.yml:1:3:7:0 | [YamlMapping] "name": "Jim Knopf" | file://:0:0:0:0 | (Mapping 1) address: | semmle.order | 1 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 0) street: | semmle.label | 0 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 0) street: | semmle.order | 0 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 1) number: | semmle.label | 1 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 1) number: | semmle.order | 1 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | 2 | +| tst.yml:2:12:6:3 | [YamlMapping] { | file://:0:0:0:0 | (Mapping 2) country: | semmle.order | 2 | +| tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 0) name: | semmle.label | 0 | +| tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 0) name: | semmle.order | 0 | +| tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 1) address: | semmle.label | 1 | +| tst.yml:7:3:14:0 | [YamlMapping] name: Frau Mahlzahn | file://:0:0:0:0 | (Mapping 1) address: | semmle.order | 1 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 0) street: | semmle.label | 0 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 0) street: | semmle.order | 0 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 1) number: | semmle.label | 1 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 1) number: | semmle.order | 1 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 2) country: | semmle.label | 2 | +| tst.yml:9:5:14:0 | [YamlMapping] street: \| | file://:0:0:0:0 | (Mapping 2) country: | semmle.order | 2 | graphProperties | semmle.graphKind | tree | diff --git a/javascript/ql/test/library-tests/YAML/tests.ql b/javascript/ql/test/library-tests/YAML/tests.ql index 664b727402e..469b57fa67c 100644 --- a/javascript/ql/test/library-tests/YAML/tests.ql +++ b/javascript/ql/test/library-tests/YAML/tests.ql @@ -1,18 +1,18 @@ import javascript -query predicate anchors(YAMLNode n, string anchor) { n.getAnchor() = anchor } +query predicate anchors(YamlNode n, string anchor) { n.getAnchor() = anchor } -query predicate eval(YAMLNode n, YAMLValue eval) { +query predicate eval(YamlNode n, YamlValue eval) { not n.eval() = n and eval = n.eval() } -query predicate yamlParseError(YAMLParseError err) { any() } +query predicate yamlParseError(YamlParseError err) { any() } -query predicate yamlMapping_maps(YAMLMapping m, YAMLValue k, YAMLValue v) { m.maps(k, v) } +query predicate yamlMapping_maps(YamlMapping m, YamlValue k, YamlValue v) { m.maps(k, v) } -query predicate yamlNode(YAMLNode n, string tag) { tag = n.getTag() } +query predicate yamlNode(YamlNode n, string tag) { tag = n.getTag() } -query predicate yamlScalar(YAMLScalar s, string style, string value) { +query predicate yamlScalar(YamlScalar s, string style, string value) { style = s.getStyle() and value = s.getValue() } diff --git a/javascript/ql/test/library-tests/frameworks/GWT/GWTGeneratedTopLevel.ql b/javascript/ql/test/library-tests/frameworks/GWT/GWTGeneratedTopLevel.ql index bc3d25d7e2d..335086bd7de 100644 --- a/javascript/ql/test/library-tests/frameworks/GWT/GWTGeneratedTopLevel.ql +++ b/javascript/ql/test/library-tests/frameworks/GWT/GWTGeneratedTopLevel.ql @@ -1,4 +1,4 @@ import semmle.javascript.frameworks.GWT -from GWTGeneratedTopLevel g +from GwtGeneratedTopLevel g select g diff --git a/javascript/ql/test/library-tests/frameworks/GWT/GWTHeader.ql b/javascript/ql/test/library-tests/frameworks/GWT/GWTHeader.ql index 14a5da47e4a..c504c8ca7bd 100644 --- a/javascript/ql/test/library-tests/frameworks/GWT/GWTHeader.ql +++ b/javascript/ql/test/library-tests/frameworks/GWT/GWTHeader.ql @@ -1,4 +1,4 @@ import semmle.javascript.frameworks.GWT -from GWTHeader h +from GwtHeader h select h diff --git a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected index 49655c0ffa3..2677e785487 100644 --- a/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected +++ b/javascript/ql/test/library-tests/frameworks/NodeJSLib/tests.expected @@ -27,6 +27,7 @@ test_RouteHandler_getAResponseHeader | src/http.js:12:19:16:1 | functio ... ar");\\n} | content-type | src/http.js:13:3:13:44 | res.set ... /html') | | src/https.js:4:33:10:1 | functio ... .foo;\\n} | location | src/https.js:7:3:7:42 | res.wri ... rget }) | | src/https.js:12:20:16:1 | functio ... ar");\\n} | content-type | src/https.js:13:3:13:44 | res.set ... /html') | +| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | content-type | src/indirect2.js:14:3:14:51 | res.set ... /json') | | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | content-type | src/indirect2.js:14:3:14:51 | res.set ... /json') | test_HeaderDefinition_defines | src/http.js:13:3:13:44 | res.set ... /html') | content-type | text/html | @@ -70,8 +71,11 @@ test_ResponseExpr | src/https.js:15:3:15:5 | res | src/https.js:12:20:16:1 | functio ... ar");\\n} | | src/indirect2.js:9:19:9:21 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:10:47:10:49 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | +| src/indirect2.js:13:33:13:35 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:13:33:13:35 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | +| src/indirect2.js:14:3:14:5 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:14:3:14:5 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | +| src/indirect2.js:15:3:15:5 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:15:3:15:5 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | | src/indirect.js:16:26:16:28 | res | src/indirect.js:16:12:20:5 | functio ... ;\\n } | | src/indirect.js:19:38:19:40 | res | src/indirect.js:16:12:20:5 | functio ... ;\\n } | @@ -85,6 +89,7 @@ test_HeaderDefinition | src/http.js:63:3:63:40 | res.set ... , "23") | src/http.js:62:19:65:1 | functio ... r2");\\n} | | src/https.js:7:3:7:42 | res.wri ... rget }) | src/https.js:4:33:10:1 | functio ... .foo;\\n} | | src/https.js:13:3:13:44 | res.set ... /html') | src/https.js:12:20:16:1 | functio ... ar");\\n} | +| src/indirect2.js:14:3:14:51 | res.set ... /json') | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:14:3:14:51 | res.set ... /json') | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | test_RouteSetup_getServer | createServer.js:2:1:2:42 | https.c ... es) {}) | createServer.js:2:1:2:42 | https.c ... es) {}) | @@ -171,6 +176,9 @@ test_RouteHandler_getAResponseExpr | src/https.js:12:20:16:1 | functio ... ar");\\n} | src/https.js:15:3:15:5 | res | | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:9:19:9:21 | res | | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:47:10:49 | res | +| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:13:33:13:35 | res | +| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:14:3:14:5 | res | +| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:15:3:15:5 | res | | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:13:33:13:35 | res | | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:14:3:14:5 | res | | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:15:3:15:5 | res | @@ -307,6 +315,7 @@ test_RequestExpr | src/indirect2.js:9:14:9:16 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:10:12:10:14 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:10:42:10:44 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | +| src/indirect2.js:13:28:13:30 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | | src/indirect2.js:13:28:13:30 | req | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | | src/indirect.js:16:21:16:23 | req | src/indirect.js:16:12:20:5 | functio ... ;\\n } | | src/indirect.js:17:28:17:30 | req | src/indirect.js:16:12:20:5 | functio ... ;\\n } | @@ -349,6 +358,7 @@ test_RouteHandler_getARequestExpr | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:9:14:9:16 | req | | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:12:10:14 | req | | src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:42:10:44 | req | +| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:13:28:13:30 | req | | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:13:28:13:30 | req | | src/indirect.js:16:12:20:5 | functio ... ;\\n } | src/indirect.js:16:21:16:23 | req | | src/indirect.js:16:12:20:5 | functio ... ;\\n } | src/indirect.js:17:28:17:30 | req | diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/UnusedParameter.expected b/javascript/ql/test/query-tests/Declarations/UnusedParameter/UnusedParameter.expected index fde6450e8e0..34cf2d268dc 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/UnusedParameter.expected +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/UnusedParameter.expected @@ -1,6 +1,6 @@ -| istype.ts:18:15:18:18 | node | Unused parameter node. | -| parameter_field.ts:6:15:6:15 | x | Unused parameter x. | -| tst2.js:1:12:1:12 | x | Unused parameter x. | -| tst2.js:29:12:29:12 | x | Unused parameter x. | -| tst.js:7:32:7:34 | idx | Unused parameter idx. | -| tst.js:12:13:12:13 | x | Unused parameter x. | +| istype.ts:18:15:18:18 | node | The parameter 'node' is never used. | +| parameter_field.ts:6:15:6:15 | x | The parameter 'x' is never used. | +| tst2.js:1:12:1:12 | x | The parameter 'x' is never used. | +| tst2.js:29:12:29:12 | x | The parameter 'x' is never used. | +| tst.js:7:32:7:34 | idx | The parameter 'idx' is never used. | +| tst.js:12:13:12:13 | x | The parameter 'x' is never used. | diff --git a/javascript/ql/test/query-tests/Expressions/BitwiseSignCheck/BitwiseSignCheck.expected b/javascript/ql/test/query-tests/Expressions/BitwiseSignCheck/BitwiseSignCheck.expected index 95e202a6752..c82afd5c4ca 100644 --- a/javascript/ql/test/query-tests/Expressions/BitwiseSignCheck/BitwiseSignCheck.expected +++ b/javascript/ql/test/query-tests/Expressions/BitwiseSignCheck/BitwiseSignCheck.expected @@ -1,3 +1,3 @@ -| tst.js:2:9:2:24 | (x & (1< 0 | Sign check of a bitwise operation | -| tst.js:14:13:14:25 | (x >>> 0) > 0 | Sign check of a bitwise operation | -| tst.js:23:1:23:21 | (x & 0x ... 00) > 0 | Sign check of a bitwise operation | +| tst.js:2:9:2:24 | (x & (1< 0 | Potentially unsafe sign check of a bitwise operation. | +| tst.js:14:13:14:25 | (x >>> 0) > 0 | Potentially unsafe sign check of a bitwise operation. | +| tst.js:23:1:23:21 | (x & 0x ... 00) > 0 | Potentially unsafe sign check of a bitwise operation. | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index 887b95b2b96..9e498c22c85 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -10057,173 +10057,173 @@ edges | typescript.ts:30:15:30:18 | path | typescript.ts:30:7:30:18 | path6 | | views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | #select -| TaintedPath-es6.js:10:26:10:45 | join("public", path) | TaintedPath-es6.js:7:20:7:26 | req.url | TaintedPath-es6.js:10:26:10:45 | join("public", path) | This path depends on $@. | TaintedPath-es6.js:7:20:7:26 | req.url | a user-provided value | -| TaintedPath.js:12:29:12:32 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:12:29:12:32 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:15:29:15:48 | "/home/user/" + path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:18:33:18:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:18:33:18:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:21:33:21:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:21:33:21:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:24:33:24:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:24:33:24:36 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:33:31:33:34 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:33:31:33:34 | path | This path depends on $@. | TaintedPath.js:9:24:9:30 | req.url | a user-provided value | -| TaintedPath.js:42:29:42:52 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:42:29:42:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:46:29:46:49 | pathMod ... n(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:46:29:46:49 | pathMod ... n(path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:48:29:48:58 | pathMod ... ath, z) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:48:29:48:58 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:50:29:50:54 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:50:29:50:54 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:52:29:52:56 | pathMod ... , path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:52:29:52:56 | pathMod ... , path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:54:29:54:56 | pathMod ... ath, x) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:54:29:54:56 | pathMod ... ath, x) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:56:29:56:52 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:56:29:56:52 | pathMod ... e(path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:58:29:58:61 | pathMod ... ath, z) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:58:29:58:61 | pathMod ... ath, z) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:60:29:60:61 | pathMod ... h(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:60:29:60:61 | pathMod ... h(path) | This path depends on $@. | TaintedPath.js:38:20:38:26 | req.url | a user-provided value | -| TaintedPath.js:71:26:71:45 | Cookie.get("unsafe") | TaintedPath.js:95:30:95:31 | ev | TaintedPath.js:71:26:71:45 | Cookie.get("unsafe") | This path depends on $@. | TaintedPath.js:95:30:95:31 | ev | a user-provided value | -| TaintedPath.js:77:31:77:76 | require ... ).query | TaintedPath.js:77:63:77:69 | req.url | TaintedPath.js:77:31:77:76 | require ... ).query | This path depends on $@. | TaintedPath.js:77:63:77:69 | req.url | a user-provided value | -| TaintedPath.js:78:31:78:74 | require ... ).query | TaintedPath.js:78:61:78:67 | req.url | TaintedPath.js:78:31:78:74 | require ... ).query | This path depends on $@. | TaintedPath.js:78:61:78:67 | req.url | a user-provided value | -| TaintedPath.js:79:31:79:73 | require ... ).query | TaintedPath.js:79:60:79:66 | req.url | TaintedPath.js:79:31:79:73 | require ... ).query | This path depends on $@. | TaintedPath.js:79:60:79:66 | req.url | a user-provided value | -| TaintedPath.js:87:48:87:60 | req.params[0] | TaintedPath.js:87:48:87:60 | req.params[0] | TaintedPath.js:87:48:87:60 | req.params[0] | This path depends on $@. | TaintedPath.js:87:48:87:60 | req.params[0] | a user-provided value | -| TaintedPath.js:102:28:102:48 | fs.real ... c(path) | TaintedPath.js:100:23:100:29 | req.url | TaintedPath.js:102:28:102:48 | fs.real ... c(path) | This path depends on $@. | TaintedPath.js:100:23:100:29 | req.url | a user-provided value | -| TaintedPath.js:105:45:105:52 | realpath | TaintedPath.js:100:23:100:29 | req.url | TaintedPath.js:105:45:105:52 | realpath | This path depends on $@. | TaintedPath.js:100:23:100:29 | req.url | a user-provided value | -| TaintedPath.js:138:23:138:26 | path | TaintedPath.js:136:23:136:29 | req.url | TaintedPath.js:138:23:138:26 | path | This path depends on $@. | TaintedPath.js:136:23:136:29 | req.url | a user-provided value | -| TaintedPath.js:144:19:144:22 | path | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:144:19:144:22 | path | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:148:19:148:33 | split.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:148:19:148:33 | split.join("/") | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:152:19:152:26 | split[x] | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:152:19:152:26 | split[x] | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:153:19:153:35 | prefix + split[x] | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:153:19:153:35 | prefix + split[x] | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:156:19:156:37 | concatted.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:156:19:156:37 | concatted.join("/") | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:159:19:159:38 | concatted2.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:159:19:159:38 | concatted2.join("/") | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:161:19:161:29 | split.pop() | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:161:19:161:29 | split.pop() | This path depends on $@. | TaintedPath.js:142:24:142:30 | req.url | a user-provided value | -| TaintedPath.js:170:29:170:55 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:170:29:170:55 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:176:29:176:52 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:176:29:176:52 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:177:29:177:53 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:177:29:177:53 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:178:29:178:51 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:178:29:178:51 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:179:29:179:57 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:179:29:179:57 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:194:29:194:73 | "prefix ... +/, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:194:29:194:73 | "prefix ... +/, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | This path depends on $@. | TaintedPath.js:166:24:166:30 | req.url | a user-provided value | -| TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | TaintedPath.js:203:38:203:44 | req.url | TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | This path depends on $@. | TaintedPath.js:203:38:203:44 | req.url | a user-provided value | -| TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | This path depends on $@. | TaintedPath.js:204:51:204:57 | req.url | a user-provided value | -| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | This path depends on $@. | TaintedPath.js:206:44:206:50 | req.url | a user-provided value | -| TaintedPath.js:212:31:212:34 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:212:31:212:34 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value | -| TaintedPath.js:213:45:213:48 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:213:45:213:48 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value | -| TaintedPath.js:214:35:214:38 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:214:35:214:38 | path | This path depends on $@. | TaintedPath.js:211:24:211:30 | req.url | a user-provided value | -| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | This path depends on $@. | express.js:8:20:8:32 | req.query.bar | a user-provided value | -| handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | This path depends on $@. | handlebars.js:29:46:29:60 | req.params.path | a user-provided value | -| handlebars.js:15:25:15:32 | filePath | handlebars.js:43:15:43:29 | req.params.path | handlebars.js:15:25:15:32 | filePath | This path depends on $@. | handlebars.js:43:15:43:29 | req.params.path | a user-provided value | -| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | -| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | -| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | -| normalizedPaths.js:16:19:16:53 | pathMod ... .html') | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:16:19:16:53 | pathMod ... .html') | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | -| normalizedPaths.js:17:19:17:57 | pathMod ... , path) | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:17:19:17:57 | pathMod ... , path) | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | -| normalizedPaths.js:23:19:23:22 | path | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:23:19:23:22 | path | This path depends on $@. | normalizedPaths.js:21:35:21:48 | req.query.path | a user-provided value | -| normalizedPaths.js:24:19:24:29 | './' + path | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:24:19:24:29 | './' + path | This path depends on $@. | normalizedPaths.js:21:35:21:48 | req.query.path | a user-provided value | -| normalizedPaths.js:25:19:25:38 | path + '/index.html' | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:25:19:25:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:21:35:21:48 | req.query.path | a user-provided value | -| normalizedPaths.js:26:19:26:53 | pathMod ... .html') | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:26:19:26:53 | pathMod ... .html') | This path depends on $@. | normalizedPaths.js:21:35:21:48 | req.query.path | a user-provided value | -| normalizedPaths.js:27:19:27:57 | pathMod ... , path) | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:27:19:27:57 | pathMod ... , path) | This path depends on $@. | normalizedPaths.js:21:35:21:48 | req.query.path | a user-provided value | -| normalizedPaths.js:36:19:36:22 | path | normalizedPaths.js:31:35:31:48 | req.query.path | normalizedPaths.js:36:19:36:22 | path | This path depends on $@. | normalizedPaths.js:31:35:31:48 | req.query.path | a user-provided value | -| normalizedPaths.js:41:21:41:24 | path | normalizedPaths.js:31:35:31:48 | req.query.path | normalizedPaths.js:41:21:41:24 | path | This path depends on $@. | normalizedPaths.js:31:35:31:48 | req.query.path | a user-provided value | -| normalizedPaths.js:59:19:59:22 | path | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:59:19:59:22 | path | This path depends on $@. | normalizedPaths.js:54:35:54:48 | req.query.path | a user-provided value | -| normalizedPaths.js:63:19:63:38 | path + "/index.html" | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:63:19:63:38 | path + "/index.html" | This path depends on $@. | normalizedPaths.js:54:35:54:48 | req.query.path | a user-provided value | -| normalizedPaths.js:68:21:68:24 | path | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:68:21:68:24 | path | This path depends on $@. | normalizedPaths.js:54:35:54:48 | req.query.path | a user-provided value | -| normalizedPaths.js:78:22:78:25 | path | normalizedPaths.js:73:42:73:55 | req.query.path | normalizedPaths.js:78:22:78:25 | path | This path depends on $@. | normalizedPaths.js:73:42:73:55 | req.query.path | a user-provided value | -| normalizedPaths.js:87:29:87:32 | path | normalizedPaths.js:82:14:82:27 | req.query.path | normalizedPaths.js:87:29:87:32 | path | This path depends on $@. | normalizedPaths.js:82:14:82:27 | req.query.path | a user-provided value | -| normalizedPaths.js:90:31:90:34 | path | normalizedPaths.js:82:14:82:27 | req.query.path | normalizedPaths.js:90:31:90:34 | path | This path depends on $@. | normalizedPaths.js:82:14:82:27 | req.query.path | a user-provided value | -| normalizedPaths.js:99:29:99:32 | path | normalizedPaths.js:94:35:94:48 | req.query.path | normalizedPaths.js:99:29:99:32 | path | This path depends on $@. | normalizedPaths.js:94:35:94:48 | req.query.path | a user-provided value | -| normalizedPaths.js:119:19:119:22 | path | normalizedPaths.js:117:30:117:43 | req.query.path | normalizedPaths.js:119:19:119:22 | path | This path depends on $@. | normalizedPaths.js:117:30:117:43 | req.query.path | a user-provided value | -| normalizedPaths.js:120:19:120:53 | pathMod ... .html') | normalizedPaths.js:117:30:117:43 | req.query.path | normalizedPaths.js:120:19:120:53 | pathMod ... .html') | This path depends on $@. | normalizedPaths.js:117:30:117:43 | req.query.path | a user-provided value | -| normalizedPaths.js:135:21:135:24 | path | normalizedPaths.js:130:35:130:48 | req.query.path | normalizedPaths.js:135:21:135:24 | path | This path depends on $@. | normalizedPaths.js:130:35:130:48 | req.query.path | a user-provided value | -| normalizedPaths.js:144:21:144:24 | path | normalizedPaths.js:139:48:139:61 | req.query.path | normalizedPaths.js:144:21:144:24 | path | This path depends on $@. | normalizedPaths.js:139:48:139:61 | req.query.path | a user-provided value | -| normalizedPaths.js:151:21:151:24 | path | normalizedPaths.js:148:44:148:57 | req.query.path | normalizedPaths.js:151:21:151:24 | path | This path depends on $@. | normalizedPaths.js:148:44:148:57 | req.query.path | a user-provided value | -| normalizedPaths.js:153:21:153:24 | path | normalizedPaths.js:148:44:148:57 | req.query.path | normalizedPaths.js:153:21:153:24 | path | This path depends on $@. | normalizedPaths.js:148:44:148:57 | req.query.path | a user-provided value | -| normalizedPaths.js:165:19:165:22 | path | normalizedPaths.js:160:35:160:48 | req.query.path | normalizedPaths.js:165:19:165:22 | path | This path depends on $@. | normalizedPaths.js:160:35:160:48 | req.query.path | a user-provided value | -| normalizedPaths.js:170:21:170:24 | path | normalizedPaths.js:160:35:160:48 | req.query.path | normalizedPaths.js:170:21:170:24 | path | This path depends on $@. | normalizedPaths.js:160:35:160:48 | req.query.path | a user-provided value | -| normalizedPaths.js:184:19:184:22 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:184:19:184:22 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:187:21:187:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:187:21:187:24 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:189:21:189:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:189:21:189:24 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:192:21:192:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:192:21:192:24 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:194:21:194:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:194:21:194:24 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:199:21:199:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:199:21:199:24 | path | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:205:21:205:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:205:21:205:34 | normalizedPath | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:208:21:208:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:208:21:208:34 | normalizedPath | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:210:21:210:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:210:21:210:34 | normalizedPath | This path depends on $@. | normalizedPaths.js:174:14:174:27 | req.query.path | a user-provided value | -| normalizedPaths.js:222:21:222:24 | path | normalizedPaths.js:214:35:214:48 | req.query.path | normalizedPaths.js:222:21:222:24 | path | This path depends on $@. | normalizedPaths.js:214:35:214:48 | req.query.path | a user-provided value | -| normalizedPaths.js:228:21:228:24 | path | normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:228:21:228:24 | path | This path depends on $@. | normalizedPaths.js:226:35:226:48 | req.query.path | a user-provided value | -| normalizedPaths.js:238:19:238:22 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:238:19:238:22 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value | -| normalizedPaths.js:245:21:245:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:245:21:245:24 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value | -| normalizedPaths.js:250:21:250:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:250:21:250:24 | path | This path depends on $@. | normalizedPaths.js:236:33:236:46 | req.query.path | a user-provided value | -| normalizedPaths.js:256:19:256:22 | path | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:256:19:256:22 | path | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:262:21:262:24 | path | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:262:21:262:24 | path | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:270:21:270:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:270:21:270:27 | newpath | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:278:21:278:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:278:21:278:27 | newpath | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:286:21:286:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:286:21:286:27 | newpath | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:296:21:296:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:296:21:296:27 | newpath | This path depends on $@. | normalizedPaths.js:254:33:254:46 | req.query.path | a user-provided value | -| normalizedPaths.js:304:18:304:21 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:304:18:304:21 | path | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:309:19:309:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:309:19:309:22 | path | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:313:19:313:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:313:19:313:22 | path | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:316:19:316:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:316:19:316:22 | path | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:325:19:325:32 | normalizedPath | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:325:19:325:32 | normalizedPath | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:332:19:332:32 | normalizedPath | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:332:19:332:32 | normalizedPath | This path depends on $@. | normalizedPaths.js:303:13:303:26 | req.query.path | a user-provided value | -| normalizedPaths.js:341:18:341:21 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:341:18:341:21 | path | This path depends on $@. | normalizedPaths.js:339:32:339:45 | req.query.path | a user-provided value | -| normalizedPaths.js:346:19:346:22 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:346:19:346:22 | path | This path depends on $@. | normalizedPaths.js:339:32:339:45 | req.query.path | a user-provided value | -| normalizedPaths.js:356:19:356:22 | path | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:356:19:356:22 | path | This path depends on $@. | normalizedPaths.js:354:14:354:27 | req.query.path | a user-provided value | -| normalizedPaths.js:363:21:363:31 | requestPath | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:363:21:363:31 | requestPath | This path depends on $@. | normalizedPaths.js:354:14:354:27 | req.query.path | a user-provided value | -| normalizedPaths.js:379:19:379:22 | path | normalizedPaths.js:377:14:377:27 | req.query.path | normalizedPaths.js:379:19:379:22 | path | This path depends on $@. | normalizedPaths.js:377:14:377:27 | req.query.path | a user-provided value | -| normalizedPaths.js:381:19:381:29 | slash(path) | normalizedPaths.js:377:14:377:27 | req.query.path | normalizedPaths.js:381:19:381:29 | slash(path) | This path depends on $@. | normalizedPaths.js:377:14:377:27 | req.query.path | a user-provided value | -| normalizedPaths.js:388:19:388:22 | path | normalizedPaths.js:385:35:385:45 | req.query.x | normalizedPaths.js:388:19:388:22 | path | This path depends on $@. | normalizedPaths.js:385:35:385:45 | req.query.x | a user-provided value | -| normalizedPaths.js:399:21:399:24 | path | normalizedPaths.js:385:35:385:45 | req.query.x | normalizedPaths.js:399:21:399:24 | path | This path depends on $@. | normalizedPaths.js:385:35:385:45 | req.query.x | a user-provided value | -| other-fs-libraries.js:11:19:11:22 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:11:19:11:22 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:12:27:12:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:12:27:12:30 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:13:24:13:27 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:13:24:13:27 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:14:27:14:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:14:27:14:30 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:16:34:16:37 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:16:34:16:37 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:17:35:17:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:17:35:17:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:19:56:19:59 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:19:56:19:59 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:24:35:24:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:24:35:24:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | -| other-fs-libraries.js:40:35:40:38 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:40:35:40:38 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value | -| other-fs-libraries.js:41:50:41:53 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:41:50:41:53 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value | -| other-fs-libraries.js:42:53:42:56 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:42:53:42:56 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value | -| other-fs-libraries.js:51:19:51:22 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:51:19:51:22 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:52:24:52:27 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:52:24:52:27 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:54:36:54:39 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:54:36:54:39 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:55:36:55:39 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:55:36:55:39 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:57:46:57:49 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:57:46:57:49 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:59:39:59:42 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:59:39:59:42 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:62:43:62:46 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:62:43:62:46 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:63:51:63:54 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:63:51:63:54 | path | This path depends on $@. | other-fs-libraries.js:49:24:49:30 | req.url | a user-provided value | -| other-fs-libraries.js:70:19:70:22 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:70:19:70:22 | path | This path depends on $@. | other-fs-libraries.js:68:24:68:30 | req.url | a user-provided value | -| other-fs-libraries.js:71:10:71:13 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:71:10:71:13 | path | This path depends on $@. | other-fs-libraries.js:68:24:68:30 | req.url | a user-provided value | -| other-fs-libraries.js:72:15:72:18 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:72:15:72:18 | path | This path depends on $@. | other-fs-libraries.js:68:24:68:30 | req.url | a user-provided value | -| prettier.js:7:28:7:28 | p | prettier.js:6:13:6:13 | p | prettier.js:7:28:7:28 | p | This path depends on $@. | prettier.js:6:13:6:13 | p | a user-provided value | -| prettier.js:11:44:11:44 | p | prettier.js:6:13:6:13 | p | prettier.js:11:44:11:44 | p | This path depends on $@. | prettier.js:6:13:6:13 | p | a user-provided value | -| pupeteer.js:9:28:9:34 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:9:28:9:34 | tainted | This path depends on $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | a user-provided value | -| pupeteer.js:13:37:13:43 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:13:37:13:43 | tainted | This path depends on $@. | pupeteer.js:5:28:5:53 | parseTo ... t).name | a user-provided value | -| tainted-access-paths.js:8:19:8:22 | path | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:8:19:8:22 | path | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:12:19:12:25 | obj.sub | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:12:19:12:25 | obj.sub | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:26:19:26:26 | obj.sub3 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:26:19:26:26 | obj.sub3 | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:29:21:29:28 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:29:21:29:28 | obj.sub4 | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:30:23:30:30 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:30:23:30:30 | obj.sub4 | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:31:23:31:30 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:31:23:31:30 | obj.sub4 | This path depends on $@. | tainted-access-paths.js:6:24:6:30 | req.url | a user-provided value | -| tainted-access-paths.js:40:23:40:26 | path | tainted-access-paths.js:39:24:39:30 | req.url | tainted-access-paths.js:40:23:40:26 | path | This path depends on $@. | tainted-access-paths.js:39:24:39:30 | req.url | a user-provided value | -| tainted-access-paths.js:49:10:49:13 | path | tainted-access-paths.js:48:24:48:30 | req.url | tainted-access-paths.js:49:10:49:13 | path | This path depends on $@. | tainted-access-paths.js:48:24:48:30 | req.url | a user-provided value | -| tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value | -| tainted-require.js:12:29:12:47 | req.param("module") | tainted-require.js:12:29:12:47 | req.param("module") | tainted-require.js:12:29:12:47 | req.param("module") | This path depends on $@. | tainted-require.js:12:29:12:47 | req.param("module") | a user-provided value | -| tainted-require.js:14:11:14:29 | req.param("module") | tainted-require.js:14:11:14:29 | req.param("module") | tainted-require.js:14:11:14:29 | req.param("module") | This path depends on $@. | tainted-require.js:14:11:14:29 | req.param("module") | a user-provided value | -| tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | a user-provided value | -| tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | a user-provided value | -| tainted-sendFile.js:18:43:18:58 | req.param("dir") | tainted-sendFile.js:18:43:18:58 | req.param("dir") | tainted-sendFile.js:18:43:18:58 | req.param("dir") | This path depends on $@. | tainted-sendFile.js:18:43:18:58 | req.param("dir") | a user-provided value | -| tainted-sendFile.js:24:16:24:49 | path.re ... rams.x) | tainted-sendFile.js:24:37:24:48 | req.params.x | tainted-sendFile.js:24:16:24:49 | path.re ... rams.x) | This path depends on $@. | tainted-sendFile.js:24:37:24:48 | req.params.x | a user-provided value | -| tainted-sendFile.js:25:16:25:46 | path.jo ... rams.x) | tainted-sendFile.js:25:34:25:45 | req.params.x | tainted-sendFile.js:25:16:25:46 | path.jo ... rams.x) | This path depends on $@. | tainted-sendFile.js:25:34:25:45 | req.params.x | a user-provided value | -| tainted-string-steps.js:8:18:8:34 | path.substring(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:8:18:8:34 | path.substring(4) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:9:18:9:37 | path.substring(0, i) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:9:18:9:37 | path.substring(0, i) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:10:18:10:31 | path.substr(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:10:18:10:31 | path.substr(4) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:11:18:11:30 | path.slice(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:11:18:11:30 | path.slice(4) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:13:18:13:37 | path.concat(unknown) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:13:18:13:37 | path.concat(unknown) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:14:18:14:37 | unknown.concat(path) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:14:18:14:37 | unknown.concat(path) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:15:18:15:46 | unknown ... , path) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:15:18:15:46 | unknown ... , path) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:17:18:17:28 | path.trim() | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:17:18:17:28 | path.trim() | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:18:18:18:35 | path.toLowerCase() | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:18:18:18:35 | path.toLowerCase() | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:22:18:22:35 | path.split('/')[i] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:22:18:22:35 | path.split('/')[i] | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:23:18:23:36 | path.split(/\\//)[i] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:23:18:23:36 | path.split(/\\//)[i] | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:24:18:24:35 | path.split("?")[0] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:24:18:24:35 | path.split("?")[0] | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:26:18:26:45 | path.sp ... hatever | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:26:18:26:45 | path.sp ... hatever | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| tainted-string-steps.js:27:18:27:36 | path.split(unknown) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:27:18:27:36 | path.split(unknown) | This path depends on $@. | tainted-string-steps.js:6:24:6:30 | req.url | a user-provided value | -| torrents.js:7:25:7:27 | loc | torrents.js:5:13:5:38 | parseTo ... t).name | torrents.js:7:25:7:27 | loc | This path depends on $@. | torrents.js:5:13:5:38 | parseTo ... t).name | a user-provided value | -| typescript.ts:12:29:12:32 | path | typescript.ts:9:24:9:30 | req.url | typescript.ts:12:29:12:32 | path | This path depends on $@. | typescript.ts:9:24:9:30 | req.url | a user-provided value | -| typescript.ts:21:39:21:43 | path3 | typescript.ts:9:24:9:30 | req.url | typescript.ts:21:39:21:43 | path3 | This path depends on $@. | typescript.ts:9:24:9:30 | req.url | a user-provided value | -| typescript.ts:24:39:24:43 | path4 | typescript.ts:9:24:9:30 | req.url | typescript.ts:24:39:24:43 | path4 | This path depends on $@. | typescript.ts:9:24:9:30 | req.url | a user-provided value | -| typescript.ts:32:29:32:33 | path6 | typescript.ts:9:24:9:30 | req.url | typescript.ts:32:29:32:33 | path6 | This path depends on $@. | typescript.ts:9:24:9:30 | req.url | a user-provided value | -| views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value | +| TaintedPath-es6.js:10:26:10:45 | join("public", path) | TaintedPath-es6.js:7:20:7:26 | req.url | TaintedPath-es6.js:10:26:10:45 | join("public", path) | $@ flows to here and is used in a path. | TaintedPath-es6.js:7:20:7:26 | req.url | User-provided value | +| TaintedPath.js:12:29:12:32 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:12:29:12:32 | path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:15:29:15:48 | "/home/user/" + path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:15:29:15:48 | "/home/user/" + path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:18:33:18:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:18:33:18:36 | path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:21:33:21:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:21:33:21:36 | path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:24:33:24:36 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:24:33:24:36 | path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:33:31:33:34 | path | TaintedPath.js:9:24:9:30 | req.url | TaintedPath.js:33:31:33:34 | path | $@ flows to here and is used in a path. | TaintedPath.js:9:24:9:30 | req.url | User-provided value | +| TaintedPath.js:42:29:42:52 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:42:29:42:52 | pathMod ... e(path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:46:29:46:49 | pathMod ... n(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:46:29:46:49 | pathMod ... n(path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:48:29:48:58 | pathMod ... ath, z) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:48:29:48:58 | pathMod ... ath, z) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:50:29:50:54 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:50:29:50:54 | pathMod ... e(path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:52:29:52:56 | pathMod ... , path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:52:29:52:56 | pathMod ... , path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:54:29:54:56 | pathMod ... ath, x) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:54:29:54:56 | pathMod ... ath, x) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:56:29:56:52 | pathMod ... e(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:56:29:56:52 | pathMod ... e(path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:58:29:58:61 | pathMod ... ath, z) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:58:29:58:61 | pathMod ... ath, z) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:60:29:60:61 | pathMod ... h(path) | TaintedPath.js:38:20:38:26 | req.url | TaintedPath.js:60:29:60:61 | pathMod ... h(path) | $@ flows to here and is used in a path. | TaintedPath.js:38:20:38:26 | req.url | User-provided value | +| TaintedPath.js:71:26:71:45 | Cookie.get("unsafe") | TaintedPath.js:95:30:95:31 | ev | TaintedPath.js:71:26:71:45 | Cookie.get("unsafe") | $@ flows to here and is used in a path. | TaintedPath.js:95:30:95:31 | ev | User-provided value | +| TaintedPath.js:77:31:77:76 | require ... ).query | TaintedPath.js:77:63:77:69 | req.url | TaintedPath.js:77:31:77:76 | require ... ).query | $@ flows to here and is used in a path. | TaintedPath.js:77:63:77:69 | req.url | User-provided value | +| TaintedPath.js:78:31:78:74 | require ... ).query | TaintedPath.js:78:61:78:67 | req.url | TaintedPath.js:78:31:78:74 | require ... ).query | $@ flows to here and is used in a path. | TaintedPath.js:78:61:78:67 | req.url | User-provided value | +| TaintedPath.js:79:31:79:73 | require ... ).query | TaintedPath.js:79:60:79:66 | req.url | TaintedPath.js:79:31:79:73 | require ... ).query | $@ flows to here and is used in a path. | TaintedPath.js:79:60:79:66 | req.url | User-provided value | +| TaintedPath.js:87:48:87:60 | req.params[0] | TaintedPath.js:87:48:87:60 | req.params[0] | TaintedPath.js:87:48:87:60 | req.params[0] | $@ flows to here and is used in a path. | TaintedPath.js:87:48:87:60 | req.params[0] | User-provided value | +| TaintedPath.js:102:28:102:48 | fs.real ... c(path) | TaintedPath.js:100:23:100:29 | req.url | TaintedPath.js:102:28:102:48 | fs.real ... c(path) | $@ flows to here and is used in a path. | TaintedPath.js:100:23:100:29 | req.url | User-provided value | +| TaintedPath.js:105:45:105:52 | realpath | TaintedPath.js:100:23:100:29 | req.url | TaintedPath.js:105:45:105:52 | realpath | $@ flows to here and is used in a path. | TaintedPath.js:100:23:100:29 | req.url | User-provided value | +| TaintedPath.js:138:23:138:26 | path | TaintedPath.js:136:23:136:29 | req.url | TaintedPath.js:138:23:138:26 | path | $@ flows to here and is used in a path. | TaintedPath.js:136:23:136:29 | req.url | User-provided value | +| TaintedPath.js:144:19:144:22 | path | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:144:19:144:22 | path | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:148:19:148:33 | split.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:148:19:148:33 | split.join("/") | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:152:19:152:26 | split[x] | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:152:19:152:26 | split[x] | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:153:19:153:35 | prefix + split[x] | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:153:19:153:35 | prefix + split[x] | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:156:19:156:37 | concatted.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:156:19:156:37 | concatted.join("/") | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:159:19:159:38 | concatted2.join("/") | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:159:19:159:38 | concatted2.join("/") | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:161:19:161:29 | split.pop() | TaintedPath.js:142:24:142:30 | req.url | TaintedPath.js:161:19:161:29 | split.pop() | $@ flows to here and is used in a path. | TaintedPath.js:142:24:142:30 | req.url | User-provided value | +| TaintedPath.js:170:29:170:55 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:170:29:170:55 | path.re ... /g, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:176:29:176:52 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:176:29:176:52 | path.re ... /g, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:177:29:177:53 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:177:29:177:53 | path.re ... /g, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:178:29:178:51 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:178:29:178:51 | path.re ... /g, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:179:29:179:57 | path.re ... /g, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:179:29:179:57 | path.re ... /g, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:194:29:194:73 | "prefix ... +/, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:194:29:194:73 | "prefix ... +/, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | TaintedPath.js:166:24:166:30 | req.url | TaintedPath.js:195:29:195:84 | pathMod ... +/, '') | $@ flows to here and is used in a path. | TaintedPath.js:166:24:166:30 | req.url | User-provided value | +| TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | TaintedPath.js:203:38:203:44 | req.url | TaintedPath.js:203:29:203:49 | qs.pars ... rl).foo | $@ flows to here and is used in a path. | TaintedPath.js:203:38:203:44 | req.url | User-provided value | +| TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | TaintedPath.js:204:51:204:57 | req.url | TaintedPath.js:204:29:204:63 | qs.pars ... l)).foo | $@ flows to here and is used in a path. | TaintedPath.js:204:51:204:57 | req.url | User-provided value | +| TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | TaintedPath.js:206:44:206:50 | req.url | TaintedPath.js:206:29:206:55 | parseqs ... rl).foo | $@ flows to here and is used in a path. | TaintedPath.js:206:44:206:50 | req.url | User-provided value | +| TaintedPath.js:212:31:212:34 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:212:31:212:34 | path | $@ flows to here and is used in a path. | TaintedPath.js:211:24:211:30 | req.url | User-provided value | +| TaintedPath.js:213:45:213:48 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:213:45:213:48 | path | $@ flows to here and is used in a path. | TaintedPath.js:211:24:211:30 | req.url | User-provided value | +| TaintedPath.js:214:35:214:38 | path | TaintedPath.js:211:24:211:30 | req.url | TaintedPath.js:214:35:214:38 | path | $@ flows to here and is used in a path. | TaintedPath.js:211:24:211:30 | req.url | User-provided value | +| express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | express.js:8:20:8:32 | req.query.bar | $@ flows to here and is used in a path. | express.js:8:20:8:32 | req.query.bar | User-provided value | +| handlebars.js:11:32:11:39 | filePath | handlebars.js:29:46:29:60 | req.params.path | handlebars.js:11:32:11:39 | filePath | $@ flows to here and is used in a path. | handlebars.js:29:46:29:60 | req.params.path | User-provided value | +| handlebars.js:15:25:15:32 | filePath | handlebars.js:43:15:43:29 | req.params.path | handlebars.js:15:25:15:32 | filePath | $@ flows to here and is used in a path. | handlebars.js:43:15:43:29 | req.params.path | User-provided value | +| normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:11:14:11:27 | req.query.path | User-provided value | +| normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | $@ flows to here and is used in a path. | normalizedPaths.js:11:14:11:27 | req.query.path | User-provided value | +| normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | $@ flows to here and is used in a path. | normalizedPaths.js:11:14:11:27 | req.query.path | User-provided value | +| normalizedPaths.js:16:19:16:53 | pathMod ... .html') | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:16:19:16:53 | pathMod ... .html') | $@ flows to here and is used in a path. | normalizedPaths.js:11:14:11:27 | req.query.path | User-provided value | +| normalizedPaths.js:17:19:17:57 | pathMod ... , path) | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:17:19:17:57 | pathMod ... , path) | $@ flows to here and is used in a path. | normalizedPaths.js:11:14:11:27 | req.query.path | User-provided value | +| normalizedPaths.js:23:19:23:22 | path | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:23:19:23:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:21:35:21:48 | req.query.path | User-provided value | +| normalizedPaths.js:24:19:24:29 | './' + path | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:24:19:24:29 | './' + path | $@ flows to here and is used in a path. | normalizedPaths.js:21:35:21:48 | req.query.path | User-provided value | +| normalizedPaths.js:25:19:25:38 | path + '/index.html' | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:25:19:25:38 | path + '/index.html' | $@ flows to here and is used in a path. | normalizedPaths.js:21:35:21:48 | req.query.path | User-provided value | +| normalizedPaths.js:26:19:26:53 | pathMod ... .html') | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:26:19:26:53 | pathMod ... .html') | $@ flows to here and is used in a path. | normalizedPaths.js:21:35:21:48 | req.query.path | User-provided value | +| normalizedPaths.js:27:19:27:57 | pathMod ... , path) | normalizedPaths.js:21:35:21:48 | req.query.path | normalizedPaths.js:27:19:27:57 | pathMod ... , path) | $@ flows to here and is used in a path. | normalizedPaths.js:21:35:21:48 | req.query.path | User-provided value | +| normalizedPaths.js:36:19:36:22 | path | normalizedPaths.js:31:35:31:48 | req.query.path | normalizedPaths.js:36:19:36:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:31:35:31:48 | req.query.path | User-provided value | +| normalizedPaths.js:41:21:41:24 | path | normalizedPaths.js:31:35:31:48 | req.query.path | normalizedPaths.js:41:21:41:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:31:35:31:48 | req.query.path | User-provided value | +| normalizedPaths.js:59:19:59:22 | path | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:59:19:59:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:54:35:54:48 | req.query.path | User-provided value | +| normalizedPaths.js:63:19:63:38 | path + "/index.html" | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:63:19:63:38 | path + "/index.html" | $@ flows to here and is used in a path. | normalizedPaths.js:54:35:54:48 | req.query.path | User-provided value | +| normalizedPaths.js:68:21:68:24 | path | normalizedPaths.js:54:35:54:48 | req.query.path | normalizedPaths.js:68:21:68:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:54:35:54:48 | req.query.path | User-provided value | +| normalizedPaths.js:78:22:78:25 | path | normalizedPaths.js:73:42:73:55 | req.query.path | normalizedPaths.js:78:22:78:25 | path | $@ flows to here and is used in a path. | normalizedPaths.js:73:42:73:55 | req.query.path | User-provided value | +| normalizedPaths.js:87:29:87:32 | path | normalizedPaths.js:82:14:82:27 | req.query.path | normalizedPaths.js:87:29:87:32 | path | $@ flows to here and is used in a path. | normalizedPaths.js:82:14:82:27 | req.query.path | User-provided value | +| normalizedPaths.js:90:31:90:34 | path | normalizedPaths.js:82:14:82:27 | req.query.path | normalizedPaths.js:90:31:90:34 | path | $@ flows to here and is used in a path. | normalizedPaths.js:82:14:82:27 | req.query.path | User-provided value | +| normalizedPaths.js:99:29:99:32 | path | normalizedPaths.js:94:35:94:48 | req.query.path | normalizedPaths.js:99:29:99:32 | path | $@ flows to here and is used in a path. | normalizedPaths.js:94:35:94:48 | req.query.path | User-provided value | +| normalizedPaths.js:119:19:119:22 | path | normalizedPaths.js:117:30:117:43 | req.query.path | normalizedPaths.js:119:19:119:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:117:30:117:43 | req.query.path | User-provided value | +| normalizedPaths.js:120:19:120:53 | pathMod ... .html') | normalizedPaths.js:117:30:117:43 | req.query.path | normalizedPaths.js:120:19:120:53 | pathMod ... .html') | $@ flows to here and is used in a path. | normalizedPaths.js:117:30:117:43 | req.query.path | User-provided value | +| normalizedPaths.js:135:21:135:24 | path | normalizedPaths.js:130:35:130:48 | req.query.path | normalizedPaths.js:135:21:135:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:130:35:130:48 | req.query.path | User-provided value | +| normalizedPaths.js:144:21:144:24 | path | normalizedPaths.js:139:48:139:61 | req.query.path | normalizedPaths.js:144:21:144:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:139:48:139:61 | req.query.path | User-provided value | +| normalizedPaths.js:151:21:151:24 | path | normalizedPaths.js:148:44:148:57 | req.query.path | normalizedPaths.js:151:21:151:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:148:44:148:57 | req.query.path | User-provided value | +| normalizedPaths.js:153:21:153:24 | path | normalizedPaths.js:148:44:148:57 | req.query.path | normalizedPaths.js:153:21:153:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:148:44:148:57 | req.query.path | User-provided value | +| normalizedPaths.js:165:19:165:22 | path | normalizedPaths.js:160:35:160:48 | req.query.path | normalizedPaths.js:165:19:165:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:160:35:160:48 | req.query.path | User-provided value | +| normalizedPaths.js:170:21:170:24 | path | normalizedPaths.js:160:35:160:48 | req.query.path | normalizedPaths.js:170:21:170:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:160:35:160:48 | req.query.path | User-provided value | +| normalizedPaths.js:184:19:184:22 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:184:19:184:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:187:21:187:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:187:21:187:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:189:21:189:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:189:21:189:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:192:21:192:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:192:21:192:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:194:21:194:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:194:21:194:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:199:21:199:24 | path | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:199:21:199:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:205:21:205:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:205:21:205:34 | normalizedPath | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:208:21:208:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:208:21:208:34 | normalizedPath | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:210:21:210:34 | normalizedPath | normalizedPaths.js:174:14:174:27 | req.query.path | normalizedPaths.js:210:21:210:34 | normalizedPath | $@ flows to here and is used in a path. | normalizedPaths.js:174:14:174:27 | req.query.path | User-provided value | +| normalizedPaths.js:222:21:222:24 | path | normalizedPaths.js:214:35:214:48 | req.query.path | normalizedPaths.js:222:21:222:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:214:35:214:48 | req.query.path | User-provided value | +| normalizedPaths.js:228:21:228:24 | path | normalizedPaths.js:226:35:226:48 | req.query.path | normalizedPaths.js:228:21:228:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:226:35:226:48 | req.query.path | User-provided value | +| normalizedPaths.js:238:19:238:22 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:238:19:238:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:236:33:236:46 | req.query.path | User-provided value | +| normalizedPaths.js:245:21:245:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:245:21:245:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:236:33:236:46 | req.query.path | User-provided value | +| normalizedPaths.js:250:21:250:24 | path | normalizedPaths.js:236:33:236:46 | req.query.path | normalizedPaths.js:250:21:250:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:236:33:236:46 | req.query.path | User-provided value | +| normalizedPaths.js:256:19:256:22 | path | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:256:19:256:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:262:21:262:24 | path | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:262:21:262:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:270:21:270:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:270:21:270:27 | newpath | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:278:21:278:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:278:21:278:27 | newpath | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:286:21:286:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:286:21:286:27 | newpath | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:296:21:296:27 | newpath | normalizedPaths.js:254:33:254:46 | req.query.path | normalizedPaths.js:296:21:296:27 | newpath | $@ flows to here and is used in a path. | normalizedPaths.js:254:33:254:46 | req.query.path | User-provided value | +| normalizedPaths.js:304:18:304:21 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:304:18:304:21 | path | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:309:19:309:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:309:19:309:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:313:19:313:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:313:19:313:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:316:19:316:22 | path | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:316:19:316:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:325:19:325:32 | normalizedPath | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:325:19:325:32 | normalizedPath | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:332:19:332:32 | normalizedPath | normalizedPaths.js:303:13:303:26 | req.query.path | normalizedPaths.js:332:19:332:32 | normalizedPath | $@ flows to here and is used in a path. | normalizedPaths.js:303:13:303:26 | req.query.path | User-provided value | +| normalizedPaths.js:341:18:341:21 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:341:18:341:21 | path | $@ flows to here and is used in a path. | normalizedPaths.js:339:32:339:45 | req.query.path | User-provided value | +| normalizedPaths.js:346:19:346:22 | path | normalizedPaths.js:339:32:339:45 | req.query.path | normalizedPaths.js:346:19:346:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:339:32:339:45 | req.query.path | User-provided value | +| normalizedPaths.js:356:19:356:22 | path | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:356:19:356:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:354:14:354:27 | req.query.path | User-provided value | +| normalizedPaths.js:363:21:363:31 | requestPath | normalizedPaths.js:354:14:354:27 | req.query.path | normalizedPaths.js:363:21:363:31 | requestPath | $@ flows to here and is used in a path. | normalizedPaths.js:354:14:354:27 | req.query.path | User-provided value | +| normalizedPaths.js:379:19:379:22 | path | normalizedPaths.js:377:14:377:27 | req.query.path | normalizedPaths.js:379:19:379:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:377:14:377:27 | req.query.path | User-provided value | +| normalizedPaths.js:381:19:381:29 | slash(path) | normalizedPaths.js:377:14:377:27 | req.query.path | normalizedPaths.js:381:19:381:29 | slash(path) | $@ flows to here and is used in a path. | normalizedPaths.js:377:14:377:27 | req.query.path | User-provided value | +| normalizedPaths.js:388:19:388:22 | path | normalizedPaths.js:385:35:385:45 | req.query.x | normalizedPaths.js:388:19:388:22 | path | $@ flows to here and is used in a path. | normalizedPaths.js:385:35:385:45 | req.query.x | User-provided value | +| normalizedPaths.js:399:21:399:24 | path | normalizedPaths.js:385:35:385:45 | req.query.x | normalizedPaths.js:399:21:399:24 | path | $@ flows to here and is used in a path. | normalizedPaths.js:385:35:385:45 | req.query.x | User-provided value | +| other-fs-libraries.js:11:19:11:22 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:11:19:11:22 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:12:27:12:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:12:27:12:30 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:13:24:13:27 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:13:24:13:27 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:14:27:14:30 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:14:27:14:30 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:16:34:16:37 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:16:34:16:37 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:17:35:17:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:17:35:17:38 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:19:56:19:59 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:19:56:19:59 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:24:35:24:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:24:35:24:38 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:9:24:9:30 | req.url | User-provided value | +| other-fs-libraries.js:40:35:40:38 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:40:35:40:38 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:38:24:38:30 | req.url | User-provided value | +| other-fs-libraries.js:41:50:41:53 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:41:50:41:53 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:38:24:38:30 | req.url | User-provided value | +| other-fs-libraries.js:42:53:42:56 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:42:53:42:56 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:38:24:38:30 | req.url | User-provided value | +| other-fs-libraries.js:51:19:51:22 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:51:19:51:22 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:52:24:52:27 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:52:24:52:27 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:54:36:54:39 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:54:36:54:39 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:55:36:55:39 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:55:36:55:39 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:57:46:57:49 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:57:46:57:49 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:59:39:59:42 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:59:39:59:42 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:62:43:62:46 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:62:43:62:46 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:63:51:63:54 | path | other-fs-libraries.js:49:24:49:30 | req.url | other-fs-libraries.js:63:51:63:54 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:49:24:49:30 | req.url | User-provided value | +| other-fs-libraries.js:70:19:70:22 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:70:19:70:22 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:68:24:68:30 | req.url | User-provided value | +| other-fs-libraries.js:71:10:71:13 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:71:10:71:13 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:68:24:68:30 | req.url | User-provided value | +| other-fs-libraries.js:72:15:72:18 | path | other-fs-libraries.js:68:24:68:30 | req.url | other-fs-libraries.js:72:15:72:18 | path | $@ flows to here and is used in a path. | other-fs-libraries.js:68:24:68:30 | req.url | User-provided value | +| prettier.js:7:28:7:28 | p | prettier.js:6:13:6:13 | p | prettier.js:7:28:7:28 | p | $@ flows to here and is used in a path. | prettier.js:6:13:6:13 | p | User-provided value | +| prettier.js:11:44:11:44 | p | prettier.js:6:13:6:13 | p | prettier.js:11:44:11:44 | p | $@ flows to here and is used in a path. | prettier.js:6:13:6:13 | p | User-provided value | +| pupeteer.js:9:28:9:34 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:9:28:9:34 | tainted | $@ flows to here and is used in a path. | pupeteer.js:5:28:5:53 | parseTo ... t).name | User-provided value | +| pupeteer.js:13:37:13:43 | tainted | pupeteer.js:5:28:5:53 | parseTo ... t).name | pupeteer.js:13:37:13:43 | tainted | $@ flows to here and is used in a path. | pupeteer.js:5:28:5:53 | parseTo ... t).name | User-provided value | +| tainted-access-paths.js:8:19:8:22 | path | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:8:19:8:22 | path | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:12:19:12:25 | obj.sub | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:12:19:12:25 | obj.sub | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:26:19:26:26 | obj.sub3 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:26:19:26:26 | obj.sub3 | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:29:21:29:28 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:29:21:29:28 | obj.sub4 | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:30:23:30:30 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:30:23:30:30 | obj.sub4 | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:31:23:31:30 | obj.sub4 | tainted-access-paths.js:6:24:6:30 | req.url | tainted-access-paths.js:31:23:31:30 | obj.sub4 | $@ flows to here and is used in a path. | tainted-access-paths.js:6:24:6:30 | req.url | User-provided value | +| tainted-access-paths.js:40:23:40:26 | path | tainted-access-paths.js:39:24:39:30 | req.url | tainted-access-paths.js:40:23:40:26 | path | $@ flows to here and is used in a path. | tainted-access-paths.js:39:24:39:30 | req.url | User-provided value | +| tainted-access-paths.js:49:10:49:13 | path | tainted-access-paths.js:48:24:48:30 | req.url | tainted-access-paths.js:49:10:49:13 | path | $@ flows to here and is used in a path. | tainted-access-paths.js:48:24:48:30 | req.url | User-provided value | +| tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | $@ flows to here and is used in a path. | tainted-require.js:7:19:7:37 | req.param("module") | User-provided value | +| tainted-require.js:12:29:12:47 | req.param("module") | tainted-require.js:12:29:12:47 | req.param("module") | tainted-require.js:12:29:12:47 | req.param("module") | $@ flows to here and is used in a path. | tainted-require.js:12:29:12:47 | req.param("module") | User-provided value | +| tainted-require.js:14:11:14:29 | req.param("module") | tainted-require.js:14:11:14:29 | req.param("module") | tainted-require.js:14:11:14:29 | req.param("module") | $@ flows to here and is used in a path. | tainted-require.js:14:11:14:29 | req.param("module") | User-provided value | +| tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | $@ flows to here and is used in a path. | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | User-provided value | +| tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | $@ flows to here and is used in a path. | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | User-provided value | +| tainted-sendFile.js:18:43:18:58 | req.param("dir") | tainted-sendFile.js:18:43:18:58 | req.param("dir") | tainted-sendFile.js:18:43:18:58 | req.param("dir") | $@ flows to here and is used in a path. | tainted-sendFile.js:18:43:18:58 | req.param("dir") | User-provided value | +| tainted-sendFile.js:24:16:24:49 | path.re ... rams.x) | tainted-sendFile.js:24:37:24:48 | req.params.x | tainted-sendFile.js:24:16:24:49 | path.re ... rams.x) | $@ flows to here and is used in a path. | tainted-sendFile.js:24:37:24:48 | req.params.x | User-provided value | +| tainted-sendFile.js:25:16:25:46 | path.jo ... rams.x) | tainted-sendFile.js:25:34:25:45 | req.params.x | tainted-sendFile.js:25:16:25:46 | path.jo ... rams.x) | $@ flows to here and is used in a path. | tainted-sendFile.js:25:34:25:45 | req.params.x | User-provided value | +| tainted-string-steps.js:8:18:8:34 | path.substring(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:8:18:8:34 | path.substring(4) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:9:18:9:37 | path.substring(0, i) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:9:18:9:37 | path.substring(0, i) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:10:18:10:31 | path.substr(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:10:18:10:31 | path.substr(4) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:11:18:11:30 | path.slice(4) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:11:18:11:30 | path.slice(4) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:13:18:13:37 | path.concat(unknown) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:13:18:13:37 | path.concat(unknown) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:14:18:14:37 | unknown.concat(path) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:14:18:14:37 | unknown.concat(path) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:15:18:15:46 | unknown ... , path) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:15:18:15:46 | unknown ... , path) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:17:18:17:28 | path.trim() | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:17:18:17:28 | path.trim() | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:18:18:18:35 | path.toLowerCase() | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:18:18:18:35 | path.toLowerCase() | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:22:18:22:35 | path.split('/')[i] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:22:18:22:35 | path.split('/')[i] | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:23:18:23:36 | path.split(/\\//)[i] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:23:18:23:36 | path.split(/\\//)[i] | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:24:18:24:35 | path.split("?")[0] | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:24:18:24:35 | path.split("?")[0] | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:26:18:26:45 | path.sp ... hatever | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:26:18:26:45 | path.sp ... hatever | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| tainted-string-steps.js:27:18:27:36 | path.split(unknown) | tainted-string-steps.js:6:24:6:30 | req.url | tainted-string-steps.js:27:18:27:36 | path.split(unknown) | $@ flows to here and is used in a path. | tainted-string-steps.js:6:24:6:30 | req.url | User-provided value | +| torrents.js:7:25:7:27 | loc | torrents.js:5:13:5:38 | parseTo ... t).name | torrents.js:7:25:7:27 | loc | $@ flows to here and is used in a path. | torrents.js:5:13:5:38 | parseTo ... t).name | User-provided value | +| typescript.ts:12:29:12:32 | path | typescript.ts:9:24:9:30 | req.url | typescript.ts:12:29:12:32 | path | $@ flows to here and is used in a path. | typescript.ts:9:24:9:30 | req.url | User-provided value | +| typescript.ts:21:39:21:43 | path3 | typescript.ts:9:24:9:30 | req.url | typescript.ts:21:39:21:43 | path3 | $@ flows to here and is used in a path. | typescript.ts:9:24:9:30 | req.url | User-provided value | +| typescript.ts:24:39:24:43 | path4 | typescript.ts:9:24:9:30 | req.url | typescript.ts:24:39:24:43 | path4 | $@ flows to here and is used in a path. | typescript.ts:9:24:9:30 | req.url | User-provided value | +| typescript.ts:32:29:32:33 | path6 | typescript.ts:9:24:9:30 | req.url | typescript.ts:32:29:32:33 | path6 | $@ flows to here and is used in a path. | typescript.ts:9:24:9:30 | req.url | User-provided value | +| views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | views.js:1:43:1:55 | req.params[0] | $@ flows to here and is used in a path. | views.js:1:43:1:55 | req.params[0] | User-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlip.expected b/javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlip.expected index 71a0dbc910a..253bca10b03 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlip.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/ZipSlip/ZipSlip.expected @@ -126,13 +126,13 @@ edges | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:7:9:7:29 | fileName | | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:7:9:7:29 | fileName | #select -| AdmZipBad.js:6:24:6:41 | zipEntry.entryName | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | item path | -| TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | TarSlipBad.js:6:36:6:46 | header.name | item path | -| TarSlipBad.js:9:17:9:31 | header.linkname | TarSlipBad.js:9:17:9:31 | header.linkname | TarSlipBad.js:9:17:9:31 | header.linkname | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | TarSlipBad.js:9:17:9:31 | header.linkname | item path | -| ZipSlipBad2.js:6:22:6:29 | fileName | ZipSlipBad2.js:5:37:5:46 | entry.path | ZipSlipBad2.js:6:22:6:29 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad2.js:5:37:5:46 | entry.path | item path | -| ZipSlipBad.js:8:37:8:44 | fileName | ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:7:22:7:31 | entry.path | item path | -| ZipSlipBad.js:16:30:16:37 | fileName | ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:16:30:16:37 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:15:22:15:31 | entry.path | item path | -| ZipSlipBad.js:23:28:23:35 | fileName | ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:23:28:23:35 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:22:22:22:31 | entry.path | item path | -| ZipSlipBad.js:31:26:31:29 | name | ZipSlipBad.js:30:14:30:17 | name | ZipSlipBad.js:31:26:31:29 | name | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:30:14:30:17 | name | item path | -| ZipSlipBad.js:35:26:35:29 | name | ZipSlipBad.js:34:16:34:19 | name | ZipSlipBad.js:35:26:35:29 | name | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBad.js:34:16:34:19 | name | item path | -| ZipSlipBadUnzipper.js:8:37:8:44 | fileName | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:8:37:8:44 | fileName | Unsanitized zip archive $@, which may contain '..', is used in a file system operation. | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | item path | +| AdmZipBad.js:6:24:6:41 | zipEntry.entryName | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | Unsanitized archive entry, which may contain '..', is used in a $@. | AdmZipBad.js:6:24:6:41 | zipEntry.entryName | file system operation | +| TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | TarSlipBad.js:6:36:6:46 | header.name | Unsanitized archive entry, which may contain '..', is used in a $@. | TarSlipBad.js:6:36:6:46 | header.name | file system operation | +| TarSlipBad.js:9:17:9:31 | header.linkname | TarSlipBad.js:9:17:9:31 | header.linkname | TarSlipBad.js:9:17:9:31 | header.linkname | Unsanitized archive entry, which may contain '..', is used in a $@. | TarSlipBad.js:9:17:9:31 | header.linkname | file system operation | +| ZipSlipBad2.js:5:37:5:46 | entry.path | ZipSlipBad2.js:5:37:5:46 | entry.path | ZipSlipBad2.js:6:22:6:29 | fileName | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad2.js:6:22:6:29 | fileName | file system operation | +| ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:7:22:7:31 | entry.path | ZipSlipBad.js:8:37:8:44 | fileName | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad.js:8:37:8:44 | fileName | file system operation | +| ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:15:22:15:31 | entry.path | ZipSlipBad.js:16:30:16:37 | fileName | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad.js:16:30:16:37 | fileName | file system operation | +| ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:22:22:22:31 | entry.path | ZipSlipBad.js:23:28:23:35 | fileName | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad.js:23:28:23:35 | fileName | file system operation | +| ZipSlipBad.js:30:14:30:17 | name | ZipSlipBad.js:30:14:30:17 | name | ZipSlipBad.js:31:26:31:29 | name | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad.js:31:26:31:29 | name | file system operation | +| ZipSlipBad.js:34:16:34:19 | name | ZipSlipBad.js:34:16:34:19 | name | ZipSlipBad.js:35:26:35:29 | name | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBad.js:35:26:35:29 | name | file system operation | +| ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:7:20:7:29 | entry.path | ZipSlipBadUnzipper.js:8:37:8:44 | fileName | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlipBadUnzipper.js:8:37:8:44 | fileName | file system operation | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 3e53d9b79b8..124ac8b62b4 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -134,6 +134,12 @@ nodes | form-parsers.js:59:10:59:33 | "touch ... ilename | | form-parsers.js:59:21:59:24 | part | | form-parsers.js:59:21:59:33 | part.filename | +| lib/subLib4/index.js:6:32:6:35 | name | +| lib/subLib4/index.js:7:18:7:21 | name | +| lib/subLib4/subsub.js:3:28:3:31 | name | +| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | +| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | +| lib/subLib4/subsub.js:4:22:4:25 | name | | lib/subLib/index.js:7:32:7:35 | name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -232,6 +238,8 @@ edges | child_process-test.js:73:25:73:31 | req.url | child_process-test.js:73:15:73:38 | url.par ... , true) | | child_process-test.js:73:25:73:31 | req.url | child_process-test.js:73:15:73:38 | url.par ... , true) | | child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName | +| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/index.js:6:32:6:35 | name | +| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/index.js:6:32:6:35 | name | | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:7:32:7:35 | name | | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:7:32:7:35 | name | | child_process-test.js:94:21:94:30 | ctx.params | child_process-test.js:94:21:94:35 | ctx.params.host | @@ -306,6 +314,11 @@ edges | form-parsers.js:59:21:59:24 | part | form-parsers.js:59:21:59:33 | part.filename | | form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename | | form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename | +| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name | +| lib/subLib4/index.js:7:18:7:21 | name | lib/subLib4/subsub.js:3:28:3:31 | name | +| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name | +| lib/subLib4/subsub.js:4:22:4:25 | name | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | +| lib/subLib4/subsub.js:4:22:4:25 | name | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | | lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | @@ -355,53 +368,54 @@ edges | third-party-command-injection.js:5:20:5:26 | command | third-party-command-injection.js:6:21:6:27 | command | | third-party-command-injection.js:5:20:5:26 | command | third-party-command-injection.js:6:21:6:27 | command | #select -| child_process-test.js:17:13:17:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:17:13:17:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:18:17:18:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:18:17:18:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:19:17:19:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:19:17:19:19 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:20:21:20:23 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:20:21:20:23 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:21:14:21:16 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:21:14:21:16 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:22:18:22:20 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:22:18:22:20 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:23:13:23:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:23:13:23:15 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:39:5:39:31 | cp.spaw ... cmd ]) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:39:26:39:28 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:44:5:44:34 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:54:5:54:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:53:15:53:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:56:5:56:59 | cp.spaw ... cmd])) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:56:25:56:58 | ['/C', ... , cmd]) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:56:5:56:59 | cp.spaw ... cmd])) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:56:54:56:56 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:57:5:57:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:6:15:6:49 | url.par ... ry.path | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:57:5:57:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:57:25:57:49 | ['/C', ... at(cmd) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:62:5:62:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:53:15:53:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:67:3:67:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:48:15:48:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | -| child_process-test.js:75:29:75:31 | cmd | child_process-test.js:73:25:73:31 | req.url | child_process-test.js:75:29:75:31 | cmd | This command depends on $@. | child_process-test.js:73:25:73:31 | req.url | a user-provided value | -| child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName | This command depends on $@. | child_process-test.js:83:19:83:36 | req.query.fileName | a user-provided value | -| child_process-test.js:94:11:94:35 | "ping " ... ms.host | child_process-test.js:94:21:94:30 | ctx.params | child_process-test.js:94:11:94:35 | "ping " ... ms.host | This command depends on $@. | child_process-test.js:94:21:94:30 | ctx.params | a user-provided value | -| exec-sh2.js:10:12:10:57 | cp.spaw ... ptions) | exec-sh2.js:14:25:14:31 | req.url | exec-sh2.js:10:40:10:46 | command | This command depends on $@. | exec-sh2.js:14:25:14:31 | req.url | a user-provided value | -| exec-sh.js:15:12:15:61 | cp.spaw ... ptions) | exec-sh.js:19:25:19:31 | req.url | exec-sh.js:15:44:15:50 | command | This command depends on $@. | exec-sh.js:19:25:19:31 | req.url | a user-provided value | -| execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | This command depends on $@. | execSeries.js:18:34:18:40 | req.url | a user-provided value | -| form-parsers.js:9:8:9:39 | "touch ... nalname | form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:8:9:39 | "touch ... nalname | This command depends on $@. | form-parsers.js:9:19:9:26 | req.file | a user-provided value | -| form-parsers.js:14:10:14:37 | "touch ... nalname | form-parsers.js:13:3:13:11 | req.files | form-parsers.js:14:10:14:37 | "touch ... nalname | This command depends on $@. | form-parsers.js:13:3:13:11 | req.files | a user-provided value | -| form-parsers.js:25:10:25:28 | "touch " + filename | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | This command depends on $@. | form-parsers.js:24:48:24:55 | filename | a user-provided value | -| form-parsers.js:36:10:36:31 | "touch ... ds.name | form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:10:36:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:35:25:35:30 | fields | a user-provided value | -| form-parsers.js:41:10:41:31 | "touch ... ds.name | form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:10:41:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:40:26:40:31 | fields | a user-provided value | -| form-parsers.js:53:10:53:31 | "touch ... ds.name | form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:10:53:31 | "touch ... ds.name | This command depends on $@. | form-parsers.js:52:34:52:39 | fields | a user-provided value | -| form-parsers.js:59:10:59:33 | "touch ... ilename | form-parsers.js:58:30:58:33 | part | form-parsers.js:59:10:59:33 | "touch ... ilename | This command depends on $@. | form-parsers.js:58:30:58:33 | part | a user-provided value | -| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | This command depends on $@. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | -| other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:9:32:9:34 | cmd | other.js:5:25:5:31 | req.url | other.js:9:32:9:34 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:10:29:10:31 | cmd | other.js:5:25:5:31 | req.url | other.js:10:29:10:31 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:11:29:11:31 | cmd | other.js:5:25:5:31 | req.url | other.js:11:29:11:31 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:12:27:12:29 | cmd | other.js:5:25:5:31 | req.url | other.js:12:27:12:29 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:14:28:14:30 | cmd | other.js:5:25:5:31 | req.url | other.js:14:28:14:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:15:34:15:36 | cmd | other.js:5:25:5:31 | req.url | other.js:15:34:15:36 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:16:21:16:23 | cmd | other.js:5:25:5:31 | req.url | other.js:16:21:16:23 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:17:27:17:29 | cmd | other.js:5:25:5:31 | req.url | other.js:17:27:17:29 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:18:22:18:24 | cmd | other.js:5:25:5:31 | req.url | other.js:18:22:18:24 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:19:36:19:38 | cmd | other.js:5:25:5:31 | req.url | other.js:19:36:19:38 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:22:21:22:23 | cmd | other.js:5:25:5:31 | req.url | other.js:22:21:22:23 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:23:28:23:30 | cmd | other.js:5:25:5:31 | req.url | other.js:23:28:23:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:26:34:26:36 | cmd | other.js:5:25:5:31 | req.url | other.js:26:34:26:36 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:28:27:28:29 | cmd | other.js:5:25:5:31 | req.url | other.js:28:27:28:29 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:30:33:30:35 | cmd | other.js:5:25:5:31 | req.url | other.js:30:33:30:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| other.js:34:44:34:46 | cmd | other.js:5:25:5:31 | req.url | other.js:34:44:34:46 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | -| third-party-command-injection.js:6:21:6:27 | command | third-party-command-injection.js:5:20:5:26 | command | third-party-command-injection.js:6:21:6:27 | command | This command depends on $@. | third-party-command-injection.js:5:20:5:26 | command | a server-provided value | +| child_process-test.js:17:13:17:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:17:13:17:15 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:18:17:18:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:18:17:18:19 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:19:17:19:19 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:19:17:19:19 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:20:21:20:23 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:20:21:20:23 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:21:14:21:16 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:21:14:21:16 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:22:18:22:20 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:22:18:22:20 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:23:13:23:15 | cmd | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:23:13:23:15 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:25:13:25:31 | "foo" + cmd + "bar" | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:39:5:39:31 | cp.spaw ... cmd ]) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:39:26:39:28 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:44:5:44:34 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:54:5:54:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:53:15:53:17 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:56:5:56:59 | cp.spaw ... cmd])) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:56:25:56:58 | ['/C', ... , cmd]) | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:56:5:56:59 | cp.spaw ... cmd])) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:56:54:56:56 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:57:5:57:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:6:15:6:49 | url.par ... ry.path | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:57:5:57:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:57:25:57:49 | ['/C', ... at(cmd) | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:62:5:62:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:53:15:53:17 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:67:3:67:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:48:15:48:17 | cmd | $@ flows to here and is used in a command. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:75:29:75:31 | cmd | child_process-test.js:73:25:73:31 | req.url | child_process-test.js:75:29:75:31 | cmd | $@ flows to here and is used in a command. | child_process-test.js:73:25:73:31 | req.url | a user-provided value | +| child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName | $@ flows to here and is used in a command. | child_process-test.js:83:19:83:36 | req.query.fileName | a user-provided value | +| child_process-test.js:94:11:94:35 | "ping " ... ms.host | child_process-test.js:94:21:94:30 | ctx.params | child_process-test.js:94:11:94:35 | "ping " ... ms.host | $@ flows to here and is used in a command. | child_process-test.js:94:21:94:30 | ctx.params | a user-provided value | +| exec-sh2.js:10:12:10:57 | cp.spaw ... ptions) | exec-sh2.js:14:25:14:31 | req.url | exec-sh2.js:10:40:10:46 | command | $@ flows to here and is used in a command. | exec-sh2.js:14:25:14:31 | req.url | a user-provided value | +| exec-sh.js:15:12:15:61 | cp.spaw ... ptions) | exec-sh.js:19:25:19:31 | req.url | exec-sh.js:15:44:15:50 | command | $@ flows to here and is used in a command. | exec-sh.js:19:25:19:31 | req.url | a user-provided value | +| execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | $@ flows to here and is used in a command. | execSeries.js:18:34:18:40 | req.url | a user-provided value | +| form-parsers.js:9:8:9:39 | "touch ... nalname | form-parsers.js:9:19:9:26 | req.file | form-parsers.js:9:8:9:39 | "touch ... nalname | $@ flows to here and is used in a command. | form-parsers.js:9:19:9:26 | req.file | a user-provided value | +| form-parsers.js:14:10:14:37 | "touch ... nalname | form-parsers.js:13:3:13:11 | req.files | form-parsers.js:14:10:14:37 | "touch ... nalname | $@ flows to here and is used in a command. | form-parsers.js:13:3:13:11 | req.files | a user-provided value | +| form-parsers.js:25:10:25:28 | "touch " + filename | form-parsers.js:24:48:24:55 | filename | form-parsers.js:25:10:25:28 | "touch " + filename | $@ flows to here and is used in a command. | form-parsers.js:24:48:24:55 | filename | a user-provided value | +| form-parsers.js:36:10:36:31 | "touch ... ds.name | form-parsers.js:35:25:35:30 | fields | form-parsers.js:36:10:36:31 | "touch ... ds.name | $@ flows to here and is used in a command. | form-parsers.js:35:25:35:30 | fields | a user-provided value | +| form-parsers.js:41:10:41:31 | "touch ... ds.name | form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:10:41:31 | "touch ... ds.name | $@ flows to here and is used in a command. | form-parsers.js:40:26:40:31 | fields | a user-provided value | +| form-parsers.js:53:10:53:31 | "touch ... ds.name | form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:10:53:31 | "touch ... ds.name | $@ flows to here and is used in a command. | form-parsers.js:52:34:52:39 | fields | a user-provided value | +| form-parsers.js:59:10:59:33 | "touch ... ilename | form-parsers.js:58:30:58:33 | part | form-parsers.js:59:10:59:33 | "touch ... ilename | $@ flows to here and is used in a command. | form-parsers.js:58:30:58:33 | part | a user-provided value | +| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | $@ flows to here and is used in a command. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | +| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | $@ flows to here and is used in a command. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value | +| other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:9:32:9:34 | cmd | other.js:5:25:5:31 | req.url | other.js:9:32:9:34 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:10:29:10:31 | cmd | other.js:5:25:5:31 | req.url | other.js:10:29:10:31 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:11:29:11:31 | cmd | other.js:5:25:5:31 | req.url | other.js:11:29:11:31 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:12:27:12:29 | cmd | other.js:5:25:5:31 | req.url | other.js:12:27:12:29 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:14:28:14:30 | cmd | other.js:5:25:5:31 | req.url | other.js:14:28:14:30 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:15:34:15:36 | cmd | other.js:5:25:5:31 | req.url | other.js:15:34:15:36 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:16:21:16:23 | cmd | other.js:5:25:5:31 | req.url | other.js:16:21:16:23 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:17:27:17:29 | cmd | other.js:5:25:5:31 | req.url | other.js:17:27:17:29 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:18:22:18:24 | cmd | other.js:5:25:5:31 | req.url | other.js:18:22:18:24 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:19:36:19:38 | cmd | other.js:5:25:5:31 | req.url | other.js:19:36:19:38 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:22:21:22:23 | cmd | other.js:5:25:5:31 | req.url | other.js:22:21:22:23 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:23:28:23:30 | cmd | other.js:5:25:5:31 | req.url | other.js:23:28:23:30 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:26:34:26:36 | cmd | other.js:5:25:5:31 | req.url | other.js:26:34:26:36 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:28:27:28:29 | cmd | other.js:5:25:5:31 | req.url | other.js:28:27:28:29 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:30:33:30:35 | cmd | other.js:5:25:5:31 | req.url | other.js:30:33:30:35 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| other.js:34:44:34:46 | cmd | other.js:5:25:5:31 | req.url | other.js:34:44:34:46 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value | +| third-party-command-injection.js:6:21:6:27 | command | third-party-command-injection.js:5:20:5:26 | command | third-party-command-injection.js:6:21:6:27 | command | $@ flows to here and is used in a command. | third-party-command-injection.js:5:20:5:26 | command | a server-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected index 035eff50202..1206af38368 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/UnsafeShellCommandConstruction.expected @@ -284,6 +284,12 @@ nodes | lib/subLib3/my-file.ts:3:28:3:31 | name | | lib/subLib3/my-file.ts:4:22:4:25 | name | | lib/subLib3/my-file.ts:4:22:4:25 | name | +| lib/subLib4/index.js:6:32:6:35 | name | +| lib/subLib4/index.js:6:32:6:35 | name | +| lib/subLib4/index.js:7:18:7:21 | name | +| lib/subLib4/subsub.js:3:28:3:31 | name | +| lib/subLib4/subsub.js:4:22:4:25 | name | +| lib/subLib4/subsub.js:4:22:4:25 | name | | lib/subLib/amdSub.js:3:28:3:31 | name | | lib/subLib/amdSub.js:3:28:3:31 | name | | lib/subLib/amdSub.js:4:22:4:25 | name | @@ -640,6 +646,11 @@ edges | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | +| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name | +| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name | +| lib/subLib4/index.js:7:18:7:21 | name | lib/subLib4/subsub.js:3:28:3:31 | name | +| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name | +| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name | | lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name | | lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name | | lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name | @@ -735,6 +746,7 @@ edges | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | $@ based on $@ is later used in $@. | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | String concatenation | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command | | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4:26 | cp.exec ... + name) | shell command | +| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/subsub.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib4/index.js:6:32:6:35 | name | library input | lib/subLib4/subsub.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib/amdSub.js:4:10:4:25 | "rm -rf " + name | lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib/amdSub.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib/amdSub.js:3:28:3:31 | name | library input | lib/subLib/amdSub.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib/index.js:4:10:4:25 | "rm -rf " + name | lib/subLib/index.js:3:28:3:31 | name | lib/subLib/index.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib/index.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib/index.js:3:28:3:31 | name | library input | lib/subLib/index.js:4:2:4:26 | cp.exec ... + name) | shell command | | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | $@ based on $@ is later used in $@. | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/subLib/index.js:7:32:7:35 | name | library input | lib/subLib/index.js:8:2:8:26 | cp.exec ... + name) | shell command | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/index.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/index.js new file mode 100644 index 00000000000..820349c5c62 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/index.js @@ -0,0 +1,8 @@ +const dispatch = { + GET: require("./bla"), + POST: require("./subsub"), +}; + +module.exports.foo = function (name, type) { + dispatch[type](name); +}; diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/package.json b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/package.json new file mode 100644 index 00000000000..87942f96b4d --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/package.json @@ -0,0 +1,5 @@ +{ + "name": "my-sub-lib", + "version": "0.0.7", + "main": "./index.js" +} diff --git a/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/subsub.js b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/subsub.js new file mode 100644 index 00000000000..952288a82ce --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-078/lib/subLib4/subsub.js @@ -0,0 +1,5 @@ +const cp = require("child_process") + +module.exports = function (name) { + cp.exec("rm -rf " + name); // NOT OK - functions exported as part of a submodule are also flagged. +}; diff --git a/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected b/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected index 0ea3425b00e..bfb9a79897b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected +++ b/javascript/ql/test/query-tests/Security/CWE-134/TaintedFormatString.expected @@ -81,23 +81,23 @@ edges | tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | | tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | #select -| tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:5:15:5:30 | req.query.format | User-provided value | -| tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:6:26:6:41 | req.query.format | User-provided value | -| tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | $@ flows here and is used in a format string. | tst.js:7:15:7:30 | req.query.format | User-provided value | -| tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:8:17:8:32 | req.query.format | User-provided value | -| tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:9:16:9:31 | req.query.format | User-provided value | -| tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | $@ flows here and is used in a format string. | tst.js:10:12:10:27 | req.query.format | User-provided value | -| tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | $@ flows here and is used in a format string. | tst.js:11:32:11:47 | req.query.format | User-provided value | -| tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | $@ flows here and is used in a format string. | tst.js:12:21:12:36 | req.query.format | User-provided value | -| tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | $@ flows here and is used in a format string. | tst.js:13:35:13:50 | req.query.format | User-provided value | -| tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | $@ flows here and is used in a format string. | tst.js:14:29:14:44 | req.query.format | User-provided value | -| tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:15:30:15:45 | req.query.format | User-provided value | -| tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | $@ flows here and is used in a format string. | tst.js:16:26:16:41 | req.query.format | User-provided value | -| tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | $@ flows here and is used in a format string. | tst.js:17:30:17:45 | req.query.format | User-provided value | -| tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | $@ flows here and is used in a format string. | tst.js:18:38:18:53 | req.query.format | User-provided value | -| tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:20:17:20:32 | req.query.format | User-provided value | -| tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | $@ flows here and is used in a format string. | tst.js:21:16:21:31 | req.query.format | User-provided value | -| tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | $@ flows here and is used in a format string. | tst.js:22:17:22:32 | req.query.format | User-provided value | -| tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | $@ flows here and is used in a format string. | tst.js:24:25:24:40 | req.query.format | User-provided value | -| tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | $@ flows here and is used in a format string. | tst.js:25:33:25:48 | req.query.format | User-provided value | -| tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | $@ flows here and is used in a format string. | tst.js:26:34:26:49 | req.query.format | User-provided value | +| tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | tst.js:5:15:5:30 | req.query.format | $@ flows to here and is used in a format string. | tst.js:5:15:5:30 | req.query.format | User-provided value | +| tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | tst.js:6:26:6:41 | req.query.format | $@ flows to here and is used in a format string. | tst.js:6:26:6:41 | req.query.format | User-provided value | +| tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | tst.js:7:15:7:30 | req.query.format | $@ flows to here and is used in a format string. | tst.js:7:15:7:30 | req.query.format | User-provided value | +| tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | tst.js:8:17:8:32 | req.query.format | $@ flows to here and is used in a format string. | tst.js:8:17:8:32 | req.query.format | User-provided value | +| tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | tst.js:9:16:9:31 | req.query.format | $@ flows to here and is used in a format string. | tst.js:9:16:9:31 | req.query.format | User-provided value | +| tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | tst.js:10:12:10:27 | req.query.format | $@ flows to here and is used in a format string. | tst.js:10:12:10:27 | req.query.format | User-provided value | +| tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | tst.js:11:32:11:47 | req.query.format | $@ flows to here and is used in a format string. | tst.js:11:32:11:47 | req.query.format | User-provided value | +| tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | tst.js:12:21:12:36 | req.query.format | $@ flows to here and is used in a format string. | tst.js:12:21:12:36 | req.query.format | User-provided value | +| tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | tst.js:13:35:13:50 | req.query.format | $@ flows to here and is used in a format string. | tst.js:13:35:13:50 | req.query.format | User-provided value | +| tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | tst.js:14:29:14:44 | req.query.format | $@ flows to here and is used in a format string. | tst.js:14:29:14:44 | req.query.format | User-provided value | +| tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | tst.js:15:30:15:45 | req.query.format | $@ flows to here and is used in a format string. | tst.js:15:30:15:45 | req.query.format | User-provided value | +| tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | tst.js:16:26:16:41 | req.query.format | $@ flows to here and is used in a format string. | tst.js:16:26:16:41 | req.query.format | User-provided value | +| tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | tst.js:17:30:17:45 | req.query.format | $@ flows to here and is used in a format string. | tst.js:17:30:17:45 | req.query.format | User-provided value | +| tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | tst.js:18:38:18:53 | req.query.format | $@ flows to here and is used in a format string. | tst.js:18:38:18:53 | req.query.format | User-provided value | +| tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | tst.js:20:17:20:32 | req.query.format | $@ flows to here and is used in a format string. | tst.js:20:17:20:32 | req.query.format | User-provided value | +| tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | tst.js:21:16:21:31 | req.query.format | $@ flows to here and is used in a format string. | tst.js:21:16:21:31 | req.query.format | User-provided value | +| tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | tst.js:22:17:22:32 | req.query.format | $@ flows to here and is used in a format string. | tst.js:22:17:22:32 | req.query.format | User-provided value | +| tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | tst.js:24:25:24:40 | req.query.format | $@ flows to here and is used in a format string. | tst.js:24:25:24:40 | req.query.format | User-provided value | +| tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | tst.js:25:33:25:48 | req.query.format | $@ flows to here and is used in a format string. | tst.js:25:33:25:48 | req.query.format | User-provided value | +| tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | tst.js:26:34:26:49 | req.query.format | $@ flows to here and is used in a format string. | tst.js:26:34:26:49 | req.query.format | User-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected index a79b3100a80..2e8cf4ee415 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-178/CaseSensitiveMiddlewarePath.expected @@ -1,3 +1,7 @@ -| tst.js:8:9:8:19 | /\\/foo\\/.*/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO/' will bypass the middleware. | tst.js:8:9:8:19 | /\\/foo\\/.*/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | -| tst.js:14:5:14:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO' will bypass the middleware. | tst.js:14:5:14:28 | new Reg ... (.*)?') | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | -| tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO/' will bypass the middleware. | tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | +| tst.js:8:9:8:19 | /\\/foo\\/.*/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:8:9:8:19 | /\\/foo\\/.*/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | +| tst.js:14:5:14:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:14:5:14:28 | new Reg ... (.*)?') | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | +| tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/FOO/1' will bypass the middleware. | tst.js:41:9:41:25 | /\\/foo\\/([0-9]+)/ | pattern | tst.js:60:1:61:2 | app.get ... ware\\n}) | here | +| tst.js:64:5:64:28 | new Reg ... (.*)?') | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/BAR/1' will bypass the middleware. | tst.js:64:5:64:28 | new Reg ... (.*)?') | pattern | tst.js:73:1:74:2 | app.get ... ware\\n}) | here | +| tst.js:76:9:76:20 | /\\/baz\\/bla/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/BAZ/BLA' will bypass the middleware. | tst.js:76:9:76:20 | /\\/baz\\/bla/ | pattern | tst.js:77:1:79:2 | app.get ... });\\n}) | here | +| tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/BAZ3/A' will bypass the middleware. | tst.js:86:9:86:30 | /\\/[Bb] ... 3\\/[a]/ | pattern | tst.js:87:1:89:2 | app.get ... });\\n}) | here | +| tst.js:91:9:91:40 | /\\/summ ... ntGame/ | This route uses a case-sensitive path $@, but is guarding a case-insensitive path $@. A path such as '/CURRENTGAME' will bypass the middleware. | tst.js:91:9:91:40 | /\\/summ ... ntGame/ | pattern | tst.js:93:1:95:2 | app.get ... O");\\n}) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-178/tst.js b/javascript/ql/test/query-tests/Security/CWE-178/tst.js index 1acb57b16ea..5fcc3cc94a0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-178/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-178/tst.js @@ -59,3 +59,37 @@ app.use(/\/foo\/([0-9]+)/i, (req, res) => { // OK - not middleware (also case in app.get('/foo/:param', (req, res) => { // OK - not a middleware }); + +app.get( + new RegExp('^/bar(.*)?'), // NOT OK - case sensitive + unknown(), + function(req, res, next) { + if (req.params.blah) { + next(); + } + } +); + +app.get('/bar/*', (req, res) => { // OK - not a middleware +}); + +app.use(/\/baz\/bla/, unknown()); // NOT OK - case sensitive +app.get('/baz/bla', (req, resp) => { + resp.send({ test: 123 }); +}); + +app.use(/\/[Bb][Aa][Zz]2\/[aA]/, unknown()); // OK - not case sensitive +app.get('/baz2/a', (req, resp) => { + resp.send({ test: 123 }); +}); + +app.use(/\/[Bb][Aa][Zz]3\/[a]/, unknown()); // NOT OK - case sensitive +app.get('/baz3/a', (req, resp) => { + resp.send({ test: 123 }); +}); + +app.use(/\/summonerByName|\/currentGame/,apiLimit1, apiLimit2); + +app.get('/currentGame', function (req, res) { + res.send("FOO"); +}); diff --git a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected index 42da210c266..392fc5805ec 100644 --- a/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected +++ b/javascript/ql/test/query-tests/Security/CWE-338/InsecureRandomness.expected @@ -159,25 +159,25 @@ edges | tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | | tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | #select -| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:2:20:2:32 | Math.random() | random value | -| tst.js:6:20:6:43 | "prefix ... andom() | tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure $@ in a security context. | tst.js:6:31:6:43 | Math.random() | random value | -| tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:10:20:10:32 | Math.random() | random value | -| tst.js:20:20:20:36 | "prefix" + suffix | tst.js:19:18:19:30 | Math.random() | tst.js:20:20:20:36 | "prefix" + suffix | Cryptographically insecure $@ in a security context. | tst.js:19:18:19:30 | Math.random() | random value | -| tst.js:29:20:29:21 | pw | tst.js:28:14:28:26 | Math.random() | tst.js:29:20:29:21 | pw | Cryptographically insecure $@ in a security context. | tst.js:28:14:28:26 | Math.random() | random value | -| tst.js:41:20:41:33 | !Math.random() | tst.js:41:21:41:33 | Math.random() | tst.js:41:20:41:33 | !Math.random() | Cryptographically insecure $@ in a security context. | tst.js:41:21:41:33 | Math.random() | random value | -| tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:45:18:45:30 | Math.random() | random value | -| tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:50:16:50:28 | Math.random() | random value | -| tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:55:17:55:29 | Math.random() | random value | -| tst.js:61:17:61:34 | '' + Math.random() | tst.js:61:22:61:34 | Math.random() | tst.js:61:17:61:34 | '' + Math.random() | Cryptographically insecure $@ in a security context. | tst.js:61:22:61:34 | Math.random() | random value | -| tst.js:66:18:66:42 | Math.fl ... ndom()) | tst.js:66:29:66:41 | Math.random() | tst.js:66:18:66:42 | Math.fl ... ndom()) | Cryptographically insecure $@ in a security context. | tst.js:66:29:66:41 | Math.random() | random value | -| tst.js:73:23:73:28 | concat | tst.js:71:27:71:39 | Math.random() | tst.js:73:23:73:28 | concat | Cryptographically insecure $@ in a security context. | tst.js:71:27:71:39 | Math.random() | random value | -| tst.js:77:16:77:21 | secret | tst.js:80:7:80:19 | Math.random() | tst.js:77:16:77:21 | secret | Cryptographically insecure $@ in a security context. | tst.js:80:7:80:19 | Math.random() | random value | -| tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:84:19:84:31 | Math.random() | random value | -| tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:90:32:90:44 | Math.random() | random value | -| tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:95:33:95:45 | Math.random() | random value | -| tst.js:115:16:115:56 | Math.fl ... 00_000) | tst.js:115:27:115:39 | Math.random() | tst.js:115:16:115:56 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:115:27:115:39 | Math.random() | random value | -| tst.js:116:22:116:62 | Math.fl ... 00_000) | tst.js:116:33:116:45 | Math.random() | tst.js:116:22:116:62 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:116:33:116:45 | Math.random() | random value | -| tst.js:117:15:117:55 | Math.fl ... 00_000) | tst.js:117:26:117:38 | Math.random() | tst.js:117:15:117:55 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:117:26:117:38 | Math.random() | random value | -| tst.js:118:23:118:63 | Math.fl ... 00_000) | tst.js:118:34:118:46 | Math.random() | tst.js:118:23:118:63 | Math.fl ... 00_000) | Cryptographically insecure $@ in a security context. | tst.js:118:34:118:46 | Math.random() | random value | -| tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:120:16:120:28 | Math.random() | random value | -| tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | Cryptographically insecure $@ in a security context. | tst.js:121:18:121:30 | Math.random() | random value | +| tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | tst.js:2:20:2:32 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:2:20:2:32 | Math.random() | Math.random() | +| tst.js:6:20:6:43 | "prefix ... andom() | tst.js:6:31:6:43 | Math.random() | tst.js:6:20:6:43 | "prefix ... andom() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:6:31:6:43 | Math.random() | Math.random() | +| tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | tst.js:10:20:10:32 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:10:20:10:32 | Math.random() | Math.random() | +| tst.js:20:20:20:36 | "prefix" + suffix | tst.js:19:18:19:30 | Math.random() | tst.js:20:20:20:36 | "prefix" + suffix | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:19:18:19:30 | Math.random() | Math.random() | +| tst.js:29:20:29:21 | pw | tst.js:28:14:28:26 | Math.random() | tst.js:29:20:29:21 | pw | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:28:14:28:26 | Math.random() | Math.random() | +| tst.js:41:20:41:33 | !Math.random() | tst.js:41:21:41:33 | Math.random() | tst.js:41:20:41:33 | !Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:41:21:41:33 | Math.random() | Math.random() | +| tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | tst.js:45:18:45:30 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:45:18:45:30 | Math.random() | Math.random() | +| tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | tst.js:50:16:50:28 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:50:16:50:28 | Math.random() | Math.random() | +| tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | tst.js:55:17:55:29 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:55:17:55:29 | Math.random() | Math.random() | +| tst.js:61:17:61:34 | '' + Math.random() | tst.js:61:22:61:34 | Math.random() | tst.js:61:17:61:34 | '' + Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:61:22:61:34 | Math.random() | Math.random() | +| tst.js:66:18:66:42 | Math.fl ... ndom()) | tst.js:66:29:66:41 | Math.random() | tst.js:66:18:66:42 | Math.fl ... ndom()) | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:66:29:66:41 | Math.random() | Math.random() | +| tst.js:73:23:73:28 | concat | tst.js:71:27:71:39 | Math.random() | tst.js:73:23:73:28 | concat | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:71:27:71:39 | Math.random() | Math.random() | +| tst.js:77:16:77:21 | secret | tst.js:80:7:80:19 | Math.random() | tst.js:77:16:77:21 | secret | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:80:7:80:19 | Math.random() | Math.random() | +| tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | tst.js:84:19:84:31 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:84:19:84:31 | Math.random() | Math.random() | +| tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | tst.js:90:32:90:44 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:90:32:90:44 | Math.random() | Math.random() | +| tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | tst.js:95:33:95:45 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:95:33:95:45 | Math.random() | Math.random() | +| tst.js:115:16:115:56 | Math.fl ... 00_000) | tst.js:115:27:115:39 | Math.random() | tst.js:115:16:115:56 | Math.fl ... 00_000) | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:115:27:115:39 | Math.random() | Math.random() | +| tst.js:116:22:116:62 | Math.fl ... 00_000) | tst.js:116:33:116:45 | Math.random() | tst.js:116:22:116:62 | Math.fl ... 00_000) | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:116:33:116:45 | Math.random() | Math.random() | +| tst.js:117:15:117:55 | Math.fl ... 00_000) | tst.js:117:26:117:38 | Math.random() | tst.js:117:15:117:55 | Math.fl ... 00_000) | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:117:26:117:38 | Math.random() | Math.random() | +| tst.js:118:23:118:63 | Math.fl ... 00_000) | tst.js:118:34:118:46 | Math.random() | tst.js:118:23:118:63 | Math.fl ... 00_000) | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:118:34:118:46 | Math.random() | Math.random() | +| tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | tst.js:120:16:120:28 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:120:16:120:28 | Math.random() | Math.random() | +| tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | tst.js:121:18:121:30 | Math.random() | Cryptographically insecure random number is generated at $@ and used here in a security context. | tst.js:121:18:121:30 | Math.random() | Math.random() | diff --git a/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected b/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected index 1e747774b61..1c4447d605f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-643/XpathInjection.expected @@ -46,10 +46,10 @@ edges | tst.js:6:17:6:37 | req.par ... rName") | tst.js:6:7:6:37 | tainted | | tst.js:6:17:6:37 | req.par ... rName") | tst.js:6:7:6:37 | tainted | #select -| XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | $@ flows here and is used in an XPath expression. | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | User-provided value | -| tst2.js:2:27:2:31 | query | tst2.js:1:13:1:34 | documen ... on.hash | tst2.js:2:27:2:31 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:34 | documen ... on.hash | User-provided value | -| tst2.js:3:19:3:23 | query | tst2.js:1:13:1:34 | documen ... on.hash | tst2.js:3:19:3:23 | query | $@ flows here and is used in an XPath expression. | tst2.js:1:13:1:34 | documen ... on.hash | User-provided value | -| tst.js:7:15:7:21 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:7:15:7:21 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | -| tst.js:8:16:8:22 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:8:16:8:22 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | -| tst.js:9:17:9:23 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:9:17:9:23 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | -| tst.js:11:8:11:14 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:11:8:11:14 | tainted | $@ flows here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | +| XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | XpathInjectionBad.js:9:34:9:96 | "//user ... text()" | $@ flows to here and is used in an XPath expression. | XpathInjectionBad.js:6:18:6:38 | req.par ... rName") | User-provided value | +| tst2.js:2:27:2:31 | query | tst2.js:1:13:1:34 | documen ... on.hash | tst2.js:2:27:2:31 | query | $@ flows to here and is used in an XPath expression. | tst2.js:1:13:1:34 | documen ... on.hash | User-provided value | +| tst2.js:3:19:3:23 | query | tst2.js:1:13:1:34 | documen ... on.hash | tst2.js:3:19:3:23 | query | $@ flows to here and is used in an XPath expression. | tst2.js:1:13:1:34 | documen ... on.hash | User-provided value | +| tst.js:7:15:7:21 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:7:15:7:21 | tainted | $@ flows to here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | +| tst.js:8:16:8:22 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:8:16:8:22 | tainted | $@ flows to here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | +| tst.js:9:17:9:23 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:9:17:9:23 | tainted | $@ flows to here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | +| tst.js:11:8:11:14 | tainted | tst.js:6:17:6:37 | req.par ... rName") | tst.js:11:8:11:14 | tainted | $@ flows to here and is used in an XPath expression. | tst.js:6:17:6:37 | req.par ... rName") | User-provided value | diff --git a/javascript/ql/test/query-tests/Statements/NestedLoopsSameVariable/NestedLoopsSameVariable.expected b/javascript/ql/test/query-tests/Statements/NestedLoopsSameVariable/NestedLoopsSameVariable.expected index 7efbbd3bfd3..3b56bbcfc44 100644 --- a/javascript/ql/test/query-tests/Statements/NestedLoopsSameVariable/NestedLoopsSameVariable.expected +++ b/javascript/ql/test/query-tests/Statements/NestedLoopsSameVariable/NestedLoopsSameVariable.expected @@ -1 +1 @@ -| tst.js:3:16:3:18 | i>5 | This for statement uses the same loop variable as an enclosing $@. | tst.js:1:1:9:1 | for (va ... , k);\\n} | for statement | +| tst.js:3:16:3:18 | i>5 | Nested for statement uses loop variable $@ of enclosing $@. | tst.js:3:23:3:23 | i | i | tst.js:1:1:9:1 | for (va ... , k);\\n} | for statement | diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/RAML.qll b/javascript/ql/test/tutorials/Validating RAML-based APIs/RAML.qll index 1156ea4c398..a871d5e751e 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/RAML.qll +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/RAML.qll @@ -3,7 +3,7 @@ import javascript import HTTP /** A RAML specification. */ -class RamlSpec extends YAMLDocument, YAMLMapping { +class RamlSpec extends YamlDocument, YamlMapping { RamlSpec() { getLocation().getFile().getExtension() = "raml" } } @@ -11,10 +11,10 @@ class RamlSpec extends YAMLDocument, YAMLMapping { deprecated class RAMLSpec = RamlSpec; /** A RAML resource specification. */ -class RamlResource extends YAMLMapping { +class RamlResource extends YamlMapping { RamlResource() { getDocument() instanceof RamlSpec and - exists(YAMLMapping m, string name | + exists(YamlMapping m, string name | this = m.lookup(name) and name.matches("/%") ) @@ -41,16 +41,16 @@ class RamlResource extends YAMLMapping { deprecated class RAMLResource = RamlResource; /** A RAML method specification. */ -class RamlMethod extends YAMLValue { +class RamlMethod extends YamlValue { RamlMethod() { getDocument() instanceof RamlSpec and - exists(YAMLMapping obj | this = obj.lookup(httpVerb())) + exists(YamlMapping obj | this = obj.lookup(httpVerb())) } /** Get the response specification for the given status code. */ - YAMLValue getResponse(int code) { - exists(YAMLMapping obj, string s | - obj = this.(YAMLMapping).lookup("responses") and + YamlValue getResponse(int code) { + exists(YamlMapping obj, string s | + obj = this.(YamlMapping).lookup("responses") and result = obj.lookup(s) and code = s.toInt() ) diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query1.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query1.ql index a20fd7f18f1..6a5c8cf71cb 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query1.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query1.ql @@ -1,7 +1,7 @@ import javascript /** A RAML specification. */ -class RamlSpec extends YAMLDocument, YAMLMapping { +class RamlSpec extends YamlDocument, YamlMapping { RamlSpec() { getLocation().getFile().getExtension() = "raml" } } diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql index e0230cbfdb0..47e264001e4 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query2.ql @@ -3,15 +3,15 @@ import javascript string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ -class RamlSpec extends YAMLDocument, YAMLMapping { +class RamlSpec extends YamlDocument, YamlMapping { RamlSpec() { getLocation().getFile().getExtension() = "raml" } } /** A RAML resource specification. */ -class RamlResource extends YAMLMapping { +class RamlResource extends YamlMapping { RamlResource() { getDocument() instanceof RamlSpec and - exists(YAMLMapping m, string name | + exists(YamlMapping m, string name | this = m.lookup(name) and name.matches("/%") ) @@ -35,16 +35,16 @@ class RamlResource extends YAMLMapping { } /** A RAML method specification. */ -class RamlMethod extends YAMLValue { +class RamlMethod extends YamlValue { RamlMethod() { getDocument() instanceof RamlSpec and - exists(YAMLMapping obj | this = obj.lookup(httpVerb())) + exists(YamlMapping obj | this = obj.lookup(httpVerb())) } /** Get the response specification for the given status code. */ - YAMLValue getResponse(int code) { - exists(YAMLMapping obj, string s | - obj = this.(YAMLMapping).lookup("responses") and + YamlValue getResponse(int code) { + exists(YamlMapping obj, string s | + obj = this.(YamlMapping).lookup("responses") and result = obj.lookup(s) and code = s.toInt() ) diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql index 60ee68a8369..12e38689590 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query3.ql @@ -3,15 +3,15 @@ import javascript string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ -class RamlSpec extends YAMLDocument, YAMLMapping { +class RamlSpec extends YamlDocument, YamlMapping { RamlSpec() { getLocation().getFile().getExtension() = "raml" } } /** A RAML resource specification. */ -class RamlResource extends YAMLMapping { +class RamlResource extends YamlMapping { RamlResource() { getDocument() instanceof RamlSpec and - exists(YAMLMapping m, string name | + exists(YamlMapping m, string name | this = m.lookup(name) and name.matches("/%") ) @@ -34,10 +34,10 @@ class RamlResource extends YAMLMapping { } } -class RamlMethod extends YAMLValue { +class RamlMethod extends YamlValue { RamlMethod() { getDocument() instanceof RamlSpec and - exists(YAMLMapping obj | this = obj.lookup(httpVerb())) + exists(YamlMapping obj | this = obj.lookup(httpVerb())) } } diff --git a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql index 0cabb0adb25..fe3986d2763 100644 --- a/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql +++ b/javascript/ql/test/tutorials/Validating RAML-based APIs/query4.ql @@ -3,15 +3,15 @@ import javascript string httpVerb() { result = ["get", "put", "post", "delete"] } /** A RAML specification. */ -class RamlSpec extends YAMLDocument, YAMLMapping { +class RamlSpec extends YamlDocument, YamlMapping { RamlSpec() { getLocation().getFile().getExtension() = "raml" } } /** A RAML resource specification. */ -class RamlResource extends YAMLMapping { +class RamlResource extends YamlMapping { RamlResource() { getDocument() instanceof RamlSpec and - exists(YAMLMapping m, string name | + exists(YamlMapping m, string name | this = m.lookup(name) and name.matches("/%") ) @@ -35,16 +35,16 @@ class RamlResource extends YAMLMapping { } /** A RAML method specification. */ -class RamlMethod extends YAMLValue { +class RamlMethod extends YamlValue { RamlMethod() { getDocument() instanceof RamlSpec and - exists(YAMLMapping obj | this = obj.lookup(httpVerb())) + exists(YamlMapping obj | this = obj.lookup(httpVerb())) } /** Get the response specification for the given status code. */ - YAMLValue getResponse(int code) { - exists(YAMLMapping obj, string s | - obj = this.(YAMLMapping).lookup("responses") and + YamlValue getResponse(int code) { + exists(YamlMapping obj, string s | + obj = this.(YamlMapping).lookup("responses") and result = obj.lookup(s) and code = s.toInt() ) diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/Scope.qll b/python/ql/lib/semmle/python/Scope.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/dataflow/new/TaintTracking3.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking3.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/dataflow/new/TaintTracking4.qll b/python/ql/lib/semmle/python/dataflow/new/TaintTracking4.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll b/python/ql/lib/semmle/python/dataflow/old/TaintTracking.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 3ba54a41718..9b5ff4c291e 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -2098,8 +2098,8 @@ private module StdlibPrivate { * * See https://docs.python.org/3.10/library/wsgiref.html#wsgiref.simple_server.WSGIRequestHandler.get_environ */ - class WSGIEnvirontParameter extends RemoteFlowSource::Range, DataFlow::ParameterNode { - WSGIEnvirontParameter() { + class WsgiEnvirontParameter extends RemoteFlowSource::Range, DataFlow::ParameterNode { + WsgiEnvirontParameter() { exists(WsgirefSimpleServerApplication func | if func.isMethod() then this.getParameter() = func.getArg(1) @@ -2112,6 +2112,9 @@ private module StdlibPrivate { } } + /** DEPRECATED: Alias for WsgiEnvirontParameter */ + deprecated class WSGIEnvirontParameter = WsgiEnvirontParameter; + /** * Gets a reference to the parameter of a `WsgirefSimpleServerApplication` that * takes the `start_response` function. diff --git a/python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll b/python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll index 3a8bf058df8..f83a6411618 100644 --- a/python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll +++ b/python/ql/lib/semmle/python/security/OverlyLargeRangeQuery.qll @@ -238,8 +238,13 @@ module RangePrinter { /** Gets a char range that is overly large because of `reason`. */ RegExpCharacterRange getABadRange(string reason, int priority) { + result instanceof OverlyWideRange and priority = 0 and - reason = "is equivalent to " + result.(OverlyWideRange).printEquivalent() + exists(string equiv | equiv = result.(OverlyWideRange).printEquivalent() | + if equiv.length() <= 50 + then reason = "is equivalent to " + equiv + else reason = "is equivalent to " + equiv.substring(0, 50) + "..." + ) or priority = 1 and exists(RegExpCharacterRange other | diff --git a/python/ql/lib/semmle/python/security/TaintTracking.qll b/python/ql/lib/semmle/python/security/TaintTracking.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll b/python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll index 000c247fc71..d006837466b 100644 --- a/python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll +++ b/python/ql/lib/semmle/python/security/regexp/ExponentialBackTracking.qll @@ -115,6 +115,7 @@ private newtype TStatePair = private int rankState(State state) { state = rank[result](State s, Location l | + stateInsideBacktracking(s) and l = s.getRepr().getLocation() | s order by l.getStartLine(), l.getStartColumn(), s.toString() diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll index fdcb10c2f85..033b8aa8cfd 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll @@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm { * Holds if this root term is relevant to the ReDoS analysis. */ predicate isRelevant() { - // there is at least one repetition - getRoot(any(InfiniteRepetitionQuantifier q)) = this and // is actually used as a RegExp this.isUsedAsRegExp() and // not excluded for library specific reasons @@ -877,6 +875,101 @@ predicate isStartState(State state) { */ signature predicate isCandidateSig(State state, string pump); +/** + * Holds if `state` is a candidate for ReDoS. + */ +signature predicate isCandidateSig(State state); + +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +module PrefixConstruction { + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + s = stateInRelevantRegexp() and + isStartState(s) and + getRoot(s.getRepr()) = root and + l = s.getRepr().getLocation() + | + s + order by + l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), + l.getEndLine() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s + order by + loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), + s.getRepr().toString() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = prefix(prev) + getCanonicalEdgeChar(prev, state) + ) + } + + /** + * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. + */ + private string getCanonicalEdgeChar(State prev, State next) { + result = + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) + } + + /** Gets a state within a regular expression that contains a candidate state. */ + pragma[noinline] + State stateInRelevantRegexp() { + exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr())) + } +} + /** * A module for pruning candidate ReDoS states. * The candidates are specified by the `isCandidate` signature predicate. @@ -910,95 +1003,9 @@ module ReDoSPruning { /** Gets a state that can reach the `accept-any` state using only epsilon steps. */ private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) } - /** - * Predicates for constructing a prefix string that leads to a given state. - */ - private module PrefixConstruction { - /** - * Holds if `state` is the textually last start state for the regular expression. - */ - private predicate lastStartState(State state) { - exists(RegExpRoot root | - state = - max(State s, Location l | - s = stateInPumpableRegexp() and - isStartState(s) and - getRoot(s.getRepr()) = root and - l = s.getRepr().getLocation() - | - s - order by - l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), - l.getEndLine() - ) - ) - } + predicate isCandidateState(State s) { isReDoSCandidate(s, _) } - /** - * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. - */ - private predicate existsTransition(State a, State b) { delta(a, _, b) } - - /** - * Gets the minimum number of transitions it takes to reach `state` from the `start` state. - */ - int prefixLength(State start, State state) = - shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) - - /** - * Gets the minimum number of transitions it takes to reach `state` from the start state. - */ - private int lengthFromStart(State state) { result = prefixLength(_, state) } - - /** - * Gets a string for which the regular expression will reach `state`. - * - * Has at most one result for any given `state`. - * This predicate will not always have a result even if there is a ReDoS issue in - * the regular expression. - */ - string prefix(State state) { - lastStartState(state) and - result = "" - or - // the search stops past the last redos candidate state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and - exists(State prev | - // select a unique predecessor (by an arbitrary measure) - prev = - min(State s, Location loc | - lengthFromStart(s) = lengthFromStart(state) - 1 and - loc = s.getRepr().getLocation() and - delta(s, _, state) - | - s - order by - loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), - s.getRepr().toString() - ) - | - // greedy search for the shortest prefix - result = prefix(prev) and delta(prev, Epsilon(), state) - or - not delta(prev, Epsilon(), state) and - result = prefix(prev) + getCanonicalEdgeChar(prev, state) - ) - } - - /** - * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. - */ - private string getCanonicalEdgeChar(State prev, State next) { - result = - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) - } - - /** Gets a state within a regular expression that has a pumpable state. */ - pragma[noinline] - State stateInPumpableRegexp() { - exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) - } - } + import PrefixConstruction as Prefix /** * Predicates for testing the presence of a rejecting suffix. @@ -1018,8 +1025,6 @@ module ReDoSPruning { * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ private module SuffixConstruction { - import PrefixConstruction - /** * Holds if all states reachable from `fork` by repeating `w` * are likely rejectable by appending some suffix. @@ -1036,7 +1041,7 @@ module ReDoSPruning { */ pragma[noinline] private predicate isLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and ( // exists a reject edge with some char. hasRejectEdge(s) @@ -1052,7 +1057,7 @@ module ReDoSPruning { * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. */ predicate isRejectState(State s) { - s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) + s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_) } /** @@ -1060,7 +1065,7 @@ module ReDoSPruning { */ pragma[noopt] predicate hasEdgeToLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | @@ -1076,7 +1081,7 @@ module ReDoSPruning { */ pragma[noinline] private string hasEdgeToLikelyRejectableHelper(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and not hasRejectEdge(s) and not isRejectState(s) and deltaClosedChar(s, result, _) @@ -1088,8 +1093,8 @@ module ReDoSPruning { * `prev` to `next` that the character symbol `char`. */ predicate deltaClosedChar(State prev, string char, State next) { - prev = stateInPumpableRegexp() and - next = stateInPumpableRegexp() and + prev = Prefix::stateInRelevantRegexp() and + next = Prefix::stateInRelevantRegexp() and deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) } @@ -1099,18 +1104,28 @@ module ReDoSPruning { result = getAnInputSymbolMatching(char) } + pragma[noinline] + RegExpRoot relevantRoot() { + exists(RegExpTerm term, State s | + s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm() + ) + } + /** * Gets a char used for finding possible suffixes inside `root`. */ pragma[noinline] private string relevant(RegExpRoot root) { - exists(ascii(result)) and exists(root) - or - exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) - or - // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). - // The three chars must be kept in sync with `hasSimpleRejectEdge`. - result = ["|", "\n", "Z"] and exists(root) + root = relevantRoot() and + ( + exists(ascii(result)) and exists(root) + or + exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + or + // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). + // The three chars must be kept in sync with `hasSimpleRejectEdge`. + result = ["|", "\n", "Z"] and exists(root) + ) } /** @@ -1208,12 +1223,12 @@ module ReDoSPruning { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { isReDoSAttackable(t, pump, s) and ( - prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and - not PrefixConstruction::prefix(s) = "" + prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and + not Prefix::prefix(s) = "" or - PrefixConstruction::prefix(s) = "" and prefixMsg = "" + Prefix::prefix(s) = "" and prefixMsg = "" or - not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + not exists(Prefix::prefix(s)) and prefixMsg = "" ) } diff --git a/python/ql/lib/semmle/python/security/strings/Basic.qll b/python/ql/lib/semmle/python/security/strings/Basic.qll old mode 100755 new mode 100644 diff --git a/python/ql/lib/semmle/python/xml/XML.qll b/python/ql/lib/semmle/python/xml/XML.qll old mode 100755 new mode 100644 diff --git a/python/ql/src/Exceptions/EmptyExcept.ql b/python/ql/src/Exceptions/EmptyExcept.ql old mode 100755 new mode 100644 diff --git a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql old mode 100755 new mode 100644 diff --git a/python/ql/src/Lexical/CommentedOutCode.ql b/python/ql/src/Lexical/CommentedOutCode.ql index d40ce95598a..d604e0290bf 100644 --- a/python/ql/src/Lexical/CommentedOutCode.ql +++ b/python/ql/src/Lexical/CommentedOutCode.ql @@ -16,4 +16,4 @@ import Lexical.CommentedOutCode from CommentedOutCodeBlock c where not c.maybeExampleCode() -select c, "These comments appear to contain commented-out code." +select c, "This comment appears to contain commented-out code." diff --git a/python/ql/src/Resources/FileNotAlwaysClosed.ql b/python/ql/src/Resources/FileNotAlwaysClosed.ql old mode 100755 new mode 100644 diff --git a/python/ql/src/Security/CWE-022/PathInjection.ql b/python/ql/src/Security/CWE-022/PathInjection.ql index 3ed0ef6234b..2ffccef1cde 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.ql +++ b/python/ql/src/Security/CWE-022/PathInjection.ql @@ -22,5 +22,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(), + "User-provided value" diff --git a/python/ql/src/Security/CWE-078/CommandInjection.ql b/python/ql/src/Security/CWE-078/CommandInjection.ql old mode 100755 new mode 100644 index d0f9214e937..f9c4f6d8ccc --- a/python/ql/src/Security/CWE-078/CommandInjection.ql +++ b/python/ql/src/Security/CWE-078/CommandInjection.ql @@ -20,5 +20,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This command depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a command.", source.getNode(), + "User-provided value" diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.ql b/python/ql/src/Security/CWE-209/StackTraceExposure.ql index 317d58f0371..85c36d2fb4f 100644 --- a/python/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/python/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -19,5 +19,6 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ may be exposed to an external user", source.getNode(), - "Error information" +select sink.getNode(), source, sink, + "Stack trace information from $@ may be exposed to an external user here.", source.getNode(), + "here" diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql index 86275621156..687cc4b4625 100644 --- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql +++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql @@ -18,4 +18,4 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Deserializing of $@.", source.getNode(), "untrusted input" +select sink.getNode(), source, sink, "Unsafe deserialization of $@.", source.getNode(), "user input" diff --git a/python/ql/src/Security/CWE-643/XpathInjection.ql b/python/ql/src/Security/CWE-643/XpathInjection.ql index 5363542278b..ac110e9e26a 100644 --- a/python/ql/src/Security/CWE-643/XpathInjection.ql +++ b/python/ql/src/Security/CWE-643/XpathInjection.ql @@ -17,4 +17,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink, source, sink, "This Xpath query depends on $@.", source, "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.", + source.getNode(), "User-provided value" diff --git a/python/ql/src/Statements/UnreachableCode.ql b/python/ql/src/Statements/UnreachableCode.ql index 04e9f79c415..47426af2c34 100644 --- a/python/ql/src/Statements/UnreachableCode.ql +++ b/python/ql/src/Statements/UnreachableCode.ql @@ -61,4 +61,4 @@ predicate reportable_unreachable(Stmt s) { from Stmt s where reportable_unreachable(s) -select s, "Unreachable statement." +select s, "This statement is unreachable." diff --git a/python/ql/src/Variables/UnusedLocalVariable.ql b/python/ql/src/Variables/UnusedLocalVariable.ql index e52c7fccaff..2202359fa0b 100644 --- a/python/ql/src/Variables/UnusedLocalVariable.ql +++ b/python/ql/src/Variables/UnusedLocalVariable.ql @@ -43,4 +43,4 @@ where unused_local(unused, v) and // If unused is part of a tuple, count it as unused if all elements of that tuple are unused. forall(Name el | el = unused.getParentNode().(Tuple).getAnElt() | unused_local(el, _)) -select unused, "The value assigned to local variable '" + v.getId() + "' is never used." +select unused, "Variable " + v.getId() + " is not used" diff --git a/python/ql/src/change-notes/2022-08-23-alert-messages.md b/python/ql/src/change-notes/2022-08-23-alert-messages.md new file mode 100644 index 00000000000..22f4c5c6682 --- /dev/null +++ b/python/ql/src/change-notes/2022-08-23-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to make the message consistent with other languages. \ No newline at end of file diff --git a/python/ql/src/experimental/semmle/python/frameworks/Django.qll b/python/ql/src/experimental/semmle/python/frameworks/Django.qll index f1895af0ea9..58d1c6a4abe 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/Django.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/Django.qll @@ -22,11 +22,14 @@ private module ExperimentalPrivateDjango { module Request { module HttpRequest { - class DjangoGETParameter extends DataFlow::Node, RemoteFlowSource::Range { - DjangoGETParameter() { this = request().getMember("GET").getMember("get").getACall() } + class DjangoGetParameter extends DataFlow::Node, RemoteFlowSource::Range { + DjangoGetParameter() { this = request().getMember("GET").getMember("get").getACall() } override string getSourceType() { result = "django.http.request.GET.get" } } + + /** DEPRECATED: Alias for DjangoGetParameter */ + deprecated class DjangoGETParameter = DjangoGetParameter; } } diff --git a/python/ql/src/experimental/semmle/python/frameworks/LDAP.qll b/python/ql/src/experimental/semmle/python/frameworks/LDAP.qll index 6ba16ae4a4e..d95149bfc50 100644 --- a/python/ql/src/experimental/semmle/python/frameworks/LDAP.qll +++ b/python/ql/src/experimental/semmle/python/frameworks/LDAP.qll @@ -126,9 +126,9 @@ private module Ldap { ( // ldap_connection.start_tls_s() // see https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.start_tls_s - exists(DataFlow::MethodCallNode startTLS | - startTLS.getObject().getALocalSource() = initialize and - startTLS.getMethodName() = "start_tls_s" + exists(DataFlow::MethodCallNode startTls | + startTls.getObject().getALocalSource() = initialize and + startTls.getMethodName() = "start_tls_s" ) or // ldap_connection.set_option(ldap.OPT_X_TLS_%s, True) @@ -234,9 +234,9 @@ private module Ldap { or // ldap_connection.start_tls_s() // see https://www.python-ldap.org/en/python-ldap-3.3.0/reference/ldap.html#ldap.LDAPObject.start_tls_s - exists(DataFlow::MethodCallNode startTLS | - startTLS.getMethodName() = "start_tls_s" and - startTLS.getObject().getALocalSource() = this + exists(DataFlow::MethodCallNode startTls | + startTls.getMethodName() = "start_tls_s" and + startTls.getObject().getALocalSource() = this ) } diff --git a/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll b/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll index 8d69bcb1a62..3eeca7a560c 100644 --- a/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll +++ b/python/ql/src/experimental/semmle/python/libraries/SmtpLib.qll @@ -31,8 +31,8 @@ module SmtpLib { * argument. Used because of the impossibility to get local source nodes from `_subparts`' * `(List|Tuple)` elements. */ - private class SMTPMessageConfig extends TaintTracking2::Configuration { - SMTPMessageConfig() { this = "SMTPMessageConfig" } + private class SmtpMessageConfig extends TaintTracking2::Configuration { + SmtpMessageConfig() { this = "SMTPMessageConfig" } override predicate isSource(DataFlow::Node source) { source = mimeText(_) } @@ -87,7 +87,7 @@ module SmtpLib { sink = [sendCall.getArg(2), sendCall.getArg(2).(DataFlow::MethodCallNode).getObject()] .getALocalSource() and - any(SMTPMessageConfig a) + any(SmtpMessageConfig a) .hasFlow(source, sink.(DataFlow::CallCfgNode).getArgByName("_subparts")) or // via .attach() @@ -117,7 +117,7 @@ module SmtpLib { * * `sub` would be `message["Subject"]` (`Subscript`) * * `result` would be `"multipart test"` */ - private DataFlow::Node getSMTPSubscriptByIndex(DataFlow::CallCfgNode sendCall, string index) { + private DataFlow::Node getSmtpSubscriptByIndex(DataFlow::CallCfgNode sendCall, string index) { exists(DefinitionNode def, Subscript sub | sub = def.getNode() and DataFlow::exprNode(sub.getObject()).getALocalSource() = @@ -163,15 +163,15 @@ module SmtpLib { override DataFlow::Node getHtmlBody() { result = getSmtpMessage(this, "html") } override DataFlow::Node getTo() { - result in [this.getArg(1), getSMTPSubscriptByIndex(this, "To")] + result in [this.getArg(1), getSmtpSubscriptByIndex(this, "To")] } override DataFlow::Node getFrom() { - result in [this.getArg(0), getSMTPSubscriptByIndex(this, "From")] + result in [this.getArg(0), getSmtpSubscriptByIndex(this, "From")] } override DataFlow::Node getSubject() { - result in [this.getArg(2), getSMTPSubscriptByIndex(this, "Subject")] + result in [this.getArg(2), getSmtpSubscriptByIndex(this, "Subject")] } } } diff --git a/python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll b/python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll index 5f19564c028..b0f0009b30d 100644 --- a/python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll +++ b/python/ql/test/experimental/dataflow/TestUtil/NormalDataflowTest.qll @@ -13,7 +13,7 @@ class DataFlowTest extends FlowTest { } } -query predicate missingAnnotationOnSINK(Location location, string error, string element) { +query predicate missingAnnotationOnSink(Location location, string error, string element) { error = "ERROR, you should add `# $ MISSING: flow` annotation" and exists(DataFlow::Node sink | exists(DataFlow::CallCfgNode call | @@ -31,3 +31,6 @@ query predicate missingAnnotationOnSINK(Location location, string error, string ) ) } + +/** DEPRECATED: Alias for missingAnnotationOnSink */ +deprecated predicate missingAnnotationOnSINK = missingAnnotationOnSink/3; diff --git a/python/ql/test/experimental/dataflow/coverage/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/coverage/NormalDataflowTest.expected index dd7fb126526..3875da4e143 100644 --- a/python/ql/test/experimental/dataflow/coverage/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/coverage/NormalDataflowTest.expected @@ -1,2 +1,2 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures diff --git a/python/ql/test/experimental/dataflow/fieldflow/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/fieldflow/NormalDataflowTest.expected index dd7fb126526..3875da4e143 100644 --- a/python/ql/test/experimental/dataflow/fieldflow/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/fieldflow/NormalDataflowTest.expected @@ -1,2 +1,2 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures diff --git a/python/ql/test/experimental/dataflow/match/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/match/NormalDataflowTest.expected index dd7fb126526..3875da4e143 100644 --- a/python/ql/test/experimental/dataflow/match/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/match/NormalDataflowTest.expected @@ -1,2 +1,2 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md index 7f098028457..59e9087ee49 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/README.md @@ -39,7 +39,7 @@ diff '--color=auto' -u -r test-1-normal/NormalDataflowTest.expected test-5-max-i --- test-1-normal/NormalDataflowTest.expected 2022-02-27 10:33:00.603882599 +0100 +++ test-5-max-import-depth-3/NormalDataflowTest.expected 2022-02-28 10:10:08.930743800 +0100 @@ -1,2 +1,3 @@ - missingAnnotationOnSINK + missingAnnotationOnSink failures +| ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff '--color=auto' -u -r test-1-normal/options test-5-max-import-depth-3/options @@ -88,7 +88,7 @@ diff '--color=auto' -u -r test-4-max-import-depth-100/NormalDataflowTest.expecte --- test-4-max-import-depth-100/NormalDataflowTest.expected 2022-02-28 10:10:02.206608379 +0100 +++ test-6-max-import-depth-2/NormalDataflowTest.expected 2022-02-28 10:10:13.882716665 +0100 @@ -1,3 +1,5 @@ - missingAnnotationOnSINK + missingAnnotationOnSink +| ../src/isfile_no_problem.py:43:6:43:8 | ../src/isfile_no_problem.py:43 | ERROR, you should add `# $ MISSING: flow` annotation | foo | failures +| ../src/isfile_no_problem.py:43:11:43:41 | Comment # $ flow="SOURCE, l:-15 -> foo" | Missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected index dd7fb126526..3875da4e143 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-1-normal/NormalDataflowTest.expected @@ -1,2 +1,2 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected index dc83fab3907..ceeb0ef30e0 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-2-without-splitting/NormalDataflowTest.expected @@ -1,3 +1,3 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures | ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected index dc83fab3907..ceeb0ef30e0 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-3-max-import-depth-0/NormalDataflowTest.expected @@ -1,3 +1,3 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures | ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected index dc83fab3907..ceeb0ef30e0 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-4-max-import-depth-100/NormalDataflowTest.expected @@ -1,3 +1,3 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures | ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected index dc83fab3907..ceeb0ef30e0 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-5-max-import-depth-3/NormalDataflowTest.expected @@ -1,3 +1,3 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures | ../src/urandom_problem.py:43:6:43:8 | ControlFlowNode for foo | Fixed missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected index aa4bfeb5ae4..7b5784017f3 100644 --- a/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected +++ b/python/ql/test/experimental/dataflow/strange-pointsto-interaction-investigation/test-6-max-import-depth-2/NormalDataflowTest.expected @@ -1,4 +1,4 @@ -missingAnnotationOnSINK +missingAnnotationOnSink | ../src/isfile_no_problem.py:43:6:43:8 | ../src/isfile_no_problem.py:43 | ERROR, you should add `# $ MISSING: flow` annotation | foo | failures | ../src/isfile_no_problem.py:43:11:43:41 | Comment # $ flow="SOURCE, l:-15 -> foo" | Missing result:flow="SOURCE, l:-15 -> foo" | diff --git a/python/ql/test/library-tests/PointsTo/new/Dataflow.ql b/python/ql/test/library-tests/PointsTo/new/Dataflow.ql old mode 100755 new mode 100644 diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql old mode 100755 new mode 100644 diff --git a/python/ql/test/library-tests/formatting/FormatArguments.expected b/python/ql/test/library-tests/formatting/FormatArguments.expected old mode 100755 new mode 100644 diff --git a/python/ql/test/library-tests/formatting/FormatFields.expected b/python/ql/test/library-tests/formatting/FormatFields.expected old mode 100755 new mode 100644 diff --git a/python/ql/test/library-tests/frameworks/django-orm/NormalDataflowTest.expected b/python/ql/test/library-tests/frameworks/django-orm/NormalDataflowTest.expected index dd7fb126526..3875da4e143 100644 --- a/python/ql/test/library-tests/frameworks/django-orm/NormalDataflowTest.expected +++ b/python/ql/test/library-tests/frameworks/django-orm/NormalDataflowTest.expected @@ -1,2 +1,2 @@ -missingAnnotationOnSINK +missingAnnotationOnSink failures diff --git a/python/ql/test/library-tests/jump_to_defn/Remote.expected b/python/ql/test/library-tests/jump_to_defn/Remote.expected old mode 100755 new mode 100644 diff --git a/python/ql/test/library-tests/jump_to_defn/test.expected b/python/ql/test/library-tests/jump_to_defn/test.expected old mode 100755 new mode 100644 diff --git a/python/ql/test/query-tests/Exceptions/general/EmptyExcept.expected b/python/ql/test/query-tests/Exceptions/general/EmptyExcept.expected old mode 100755 new mode 100644 diff --git a/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.expected b/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.expected index ac6b27d1a22..ba25d2e5559 100644 --- a/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.expected +++ b/python/ql/test/query-tests/Lexical/commented_out_code/CommentedOutCode.expected @@ -1,3 +1,3 @@ -| test.py:15:5:16:28 | Commented out code | These comments appear to contain commented-out code. | -| test.py:21:1:72:9 | Commented out code | These comments appear to contain commented-out code. | -| test.py:78:1:85:9 | Commented out code | These comments appear to contain commented-out code. | +| test.py:15:5:16:28 | Commented out code | This comment appears to contain commented-out code. | +| test.py:21:1:72:9 | Commented out code | This comment appears to contain commented-out code. | +| test.py:78:1:85:9 | Commented out code | This comment appears to contain commented-out code. | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected index 49c173f6fe9..1c037c6e1db 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected @@ -122,21 +122,21 @@ subpaths | test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() | #select -| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | a user-provided value | -| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:19:16:19:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:46:16:46:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:63:16:63:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on $@. | path_injection.py:84:16:84:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | a user-provided value | -| path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | a user-provided value | -| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:107:16:107:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:118:16:118:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on $@. | path_injection.py:129:16:129:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:138:16:138:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on $@. | path_injection.py:149:16:149:22 | ControlFlowNode for request | a user-provided value | -| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | +| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | $@ flows to here and is used in a path. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | User-provided value | +| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | $@ flows to here and is used in a path. | path_injection.py:12:16:12:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | $@ flows to here and is used in a path. | path_injection.py:19:16:19:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | $@ flows to here and is used in a path. | path_injection.py:27:16:27:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | $@ flows to here and is used in a path. | path_injection.py:46:16:46:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | $@ flows to here and is used in a path. | path_injection.py:63:16:63:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | $@ flows to here and is used in a path. | path_injection.py:84:16:84:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | User-provided value | +| path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | User-provided value | +| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:107:16:107:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:118:16:118:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | $@ flows to here and is used in a path. | path_injection.py:129:16:129:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:138:16:138:22 | ControlFlowNode for request | User-provided value | +| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | $@ flows to here and is used in a path. | path_injection.py:149:16:149:22 | ControlFlowNode for request | User-provided value | +| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | $@ flows to here and is used in a path. | test.py:9:12:9:18 | ControlFlowNode for request | User-provided value | +| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | $@ flows to here and is used in a path. | test.py:9:12:9:18 | ControlFlowNode for request | User-provided value | +| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | $@ flows to here and is used in a path. | test.py:9:12:9:18 | ControlFlowNode for request | User-provided value | +| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | $@ flows to here and is used in a path. | test.py:9:12:9:18 | ControlFlowNode for request | User-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected index 3c000eb1070..e1069c6fb4e 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected @@ -23,12 +23,12 @@ nodes | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | +| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected index 449bc4d0efb..5ef5ca01061 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected @@ -52,16 +52,16 @@ nodes | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command depends on $@. | command_injection.py:25:11:25:17 | ControlFlowNode for request | a user-provided value | -| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:31:13:31:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:71:12:71:18 | ControlFlowNode for request | a user-provided value | -| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command depends on $@. | command_injection.py:78:12:78:18 | ControlFlowNode for request | a user-provided value | +| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:11:13:11:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:18:13:18:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | $@ flows to here and is used in a command. | command_injection.py:25:11:25:17 | ControlFlowNode for request | User-provided value | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:31:13:31:19 | ControlFlowNode for request | User-provided value | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:38:15:38:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:38:15:38:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:54:15:54:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:54:15:54:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:54:15:54:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:54:15:54:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | $@ flows to here and is used in a command. | command_injection.py:54:15:54:21 | ControlFlowNode for request | User-provided value | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:71:12:71:18 | ControlFlowNode for request | User-provided value | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in a command. | command_injection.py:78:12:78:18 | ControlFlowNode for request | User-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected index cf73f12b9a4..85f0eab4e37 100644 --- a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected +++ b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected @@ -19,7 +19,7 @@ nodes subpaths | test.py:50:29:50:31 | ControlFlowNode for err | test.py:52:18:52:20 | ControlFlowNode for msg | test.py:53:12:53:27 | ControlFlowNode for BinaryExpr | test.py:50:16:50:32 | ControlFlowNode for format_error() | #select -| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | $@ may be exposed to an external user | test.py:16:16:16:37 | ControlFlowNode for Attribute() | Error information | -| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | $@ may be exposed to an external user | test.py:23:25:23:25 | SSA variable e | Error information | -| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | $@ may be exposed to an external user | test.py:31:25:31:25 | SSA variable e | Error information | -| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | $@ may be exposed to an external user | test.py:49:15:49:36 | ControlFlowNode for Attribute() | Error information | +| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | Stack trace information from $@ may be exposed to an external user here. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | here | +| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | Stack trace information from $@ may be exposed to an external user here. | test.py:23:25:23:25 | SSA variable e | here | +| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | Stack trace information from $@ may be exposed to an external user here. | test.py:31:25:31:25 | SSA variable e | here | +| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | Stack trace information from $@ may be exposed to an external user here. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | here | diff --git a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected index cee0bf3ad7c..9c158382a74 100644 --- a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected +++ b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected @@ -13,7 +13,7 @@ nodes | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | subpaths #select -| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | untrusted input | -| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | untrusted input | -| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | untrusted input | -| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Deserializing of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | untrusted input | +| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user input | +| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user input | +| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user input | +| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization of $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user input | diff --git a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected index 9a10b21d56d..e732b5db795 100644 --- a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected @@ -34,9 +34,9 @@ nodes | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | semmle.label | ControlFlowNode for xpathQuery | subpaths #select -| xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | This Xpath query depends on $@. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | This Xpath query depends on $@. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | This Xpath query depends on $@. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | This Xpath query depends on $@. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | This Xpath query depends on $@. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | This Xpath query depends on $@. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | a user-provided value | +| xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | $@ flows to here and is used in an XPath expression. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | User-provided value | +| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | $@ flows to here and is used in an XPath expression. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | User-provided value | +| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | $@ flows to here and is used in an XPath expression. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | User-provided value | +| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | $@ flows to here and is used in an XPath expression. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | User-provided value | +| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | $@ flows to here and is used in an XPath expression. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | User-provided value | +| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | $@ flows to here and is used in an XPath expression. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | User-provided value | diff --git a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected index 74e56473a61..2417041f472 100644 --- a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected +++ b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected @@ -1,6 +1,6 @@ -| test.py:8:9:8:28 | AssignStmt | Unreachable statement. | -| test.py:10:9:10:28 | Return | Unreachable statement. | -| test.py:16:9:16:21 | ExprStmt | Unreachable statement. | -| test.py:21:5:21:38 | For | Unreachable statement. | -| test.py:28:9:28:21 | ExprStmt | Unreachable statement. | -| test.py:84:5:84:21 | ExceptStmt | Unreachable statement. | +| test.py:8:9:8:28 | AssignStmt | This statement is unreachable. | +| test.py:10:9:10:28 | Return | This statement is unreachable. | +| test.py:16:9:16:21 | ExprStmt | This statement is unreachable. | +| test.py:21:5:21:38 | For | This statement is unreachable. | +| test.py:28:9:28:21 | ExprStmt | This statement is unreachable. | +| test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. | diff --git a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected index a902cad04cb..e0c2505bdda 100644 --- a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected +++ b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected @@ -1,5 +1,5 @@ -| variables_test.py:29:5:29:5 | x | The value assigned to local variable 'x' is never used. | -| variables_test.py:89:5:89:5 | a | The value assigned to local variable 'a' is never used. | -| variables_test.py:89:7:89:7 | b | The value assigned to local variable 'b' is never used. | -| variables_test.py:89:9:89:9 | c | The value assigned to local variable 'c' is never used. | -| variables_test.py:95:5:95:7 | var | The value assigned to local variable 'var' is never used. | +| variables_test.py:29:5:29:5 | x | Variable x is not used | +| variables_test.py:89:5:89:5 | a | Variable a is not used | +| variables_test.py:89:7:89:7 | b | Variable b is not used | +| variables_test.py:89:9:89:9 | c | Variable c is not used | +| variables_test.py:95:5:95:7 | var | Variable var is not used | diff --git a/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected b/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected index 3cb5b2a8e63..9abbf310179 100644 --- a/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected +++ b/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected @@ -1 +1 @@ -| variables_test.py:32:9:32:12 | test | The value assigned to local variable 'test' is never used. | +| variables_test.py:32:9:32:12 | test | Variable test is not used | diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 7e7013b36c7..89f819f4223 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -521,6 +521,9 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati } override predicate isPrivate() { Predicate.super.isPrivate() } + + /** Holds if this classless predicate is a signature predicate with no body. */ + predicate isSignature() { not exists(this.getBody()) } } /** @@ -2477,15 +2480,18 @@ class BindingSet extends Annotation { */ module YAML { /** A node in a YAML file */ - class YAMLNode extends TYamlNode, AstNode { + class YamlNode extends TYamlNode, AstNode { /** Holds if the predicate is a root node (has no parent) */ predicate isRoot() { not exists(this.getParent()) } override AstNode getParent() { toGenerateYaml(result) = toGenerateYaml(this).getParent() } } + /** DEPRECATED: Alias for YamlNode */ + deprecated class YAMLNode = YamlNode; + /** A YAML comment. */ - class YamlComment extends TYamlCommemt, YAMLNode { + class YamlComment extends TYamlCommemt, YamlNode { Yaml::Comment yamlcomment; YamlComment() { this = TYamlCommemt(yamlcomment) } @@ -2497,7 +2503,7 @@ module YAML { deprecated class YAMLComment = YamlComment; /** A YAML entry. */ - class YamlEntry extends TYamlEntry, YAMLNode { + class YamlEntry extends TYamlEntry, YamlNode { Yaml::Entry yamle; YamlEntry() { this = TYamlEntry(yamle) } @@ -2527,7 +2533,7 @@ module YAML { deprecated class YAMLEntry = YamlEntry; /** A YAML key. */ - class YamlKey extends TYamlKey, YAMLNode { + class YamlKey extends TYamlKey, YamlNode { Yaml::Key yamlkey; YamlKey() { this = TYamlKey(yamlkey) } @@ -2566,7 +2572,7 @@ module YAML { deprecated class YAMLKey = YamlKey; /** A YAML list item. */ - class YamlListItem extends TYamlListitem, YAMLNode { + class YamlListItem extends TYamlListitem, YamlNode { Yaml::Listitem yamllistitem; YamlListItem() { this = TYamlListitem(yamllistitem) } @@ -2583,7 +2589,7 @@ module YAML { deprecated class YAMLListItem = YamlListItem; /** A YAML value. */ - class YamlValue extends TYamlValue, YAMLNode { + class YamlValue extends TYamlValue, YamlNode { Yaml::Value yamlvalue; YamlValue() { this = TYamlValue(yamlvalue) } @@ -2691,7 +2697,7 @@ module YAML { Location getLocation() { // hacky, just pick the first node in the file. result = - min(YAMLNode entry, Location l, File f | + min(YamlNode entry, Location l, File f | entry.getLocation().getFile() = file and f = file and l = entry.getLocation() diff --git a/ql/ql/src/codeql_ql/ast/internal/Predicate.qll b/ql/ql/src/codeql_ql/ast/internal/Predicate.qll index d0a5cac8534..689880ce7e9 100644 --- a/ql/ql/src/codeql_ql/ast/internal/Predicate.qll +++ b/ql/ql/src/codeql_ql/ast/internal/Predicate.qll @@ -209,7 +209,9 @@ module PredConsistency { not exists(p0.getAlias()) ) and c > 1 and - resolvePredicateExpr(pe, p) + resolvePredicateExpr(pe, p) and + // parameterized modules are expected to resolve to multiple. + not exists(ClasslessPredicate sig | not sig.isSignature() and resolvePredicateExpr(pe, sig)) } query predicate multipleResolveCall(Call call, int c, PredicateOrBuiltin p) { @@ -225,6 +227,6 @@ module PredConsistency { c > 1 and resolveCall(call, p) and // parameterized modules are expected to resolve to multiple. - not exists(Predicate sig | not exists(sig.getBody()) and resolveCall(call, sig)) + not exists(ClasslessPredicate sig | not sig.isSignature() and resolveCall(call, sig)) } } diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll index 447048d446e..798a35d1169 100644 --- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll +++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll @@ -606,11 +606,20 @@ module API { result = useCandRev() and t.start() or - exists(TypeTracker t2, DataFlow::LocalSourceNode mid, TypeBackTracker tb | + exists(TypeTracker t2, DataFlow::LocalSourceNode mid | mid = trackUseNode(src, t2) and - result = mid.track(t2, t) and - pragma[only_bind_out](result) = useCandRev(tb) and - pragma[only_bind_out](t) = pragma[only_bind_out](tb).getACompatibleTypeTracker() + result = useNodeStep(mid, t2, t) + ) + } + + pragma[nomagic] + private DataFlow::Node useNodeStep( + DataFlow::LocalSourceNode mid, TypeTracker tmid, TypeTracker t + ) { + exists(TypeBackTracker tb | + result = mid.track(tmid, t) and + pragma[only_bind_into](result) = useCandRev(pragma[only_bind_into](tb)) and + pragma[only_bind_out](t) = pragma[only_bind_into](tb).getACompatibleTypeTracker() ) } diff --git a/ruby/ql/lib/codeql/ruby/TaintTracking.qll b/ruby/ql/lib/codeql/ruby/TaintTracking.qll old mode 100755 new mode 100644 diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPrivate.qll old mode 100755 new mode 100644 diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/TaintTrackingPublic.qll old mode 100755 new mode 100644 diff --git a/ruby/ql/lib/codeql/ruby/frameworks/XmlParsing.qll b/ruby/ql/lib/codeql/ruby/frameworks/XmlParsing.qll index 8113bb537e2..51fa3d5f76b 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/XmlParsing.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/XmlParsing.qll @@ -97,13 +97,13 @@ class Feature extends TFeature { abstract string getConstantName(); } -private class FeatureNOENT extends Feature, TNOENT { +private class FeatureNoent extends Feature, TNOENT { override int getValue() { result = 2 } override string getConstantName() { result = "NOENT" } } -private class FeatureNONET extends Feature, TNONET { +private class FeatureNonet extends Feature, TNONET { override int getValue() { result = 2048 } override string getConstantName() { result = "NONET" } diff --git a/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeCustomizations.qll new file mode 100644 index 00000000000..d5774dca1dd --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeCustomizations.qll @@ -0,0 +1,111 @@ +/** + * Provides default sources, sinks and sanitizers for reasoning about hard-coded + * data being interpreted as code, as well as extension points for adding your + * own. + */ + +private import codeql.ruby.DataFlow +private import codeql.ruby.security.CodeInjectionCustomizations +private import codeql.ruby.AST as AST +private import codeql.ruby.controlflow.CfgNodes + +/** + * Provides default sources, sinks and sanitizers for reasoning about hard-coded + * data being interpreted as code, as well as extension points for adding your + * own. + */ +module HardcodedDataInterpretedAsCode { + /** + * Flow states used to distinguish value-preserving flow from taint flow. + */ + module FlowState { + /** Flow state used to track value-preserving flow. */ + DataFlow::FlowState data() { result = "data" } + + /** Flow state used to tainted data (non-value preserving flow). */ + DataFlow::FlowState taint() { result = "taint" } + } + + /** + * A data flow source for hard-coded data. + */ + abstract class Source extends DataFlow::Node { + /** Gets a flow label for which this is a source. */ + DataFlow::FlowState getLabel() { result = FlowState::data() } + } + + /** + * A data flow sink for code injection. + */ + abstract class Sink extends DataFlow::Node { + /** Gets a description of what kind of sink this is. */ + abstract string getKind(); + + /** Gets a flow label for which this is a sink. */ + DataFlow::FlowState getLabel() { + // We want to ignore value-flow and only consider taint-flow, since the + // source is just a hex string, and evaluating that directly will just + // cause a syntax error. + result = FlowState::taint() + } + } + + /** A sanitizer for hard-coded data. */ + abstract class Sanitizer extends DataFlow::Node { } + + /** + * A constant string consisting of eight or more hexadecimal characters (including at + * least one digit), viewed as a source of hard-coded data that should not be + * interpreted as code. + */ + private class HexStringSource extends Source { + HexStringSource() { + exists(string val | + this.asExpr().(ExprNodes::StringLiteralCfgNode).getConstantValue().isString(val) + | + val.regexpMatch("[0-9a-fA-F]{8,}") and + val.regexpMatch(".*[0-9].*") + ) + } + } + + /** + * A string literal whose raw text is made up entirely of `\x` escape + * sequences, viewed as a source of hard-coded data that should not be + * interpreted as code. + */ + private class HexEscapedStringSource extends Source { + HexEscapedStringSource() { + forex(StringComponentCfgNode c | + c = this.asExpr().(ExprNodes::StringlikeLiteralCfgNode).getAComponent() + | + c.getNode().(AST::StringEscapeSequenceComponent).getRawText().matches("\\x%") + ) + } + } + + /** + * A code injection sink; hard-coded data should not flow here. + */ + private class DefaultCodeInjectionSink extends Sink { + DefaultCodeInjectionSink() { this instanceof CodeInjection::Sink } + + override string getKind() { result = "code" } + } + + /** + * An argument to `require` path; hard-coded data should not flow here. + */ + private class RequireArgumentSink extends Sink { + RequireArgumentSink() { + exists(DataFlow::CallNode require | + require.getReceiver().getExprNode().getExpr() instanceof AST::SelfVariableAccess and + require.getMethodName() = "require" + | + this = require.getArgument(0) + ) + } + + override string getKind() { result = "an import path" } + } +} diff --git a/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeQuery.qll b/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeQuery.qll new file mode 100644 index 00000000000..98fb0542815 --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/security/HardcodedDataInterpretedAsCodeQuery.qll @@ -0,0 +1,48 @@ +/** + * Provides a taint-tracking configuration for reasoning about hard-coded data + * being interpreted as code. + * + * Note, for performance reasons: only import this file if + * `HardcodedDataInterpretedAsCode::Configuration` is needed, otherwise + * `HardcodedDataInterpretedAsCodeCustomizations` should be imported instead. + */ + +private import codeql.ruby.DataFlow +private import codeql.ruby.TaintTracking +private import codeql.ruby.dataflow.internal.TaintTrackingPrivate +import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode + +/** + * A taint-tracking configuration for reasoning about hard-coded data + * being interpreted as code. + * + * We extend `DataFlow::Configuration` rather than + * `TaintTracking::Configuration`, so that we can set the flow state to + * `"taint"` on a taint step. + */ +class Configuration extends DataFlow::Configuration { + Configuration() { this = "HardcodedDataInterpretedAsCode" } + + override predicate isSource(DataFlow::Node source, DataFlow::FlowState label) { + source.(Source).getLabel() = label + } + + override predicate isSink(DataFlow::Node sink, DataFlow::FlowState label) { + sink.(Sink).getLabel() = label + } + + override predicate isBarrier(DataFlow::Node node) { + super.isBarrier(node) or + node instanceof Sanitizer + } + + override predicate isAdditionalFlowStep( + DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo, + DataFlow::FlowState stateTo + ) { + defaultAdditionalTaintStep(nodeFrom, nodeTo) and + // This is a taint step, so the flow state becomes `taint`. + stateFrom = [FlowState::data(), FlowState::taint()] and + stateTo = FlowState::taint() + } +} diff --git a/ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll b/ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll index 3a8bf058df8..f83a6411618 100644 --- a/ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll +++ b/ruby/ql/lib/codeql/ruby/security/OverlyLargeRangeQuery.qll @@ -238,8 +238,13 @@ module RangePrinter { /** Gets a char range that is overly large because of `reason`. */ RegExpCharacterRange getABadRange(string reason, int priority) { + result instanceof OverlyWideRange and priority = 0 and - reason = "is equivalent to " + result.(OverlyWideRange).printEquivalent() + exists(string equiv | equiv = result.(OverlyWideRange).printEquivalent() | + if equiv.length() <= 50 + then reason = "is equivalent to " + equiv + else reason = "is equivalent to " + equiv.substring(0, 50) + "..." + ) or priority = 1 and exists(RegExpCharacterRange other | diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll b/ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll index 000c247fc71..d006837466b 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/ExponentialBackTracking.qll @@ -115,6 +115,7 @@ private newtype TStatePair = private int rankState(State state) { state = rank[result](State s, Location l | + stateInsideBacktracking(s) and l = s.getRepr().getLocation() | s order by l.getStartLine(), l.getStartColumn(), s.toString() diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll index fdcb10c2f85..033b8aa8cfd 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll @@ -93,8 +93,6 @@ class RegExpRoot extends RegExpTerm { * Holds if this root term is relevant to the ReDoS analysis. */ predicate isRelevant() { - // there is at least one repetition - getRoot(any(InfiniteRepetitionQuantifier q)) = this and // is actually used as a RegExp this.isUsedAsRegExp() and // not excluded for library specific reasons @@ -877,6 +875,101 @@ predicate isStartState(State state) { */ signature predicate isCandidateSig(State state, string pump); +/** + * Holds if `state` is a candidate for ReDoS. + */ +signature predicate isCandidateSig(State state); + +/** + * Predicates for constructing a prefix string that leads to a given state. + */ +module PrefixConstruction { + /** + * Holds if `state` is the textually last start state for the regular expression. + */ + private predicate lastStartState(State state) { + exists(RegExpRoot root | + state = + max(State s, Location l | + s = stateInRelevantRegexp() and + isStartState(s) and + getRoot(s.getRepr()) = root and + l = s.getRepr().getLocation() + | + s + order by + l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), + l.getEndLine() + ) + ) + } + + /** + * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. + */ + private predicate existsTransition(State a, State b) { delta(a, _, b) } + + /** + * Gets the minimum number of transitions it takes to reach `state` from the `start` state. + */ + int prefixLength(State start, State state) = + shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) + + /** + * Gets the minimum number of transitions it takes to reach `state` from the start state. + */ + private int lengthFromStart(State state) { result = prefixLength(_, state) } + + /** + * Gets a string for which the regular expression will reach `state`. + * + * Has at most one result for any given `state`. + * This predicate will not always have a result even if there is a ReDoS issue in + * the regular expression. + */ + string prefix(State state) { + lastStartState(state) and + result = "" + or + // the search stops past the last redos candidate state. + lengthFromStart(state) <= max(lengthFromStart(any(State s | isCandidate(s)))) and + exists(State prev | + // select a unique predecessor (by an arbitrary measure) + prev = + min(State s, Location loc | + lengthFromStart(s) = lengthFromStart(state) - 1 and + loc = s.getRepr().getLocation() and + delta(s, _, state) + | + s + order by + loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), + s.getRepr().toString() + ) + | + // greedy search for the shortest prefix + result = prefix(prev) and delta(prev, Epsilon(), state) + or + not delta(prev, Epsilon(), state) and + result = prefix(prev) + getCanonicalEdgeChar(prev, state) + ) + } + + /** + * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. + */ + private string getCanonicalEdgeChar(State prev, State next) { + result = + min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) + } + + /** Gets a state within a regular expression that contains a candidate state. */ + pragma[noinline] + State stateInRelevantRegexp() { + exists(State s | isCandidate(s) | getRoot(s.getRepr()) = getRoot(result.getRepr())) + } +} + /** * A module for pruning candidate ReDoS states. * The candidates are specified by the `isCandidate` signature predicate. @@ -910,95 +1003,9 @@ module ReDoSPruning { /** Gets a state that can reach the `accept-any` state using only epsilon steps. */ private State acceptsAnySuffix() { epsilonSucc*(result) = AcceptAnySuffix(_) } - /** - * Predicates for constructing a prefix string that leads to a given state. - */ - private module PrefixConstruction { - /** - * Holds if `state` is the textually last start state for the regular expression. - */ - private predicate lastStartState(State state) { - exists(RegExpRoot root | - state = - max(State s, Location l | - s = stateInPumpableRegexp() and - isStartState(s) and - getRoot(s.getRepr()) = root and - l = s.getRepr().getLocation() - | - s - order by - l.getStartLine(), l.getStartColumn(), s.getRepr().toString(), l.getEndColumn(), - l.getEndLine() - ) - ) - } + predicate isCandidateState(State s) { isReDoSCandidate(s, _) } - /** - * Holds if there exists any transition (Epsilon() or other) from `a` to `b`. - */ - private predicate existsTransition(State a, State b) { delta(a, _, b) } - - /** - * Gets the minimum number of transitions it takes to reach `state` from the `start` state. - */ - int prefixLength(State start, State state) = - shortestDistances(lastStartState/1, existsTransition/2)(start, state, result) - - /** - * Gets the minimum number of transitions it takes to reach `state` from the start state. - */ - private int lengthFromStart(State state) { result = prefixLength(_, state) } - - /** - * Gets a string for which the regular expression will reach `state`. - * - * Has at most one result for any given `state`. - * This predicate will not always have a result even if there is a ReDoS issue in - * the regular expression. - */ - string prefix(State state) { - lastStartState(state) and - result = "" - or - // the search stops past the last redos candidate state. - lengthFromStart(state) <= max(lengthFromStart(any(State s | isReDoSCandidate(s, _)))) and - exists(State prev | - // select a unique predecessor (by an arbitrary measure) - prev = - min(State s, Location loc | - lengthFromStart(s) = lengthFromStart(state) - 1 and - loc = s.getRepr().getLocation() and - delta(s, _, state) - | - s - order by - loc.getStartLine(), loc.getStartColumn(), loc.getEndLine(), loc.getEndColumn(), - s.getRepr().toString() - ) - | - // greedy search for the shortest prefix - result = prefix(prev) and delta(prev, Epsilon(), state) - or - not delta(prev, Epsilon(), state) and - result = prefix(prev) + getCanonicalEdgeChar(prev, state) - ) - } - - /** - * Gets a canonical char for which there exists a transition from `prev` to `next` in the NFA. - */ - private string getCanonicalEdgeChar(State prev, State next) { - result = - min(string c | delta(prev, any(InputSymbol symbol | c = intersect(Any(), symbol)), next)) - } - - /** Gets a state within a regular expression that has a pumpable state. */ - pragma[noinline] - State stateInPumpableRegexp() { - exists(State s | isReDoSCandidate(s, _) | getRoot(s.getRepr()) = getRoot(result.getRepr())) - } - } + import PrefixConstruction as Prefix /** * Predicates for testing the presence of a rejecting suffix. @@ -1018,8 +1025,6 @@ module ReDoSPruning { * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ private module SuffixConstruction { - import PrefixConstruction - /** * Holds if all states reachable from `fork` by repeating `w` * are likely rejectable by appending some suffix. @@ -1036,7 +1041,7 @@ module ReDoSPruning { */ pragma[noinline] private predicate isLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and ( // exists a reject edge with some char. hasRejectEdge(s) @@ -1052,7 +1057,7 @@ module ReDoSPruning { * Holds if `s` is not an accept state, and there is no epsilon transition to an accept state. */ predicate isRejectState(State s) { - s = stateInPumpableRegexp() and not epsilonSucc*(s) = Accept(_) + s = Prefix::stateInRelevantRegexp() and not epsilonSucc*(s) = Accept(_) } /** @@ -1060,7 +1065,7 @@ module ReDoSPruning { */ pragma[noopt] predicate hasEdgeToLikelyRejectable(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and // all edges (at least one) with some char leads to another state that is rejectable. // the `next` states might not share a common suffix, which can cause FPs. exists(string char | char = hasEdgeToLikelyRejectableHelper(s) | @@ -1076,7 +1081,7 @@ module ReDoSPruning { */ pragma[noinline] private string hasEdgeToLikelyRejectableHelper(State s) { - s = stateInPumpableRegexp() and + s = Prefix::stateInRelevantRegexp() and not hasRejectEdge(s) and not isRejectState(s) and deltaClosedChar(s, result, _) @@ -1088,8 +1093,8 @@ module ReDoSPruning { * `prev` to `next` that the character symbol `char`. */ predicate deltaClosedChar(State prev, string char, State next) { - prev = stateInPumpableRegexp() and - next = stateInPumpableRegexp() and + prev = Prefix::stateInRelevantRegexp() and + next = Prefix::stateInRelevantRegexp() and deltaClosed(prev, getAnInputSymbolMatchingRelevant(char), next) } @@ -1099,18 +1104,28 @@ module ReDoSPruning { result = getAnInputSymbolMatching(char) } + pragma[noinline] + RegExpRoot relevantRoot() { + exists(RegExpTerm term, State s | + s.getRepr() = term and isCandidateState(s) and result = term.getRootTerm() + ) + } + /** * Gets a char used for finding possible suffixes inside `root`. */ pragma[noinline] private string relevant(RegExpRoot root) { - exists(ascii(result)) and exists(root) - or - exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) - or - // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). - // The three chars must be kept in sync with `hasSimpleRejectEdge`. - result = ["|", "\n", "Z"] and exists(root) + root = relevantRoot() and + ( + exists(ascii(result)) and exists(root) + or + exists(InputSymbol s | belongsTo(s, root) | result = intersect(s, _)) + or + // The characters from `hasSimpleRejectEdge`. Only `\n` is really needed (as `\n` is not in the `ascii` relation). + // The three chars must be kept in sync with `hasSimpleRejectEdge`. + result = ["|", "\n", "Z"] and exists(root) + ) } /** @@ -1208,12 +1223,12 @@ module ReDoSPruning { predicate hasReDoSResult(RegExpTerm t, string pump, State s, string prefixMsg) { isReDoSAttackable(t, pump, s) and ( - prefixMsg = "starting with '" + escape(PrefixConstruction::prefix(s)) + "' and " and - not PrefixConstruction::prefix(s) = "" + prefixMsg = "starting with '" + escape(Prefix::prefix(s)) + "' and " and + not Prefix::prefix(s) = "" or - PrefixConstruction::prefix(s) = "" and prefixMsg = "" + Prefix::prefix(s) = "" and prefixMsg = "" or - not exists(PrefixConstruction::prefix(s)) and prefixMsg = "" + not exists(Prefix::prefix(s)) and prefixMsg = "" ) } diff --git a/ruby/ql/src/change-notes/2022-07-26-hardcoded-data.md b/ruby/ql/src/change-notes/2022-07-26-hardcoded-data.md new file mode 100644 index 00000000000..4878b51992f --- /dev/null +++ b/ruby/ql/src/change-notes/2022-07-26-hardcoded-data.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new query, `rb/hardcoded-data-interpreted-as-code`, to detect cases where hardcoded data is executed as code, a technique associated with backdoors. diff --git a/ruby/ql/src/change-notes/2022-08-23-alert-messages.md b/ruby/ql/src/change-notes/2022-08-23-alert-messages.md new file mode 100644 index 00000000000..22f4c5c6682 --- /dev/null +++ b/ruby/ql/src/change-notes/2022-08-23-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to make the message consistent with other languages. \ No newline at end of file diff --git a/ruby/ql/src/queries/security/cwe-022/PathInjection.ql b/ruby/ql/src/queries/security/cwe-022/PathInjection.ql index eb52f8e4531..027cf0a33f7 100644 --- a/ruby/ql/src/queries/security/cwe-022/PathInjection.ql +++ b/ruby/ql/src/queries/security/cwe-022/PathInjection.ql @@ -22,5 +22,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is used in a path.", source.getNode(), + "User-provided value" diff --git a/ruby/ql/src/queries/security/cwe-079/ReflectedXSS.ql b/ruby/ql/src/queries/security/cwe-079/ReflectedXSS.ql index 818dee88fe6..2e8d4949b20 100644 --- a/ruby/ql/src/queries/security/cwe-079/ReflectedXSS.ql +++ b/ruby/ql/src/queries/security/cwe-079/ReflectedXSS.ql @@ -20,4 +20,4 @@ import DataFlow::PathGraph from ReflectedXss::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.", - source.getNode(), "a user-provided value" + source.getNode(), "user-provided value" diff --git a/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql b/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql index 0ff8236dee7..4061a7743ec 100644 --- a/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql +++ b/ruby/ql/src/queries/security/cwe-079/StoredXSS.ql @@ -18,5 +18,5 @@ import DataFlow::PathGraph from StoredXss::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@", +select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.", source.getNode(), "stored value" diff --git a/ruby/ql/src/queries/security/cwe-094/CodeInjection.ql b/ruby/ql/src/queries/security/cwe-094/CodeInjection.ql index c3b52409710..66074c408c2 100644 --- a/ruby/ql/src/queries/security/cwe-094/CodeInjection.ql +++ b/ruby/ql/src/queries/security/cwe-094/CodeInjection.ql @@ -22,5 +22,5 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, S where config.hasFlowPath(source, sink) and sourceNode = source.getNode() -select sink.getNode(), source, sink, "This code execution depends on $@.", sourceNode, - "a user-provided value" +select sink.getNode(), source, sink, "$@ flows to here and is interpreted as code.", + source.getNode(), "User-provided value" diff --git a/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.qhelp b/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.qhelp new file mode 100644 index 00000000000..236cadc1742 --- /dev/null +++ b/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.qhelp @@ -0,0 +1,47 @@ + + + + +

+Interpreting hard-coded data (such as string literals containing hexadecimal numbers) +as code or as an import path is typical of malicious backdoor code that has been +implanted into an otherwise trusted code base and is trying to hide its true purpose +from casual readers or automated scanning tools. +

+
+ + +

+Examine the code in question carefully to ascertain its provenance and its true purpose. +If the code is benign, it should always be possible to rewrite it without relying +on dynamically interpreting data as code, improving both clarity and safety. +

+
+ + +

+As an example of malicious code using this obfuscation technique, consider the +following simplified Ruby version of a snippet of backdoor code that was +discovered in a dependency of the popular JavaScript event-stream +npm package: +

+ +

+While this shows only the first few lines of code, it already looks very suspicious +since it takes a hard-coded string literal, hex-decodes it and then uses it as an +import path. The only reason to do so is to hide the name of the file being imported. +

+
+ + +
  • +OWASP: +Trojan Horse. +
  • +
  • +The npm Blog: +Details about the event-stream incident. +
  • +
    + +
    diff --git a/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.ql b/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.ql new file mode 100644 index 00000000000..ead7dbeda08 --- /dev/null +++ b/ruby/ql/src/queries/security/cwe-506/HardcodedDataInterpretedAsCode.ql @@ -0,0 +1,23 @@ +/** + * @name Hard-coded data interpreted as code + * @description Transforming hard-coded data (such as hexadecimal constants) into code + * to be executed is a technique often associated with backdoors and should + * be avoided. + * @kind path-problem + * @problem.severity error + * @security-severity 9.1 + * @precision medium + * @id rb/hardcoded-data-interpreted-as-code + * @tags security + * external/cwe/cwe-506 + */ + +import codeql.ruby.security.HardcodedDataInterpretedAsCodeQuery +import codeql.ruby.DataFlow +import DataFlow::PathGraph + +from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink +where cfg.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "Hard-coded data from $@ is interpreted as " + sink.getNode().(Sink).getKind() + ".", + source.getNode(), "here" diff --git a/ruby/ql/src/queries/security/cwe-506/examples/HardcodedDataInterpretedAsCode.rb b/ruby/ql/src/queries/security/cwe-506/examples/HardcodedDataInterpretedAsCode.rb new file mode 100644 index 00000000000..96f82a6ff1f --- /dev/null +++ b/ruby/ql/src/queries/security/cwe-506/examples/HardcodedDataInterpretedAsCode.rb @@ -0,0 +1,6 @@ +def e(r) + [r].pack 'H*' +end + +# BAD: hexadecimal constant decoded and interpreted as import path +require e("2e2f746573742f64617461") diff --git a/ruby/ql/src/queries/security/cwe-611/Xxe.ql b/ruby/ql/src/queries/security/cwe-611/Xxe.ql index c7eae21333e..8b4edfbee14 100644 --- a/ruby/ql/src/queries/security/cwe-611/Xxe.ql +++ b/ruby/ql/src/queries/security/cwe-611/Xxe.ql @@ -39,5 +39,6 @@ class XxeConfig extends TaintTracking::Configuration { from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf where conf.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Unsafe parsing of XML file from $@.", source.getNode(), - "user input" +select sink.getNode(), source, sink, + "A $@ is parsed as XML without guarding against external entity expansion.", source.getNode(), + "user-provided value" diff --git a/ruby/ql/src/queries/variables/UnusedParameter.ql b/ruby/ql/src/queries/variables/UnusedParameter.ql index 1aa1a6bc462..381d2c77a33 100644 --- a/ruby/ql/src/queries/variables/UnusedParameter.ql +++ b/ruby/ql/src/queries/variables/UnusedParameter.ql @@ -24,4 +24,4 @@ class RelevantParameterVariable extends LocalVariable { from RelevantParameterVariable v where not exists(Ssa::WriteDefinition def | def.getWriteAccess() = v.getDefiningAccess()) -select v, "Unused parameter." +select v, "The parameter '" + v.getName() + "' is never used." diff --git a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected index 77dc81423b2..1c33f59f3c3 100644 --- a/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-022/PathInjection.expected @@ -88,15 +88,15 @@ nodes | tainted_path.rb:60:26:60:29 | path | semmle.label | path | subpaths #select -| ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params : | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | This path depends on $@. | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | a user-provided value | -| ArchiveApiPathTraversal.rb:68:20:68:23 | file | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params : | ArchiveApiPathTraversal.rb:68:20:68:23 | file | This path depends on $@. | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | a user-provided value | -| ArchiveApiPathTraversal.rb:76:19:76:26 | filename | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params : | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | This path depends on $@. | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | a user-provided value | -| tainted_path.rb:5:26:5:29 | path | tainted_path.rb:4:12:4:17 | call to params : | tainted_path.rb:5:26:5:29 | path | This path depends on $@. | tainted_path.rb:4:12:4:17 | call to params | a user-provided value | -| tainted_path.rb:11:26:11:29 | path | tainted_path.rb:10:31:10:36 | call to params : | tainted_path.rb:11:26:11:29 | path | This path depends on $@. | tainted_path.rb:10:31:10:36 | call to params | a user-provided value | -| tainted_path.rb:17:26:17:29 | path | tainted_path.rb:16:28:16:33 | call to params : | tainted_path.rb:17:26:17:29 | path | This path depends on $@. | tainted_path.rb:16:28:16:33 | call to params | a user-provided value | -| tainted_path.rb:23:26:23:29 | path | tainted_path.rb:22:29:22:34 | call to params : | tainted_path.rb:23:26:23:29 | path | This path depends on $@. | tainted_path.rb:22:29:22:34 | call to params | a user-provided value | -| tainted_path.rb:29:26:29:29 | path | tainted_path.rb:28:22:28:27 | call to params : | tainted_path.rb:29:26:29:29 | path | This path depends on $@. | tainted_path.rb:28:22:28:27 | call to params | a user-provided value | -| tainted_path.rb:35:26:35:29 | path | tainted_path.rb:34:29:34:34 | call to params : | tainted_path.rb:35:26:35:29 | path | This path depends on $@. | tainted_path.rb:34:29:34:34 | call to params | a user-provided value | -| tainted_path.rb:41:26:41:29 | path | tainted_path.rb:40:26:40:31 | call to params : | tainted_path.rb:41:26:41:29 | path | This path depends on $@. | tainted_path.rb:40:26:40:31 | call to params | a user-provided value | -| tainted_path.rb:48:26:48:29 | path | tainted_path.rb:47:43:47:48 | call to params : | tainted_path.rb:48:26:48:29 | path | This path depends on $@. | tainted_path.rb:47:43:47:48 | call to params | a user-provided value | -| tainted_path.rb:60:26:60:29 | path | tainted_path.rb:59:40:59:45 | call to params : | tainted_path.rb:60:26:60:29 | path | This path depends on $@. | tainted_path.rb:59:40:59:45 | call to params | a user-provided value | +| ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params : | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | $@ flows to here and is used in a path. | ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | User-provided value | +| ArchiveApiPathTraversal.rb:68:20:68:23 | file | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params : | ArchiveApiPathTraversal.rb:68:20:68:23 | file | $@ flows to here and is used in a path. | ArchiveApiPathTraversal.rb:10:11:10:16 | call to params | User-provided value | +| ArchiveApiPathTraversal.rb:76:19:76:26 | filename | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params : | ArchiveApiPathTraversal.rb:76:19:76:26 | filename | $@ flows to here and is used in a path. | ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | User-provided value | +| tainted_path.rb:5:26:5:29 | path | tainted_path.rb:4:12:4:17 | call to params : | tainted_path.rb:5:26:5:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:4:12:4:17 | call to params | User-provided value | +| tainted_path.rb:11:26:11:29 | path | tainted_path.rb:10:31:10:36 | call to params : | tainted_path.rb:11:26:11:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:10:31:10:36 | call to params | User-provided value | +| tainted_path.rb:17:26:17:29 | path | tainted_path.rb:16:28:16:33 | call to params : | tainted_path.rb:17:26:17:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:16:28:16:33 | call to params | User-provided value | +| tainted_path.rb:23:26:23:29 | path | tainted_path.rb:22:29:22:34 | call to params : | tainted_path.rb:23:26:23:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:22:29:22:34 | call to params | User-provided value | +| tainted_path.rb:29:26:29:29 | path | tainted_path.rb:28:22:28:27 | call to params : | tainted_path.rb:29:26:29:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:28:22:28:27 | call to params | User-provided value | +| tainted_path.rb:35:26:35:29 | path | tainted_path.rb:34:29:34:34 | call to params : | tainted_path.rb:35:26:35:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:34:29:34:34 | call to params | User-provided value | +| tainted_path.rb:41:26:41:29 | path | tainted_path.rb:40:26:40:31 | call to params : | tainted_path.rb:41:26:41:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:40:26:40:31 | call to params | User-provided value | +| tainted_path.rb:48:26:48:29 | path | tainted_path.rb:47:43:47:48 | call to params : | tainted_path.rb:48:26:48:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:47:43:47:48 | call to params | User-provided value | +| tainted_path.rb:60:26:60:29 | path | tainted_path.rb:59:40:59:45 | call to params : | tainted_path.rb:60:26:60:29 | path | $@ flows to here and is used in a path. | tainted_path.rb:59:40:59:45 | call to params | User-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected b/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected index 8f2503c8884..13b94defb24 100644 --- a/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected +++ b/ruby/ql/test/query-tests/security/cwe-079/ReflectedXSS.expected @@ -52,15 +52,15 @@ nodes | app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | semmle.label | ...[...] | subpaths #select -| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params : | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params : | app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params : | app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | Cross-site scripting vulnerability due to $@. | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params | a user-provided value | -| app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params : | app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | Cross-site scripting vulnerability due to $@. | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params | a user-provided value | +| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params : | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params : | app/views/foo/bars/show.html.erb:47:5:47:13 | call to user_name | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:9:12:9:17 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params : | app/views/foo/bars/show.html.erb:51:5:51:18 | call to user_name_memo | Cross-site scripting vulnerability due to $@. | app/controllers/foo/bars_controller.rb:13:20:13:25 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params : | app/views/foo/bars/show.html.erb:54:29:54:44 | ...[...] | Cross-site scripting vulnerability due to $@. | app/views/foo/bars/show.html.erb:54:29:54:34 | call to params | user-provided value | +| app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params : | app/views/foo/bars/show.html.erb:57:13:57:28 | ...[...] | Cross-site scripting vulnerability due to $@. | app/views/foo/bars/show.html.erb:57:13:57:18 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected b/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected index 5d578d84776..fb229fa4bae 100644 --- a/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected +++ b/ruby/ql/test/query-tests/security/cwe-079/StoredXSS.expected @@ -32,15 +32,15 @@ nodes | app/views/foo/stores/show.html.erb:84:5:84:24 | @other_user_raw_name | semmle.label | @other_user_raw_name | subpaths #select -| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | -| app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | Cross-site scripting vulnerability due to $@ | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | stored value | -| app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | Cross-site scripting vulnerability due to $@ | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | stored value | -| app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | Cross-site scripting vulnerability due to $@ | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | stored value | -| app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | Cross-site scripting vulnerability due to $@ | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | stored value | -| app/views/foo/stores/show.html.erb:84:5:84:24 | @other_user_raw_name | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:84:5:84:24 | @other_user_raw_name | Cross-site scripting vulnerability due to $@ | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | stored value | +| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:5:9:5:36 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:9:9:9:26 | ...[...] | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:33:3:33:14 | call to display_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read : | app/views/foo/stores/show.html.erb:38:3:38:16 | @instance_text | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | stored value | +| app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:47:5:47:16 | call to handle | stored value | +| app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:50:5:50:18 | call to raw_name | stored value | +| app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:64:3:64:18 | call to handle | stored value | +| app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | Stored cross-site scripting vulnerability due to $@. | app/views/foo/stores/show.html.erb:70:3:70:20 | call to raw_name | stored value | +| app/views/foo/stores/show.html.erb:84:5:84:24 | @other_user_raw_name | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name : | app/views/foo/stores/show.html.erb:84:5:84:24 | @other_user_raw_name | Stored cross-site scripting vulnerability due to $@. | app/controllers/foo/stores_controller.rb:12:28:12:48 | call to raw_name | stored value | diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected index 5e32af975dc..d48f34aaa22 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected @@ -20,10 +20,10 @@ nodes | CodeInjection.rb:36:24:36:27 | code : | semmle.label | code : | subpaths #select -| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | -| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on $@. | CodeInjection.rb:9:10:9:15 | call to params | a user-provided value | -| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | -| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | -| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | -| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | -| CodeInjection.rb:36:10:36:28 | call to escape | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:36:10:36:28 | call to escape | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value | +| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | +| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | $@ flows to here and is interpreted as code. | CodeInjection.rb:9:10:9:15 | call to params | User-provided value | +| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | +| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | +| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | +| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | +| CodeInjection.rb:36:10:36:28 | call to escape | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:36:10:36:28 | call to escape | $@ flows to here and is interpreted as code. | CodeInjection.rb:3:12:3:17 | call to params | User-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected new file mode 100644 index 00000000000..0d74b778a18 --- /dev/null +++ b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.expected @@ -0,0 +1,29 @@ +edges +| tst.rb:1:7:1:7 | r : | tst.rb:2:4:2:4 | r : | +| tst.rb:2:4:2:4 | r : | tst.rb:2:3:2:15 | call to pack : | +| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | tst.rb:7:8:7:30 | totally_harmless_string : | +| tst.rb:7:8:7:30 | totally_harmless_string : | tst.rb:1:7:1:7 | r : | +| tst.rb:7:8:7:30 | totally_harmless_string : | tst.rb:7:6:7:31 | call to e | +| tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:1:7:1:7 | r : | +| tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:10:9:10:25 | call to e | +| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | tst.rb:17:6:17:32 | another_questionable_string : | +| tst.rb:17:6:17:32 | another_questionable_string : | tst.rb:17:6:17:38 | call to strip | +nodes +| tst.rb:1:7:1:7 | r : | semmle.label | r : | +| tst.rb:2:3:2:15 | call to pack : | semmle.label | call to pack : | +| tst.rb:2:4:2:4 | r : | semmle.label | r : | +| tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | semmle.label | "707574732822636f646520696e6a6..." : | +| tst.rb:7:6:7:31 | call to e | semmle.label | call to e | +| tst.rb:7:8:7:30 | totally_harmless_string : | semmle.label | totally_harmless_string : | +| tst.rb:10:9:10:25 | call to e | semmle.label | call to e | +| tst.rb:10:11:10:24 | "666f6f626172" : | semmle.label | "666f6f626172" : | +| tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | semmle.label | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | +| tst.rb:17:6:17:32 | another_questionable_string : | semmle.label | another_questionable_string : | +| tst.rb:17:6:17:38 | call to strip | semmle.label | call to strip | +subpaths +| tst.rb:7:8:7:30 | totally_harmless_string : | tst.rb:1:7:1:7 | r : | tst.rb:2:3:2:15 | call to pack : | tst.rb:7:6:7:31 | call to e | +| tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:1:7:1:7 | r : | tst.rb:2:3:2:15 | call to pack : | tst.rb:10:9:10:25 | call to e | +#select +| tst.rb:7:6:7:31 | call to e | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." : | tst.rb:7:6:7:31 | call to e | Hard-coded data from $@ is interpreted as code. | tst.rb:5:27:5:72 | "707574732822636f646520696e6a6..." | here | +| tst.rb:10:9:10:25 | call to e | tst.rb:10:11:10:24 | "666f6f626172" : | tst.rb:10:9:10:25 | call to e | Hard-coded data from $@ is interpreted as an import path. | tst.rb:10:11:10:24 | "666f6f626172" | here | +| tst.rb:17:6:17:38 | call to strip | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." : | tst.rb:17:6:17:38 | call to strip | Hard-coded data from $@ is interpreted as code. | tst.rb:16:31:16:84 | "\\x70\\x75\\x74\\x73\\x28\\x27\\x68\\..." | here | diff --git a/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.qlref b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.qlref new file mode 100644 index 00000000000..afa4fec282c --- /dev/null +++ b/ruby/ql/test/query-tests/security/cwe-506/HardcodedDataInterpretedAsCode.qlref @@ -0,0 +1 @@ +queries/security/cwe-506/HardcodedDataInterpretedAsCode.ql diff --git a/ruby/ql/test/query-tests/security/cwe-506/tst.rb b/ruby/ql/test/query-tests/security/cwe-506/tst.rb new file mode 100644 index 00000000000..67d117e95c4 --- /dev/null +++ b/ruby/ql/test/query-tests/security/cwe-506/tst.rb @@ -0,0 +1,18 @@ +def e(r) + [r].pack 'H*' +end + +totally_harmless_string = '707574732822636f646520696e6a656374696f6e2229' + +eval(e(totally_harmless_string)) # NOT OK: eval("puts('hello'") +eval(totally_harmless_string) # OK: throws parse error + +require e('666f6f626172') # NOT OK: require 'foobar' +require '666f6f626172' # OK: no taint step between source and sink + +x = 'deadbeef' +require e(x) # OK: doesn't meet our criteria for being a source + +another_questionable_string = "\x70\x75\x74\x73\x28\x27\x68\x65\x6C\x6C\x6F\x27\x29" +eval(another_questionable_string.strip) # NOT OK: eval("puts('hello'") +eval(another_questionable_string) # OK: no taint step between source and sink diff --git a/ruby/ql/test/query-tests/security/cwe-611/Xxe.expected b/ruby/ql/test/query-tests/security/cwe-611/Xxe.expected index 44732d9a7a7..014aaeef477 100644 --- a/ruby/ql/test/query-tests/security/cwe-611/Xxe.expected +++ b/ruby/ql/test/query-tests/security/cwe-611/Xxe.expected @@ -54,26 +54,26 @@ nodes | Nokogiri.rb:28:26:28:32 | content | semmle.label | content | subpaths #select -| LibXmlRuby.rb:4:34:4:40 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:4:34:4:40 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:5:32:5:38 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:5:32:5:38 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:6:30:6:36 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:6:30:6:36 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:7:32:7:38 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:7:32:7:38 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:8:30:8:36 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:8:30:8:36 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:9:28:9:34 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:9:28:9:34 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:11:26:11:32 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:11:26:11:32 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| LibXmlRuby.rb:12:24:12:30 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:12:24:12:30 | content | Unsafe parsing of XML file from $@. | LibXmlRuby.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:5:26:5:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:5:26:5:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:6:26:6:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:6:26:6:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:7:26:7:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:7:26:7:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:8:26:8:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:8:26:8:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:9:26:9:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:9:26:9:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:11:26:11:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:11:26:11:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:12:26:12:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:12:26:12:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:15:26:15:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:15:26:15:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:16:26:16:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:16:26:16:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:18:26:18:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:18:26:18:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:19:26:19:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:19:26:19:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:22:26:22:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:22:26:22:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:25:26:25:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:25:26:25:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:27:26:27:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:27:26:27:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | -| Nokogiri.rb:28:26:28:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:28:26:28:32 | content | Unsafe parsing of XML file from $@. | Nokogiri.rb:3:15:3:20 | call to params | user input | +| LibXmlRuby.rb:4:34:4:40 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:4:34:4:40 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:5:32:5:38 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:5:32:5:38 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:6:30:6:36 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:6:30:6:36 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:7:32:7:38 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:7:32:7:38 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:8:30:8:36 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:8:30:8:36 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:9:28:9:34 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:9:28:9:34 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:11:26:11:32 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:11:26:11:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| LibXmlRuby.rb:12:24:12:30 | content | LibXmlRuby.rb:3:15:3:20 | call to params : | LibXmlRuby.rb:12:24:12:30 | content | A $@ is parsed as XML without guarding against external entity expansion. | LibXmlRuby.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:5:26:5:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:5:26:5:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:6:26:6:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:6:26:6:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:7:26:7:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:7:26:7:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:8:26:8:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:8:26:8:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:9:26:9:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:9:26:9:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:11:26:11:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:11:26:11:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:12:26:12:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:12:26:12:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:15:26:15:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:15:26:15:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:16:26:16:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:16:26:16:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:18:26:18:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:18:26:18:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:19:26:19:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:19:26:19:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:22:26:22:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:22:26:22:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:25:26:25:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:25:26:25:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:27:26:27:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:27:26:27:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | +| Nokogiri.rb:28:26:28:32 | content | Nokogiri.rb:3:15:3:20 | call to params : | Nokogiri.rb:28:26:28:32 | content | A $@ is parsed as XML without guarding against external entity expansion. | Nokogiri.rb:3:15:3:20 | call to params | user-provided value | diff --git a/swift/codegen/generators/qlgen.py b/swift/codegen/generators/qlgen.py index 38c9ee4145d..7305651fd89 100755 --- a/swift/codegen/generators/qlgen.py +++ b/swift/codegen/generators/qlgen.py @@ -1,5 +1,24 @@ -#!/usr/bin/env python3 -# TODO this should probably be split in different generators now: ql, qltest, maybe qlipa +""" +QL code generation + +`generate(opts, renderer)` will generate in the library directory: + * generated/Raw.qll with thin class wrappers around DB types + * generated/Synth.qll with the base algebraic datatypes for AST entities + * generated//.qll with generated properties for each class + * if not already modified, a elements//.qll stub to customize the above classes + * elements.qll importing all the above stubs + * if not already modified, a elements//Constructor.qll stub to customize the algebraic datatype + characteristic predicate + * generated/SynthConstructors.qll importing all the above constructor stubs + * generated/PureSynthConstructors.qll importing constructor stubs for pure synthesized types (that is, not + corresponding to raw types) +Moreover in the test directory for each in it will generate beneath the +extractor-tests/generated// directory either + * a `MISSING_SOURCE.txt` explanation file if no `swift` source is present, or + * one `.ql` test query for all single properties and on `_.ql` test query for each optional or + repeated property +""" +# TODO this should probably be split in different generators now: ql, qltest, maybe qlsynth import logging import pathlib @@ -29,11 +48,15 @@ class ModifiedStubMarkedAsGeneratedError(Error): pass -def get_ql_property(cls: schema.Class, prop: schema.Property) -> ql.Property: +class RootElementHasChildren(Error): + pass + + +def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str = "") -> ql.Property: args = dict( type=prop.type if not prop.is_predicate else "predicate", qltest_skip="qltest_skip" in prop.pragmas, - is_child=prop.is_child, + prev_child=prev_child if prop.is_child else None, is_optional=prop.is_optional, is_predicate=prop.is_predicate, ) @@ -69,11 +92,18 @@ def get_ql_property(cls: schema.Class, prop: schema.Property) -> ql.Property: def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]): pragmas = {k: True for k in cls.pragmas if k.startswith("ql")} + prev_child = "" + properties = [] + for p in cls.properties: + prop = get_ql_property(cls, p, prev_child) + if prop.is_child: + prev_child = prop.singular + properties.append(prop) return ql.Class( name=cls.name, bases=cls.bases, final=not cls.derived, - properties=[get_ql_property(cls, p) for p in cls.properties], + properties=properties, dir=cls.dir, ipa=bool(cls.ipa), **pragmas, @@ -116,14 +146,14 @@ def get_import(file: pathlib.Path, swift_dir: pathlib.Path): return str(stem).replace("/", ".") -def get_types_used_by(cls: ql.Class): +def get_types_used_by(cls: ql.Class) -> typing.Iterable[str]: for b in cls.bases: - yield b + yield b.base for p in cls.properties: yield p.type -def get_classes_used_by(cls: ql.Class): +def get_classes_used_by(cls: ql.Class) -> typing.List[str]: return sorted(set(t for t in get_types_used_by(cls) if t[0].isupper())) @@ -227,10 +257,15 @@ def generate(opts, renderer): data = schema.load(input) classes = {name: get_ql_class(cls, data.classes) for name, cls in data.classes.items()} + # element root is absent in tests + if schema.root_class_name in classes and classes[schema.root_class_name].has_children: + raise RootElementHasChildren + imports = {} inheritance_graph = {name: cls.bases for name, cls in data.classes.items()} - db_classes = [classes[name] for name in toposort_flatten(inheritance_graph) if not classes[name].ipa] + toposorted_names = toposort_flatten(inheritance_graph) + db_classes = [classes[name] for name in toposorted_names if not classes[name].ipa] renderer.render(ql.DbClasses(db_classes), out / "Raw.qll") classes_by_dir_and_name = sorted(classes.values(), key=lambda cls: (cls.dir, cls.name)) @@ -251,7 +286,8 @@ def generate(opts, renderer): include_file = stub_out.with_suffix(".qll") renderer.render(ql.ImportList(list(imports.values())), include_file) - renderer.render(ql.GetParentImplementation(classes_by_dir_and_name), out / 'GetImmediateParent.qll') + toposorted_classes = [classes[name] for name in toposorted_names] + renderer.render(ql.GetParentImplementation(toposorted_classes), out / 'ParentChild.qll') for c in data.classes.values(): if _should_skip_qltest(c, data.classes): diff --git a/swift/codegen/lib/ql.py b/swift/codegen/lib/ql.py index f862d29fdc3..f9e95e3280e 100644 --- a/swift/codegen/lib/ql.py +++ b/swift/codegen/lib/ql.py @@ -14,6 +14,7 @@ left behind and must be dealt with by hand. import pathlib from dataclasses import dataclass, field +import itertools from typing import List, ClassVar, Union, Optional import inflection @@ -35,7 +36,7 @@ class Property: first: bool = False is_optional: bool = False is_predicate: bool = False - is_child: bool = False + prev_child: Optional[str] = None qltest_skip: bool = False def __post_init__(self): @@ -65,13 +66,26 @@ class Property: def is_single(self): return not (self.is_optional or self.is_repeated or self.is_predicate) + @property + def is_child(self): + return self.prev_child is not None + + +@dataclass +class Base: + base: str + prev: str = "" + + def __str__(self): + return self.base + @dataclass class Class: template: ClassVar = 'ql_class' name: str - bases: List[str] = field(default_factory=list) + bases: List[Base] = field(default_factory=list) final: bool = False properties: List[Property] = field(default_factory=list) dir: pathlib.Path = pathlib.Path() @@ -82,7 +96,8 @@ class Class: ipa: bool = False def __post_init__(self): - self.bases = sorted(self.bases) + bases = sorted(str(b) for b in self.bases) + self.bases = [Base(str(b), prev) for b, prev in zip(bases, itertools.chain([""], bases))] if self.properties: self.properties[0].first = True @@ -95,9 +110,17 @@ class Class: return self.dir / self.name @property - def db_id(self): + def db_id(self) -> str: return "@" + inflection.underscore(self.name) + @property + def has_children(self) -> bool: + return any(p.is_child for p in self.properties) + + @property + def last_base(self) -> str: + return self.bases[-1].base if self.bases else "" + @dataclass class Stub: diff --git a/swift/codegen/schema.yml b/swift/codegen/schema.yml index 8cf2c8f0f25..02007f6e416 100644 --- a/swift/codegen/schema.yml +++ b/swift/codegen/schema.yml @@ -80,8 +80,8 @@ AstNode: Callable: _children: - params: ParamDecl* self_param: ParamDecl? + params: ParamDecl* body: BraceStmt? ConditionElement: @@ -545,7 +545,7 @@ RebindSelfInConstructorExpr: _extends: Expr _children: sub_expr: Expr - self: VarDecl + self: VarDecl SequenceExpr: _extends: Expr @@ -1121,6 +1121,8 @@ ModuleDecl: _extends: TypeDecl is_builtin_module: predicate is_system_module: predicate + imported_modules: ModuleDecl* + exported_modules: ModuleDecl* ConstructorRefCallExpr: _extends: SelfApplyExpr diff --git a/swift/codegen/templates/ql_parent.mustache b/swift/codegen/templates/ql_parent.mustache index d13a47a8ae4..2182d86e6f0 100644 --- a/swift/codegen/templates/ql_parent.mustache +++ b/swift/codegen/templates/ql_parent.mustache @@ -2,33 +2,88 @@ import codeql.swift.elements -/** - * Gets any of the "immediate" children of `e`. "Immediate" means not taking into account node resolution: for example - * if the AST child is the first of a series of conversions that would normally be hidden away, this will select the - * next conversion down the hidden AST tree instead of the corresponding fully uncoverted node at the bottom. - * Outside this module this file is mainly intended to be used to test uniqueness of parents. - */ +private module Impl { +{{#classes}} + private Element getImmediateChildOf{{name}}({{name}} e, int index, string partialPredicateCall) { + {{! avoid unused argument warnings on root element, assuming the root element has no children }} + {{#root}}none(){{/root}} + {{^root}} + {{! b is the base offset 0, for ease of generation }} + {{! b is constructed to be strictly greater than the indexes required for children coming from }} + {{! n is the base offset for direct children, equal to the last base offset from above }} + {{! n is constructed to be strictly greater than the indexes for children }} + exists(int b{{#bases}}, int b{{.}}{{/bases}}, int n{{#properties}}{{#is_child}}, int n{{singular}}{{/is_child}}{{/properties}} | + b = 0 + {{#bases}} + and + b{{.}} = b{{prev}} + 1 + max(int i | i = -1 or exists(getImmediateChildOf{{.}}(e, i, _)) | i) + {{/bases}} + and + n = b{{last_base}} + {{#properties}} + {{#is_child}} + {{! n is defined on top of the previous definition }} + {{! for single and optional properties it adds 1 (regardless of whether the optional property exists) }} + {{! for repeated it adds 1 + the maximum index (which works for repeated optional as well) }} + and + n{{singular}} = n{{prev_child}} + 1{{#is_repeated}}+ max(int i | i = -1 or exists(e.getImmediate{{singular}}(i)) | i){{/is_repeated}} + {{/is_child}} + {{/properties}} and ( + none() + {{#bases}} + or + result = getImmediateChildOf{{.}}(e, index - b{{prev}}, partialPredicateCall) + {{/bases}} + {{#properties}} + {{#is_child}} + or + {{#is_repeated}} + result = e.getImmediate{{singular}}(index - n{{prev_child}}) and partialPredicateCall = "{{singular}}(" + (index - n{{prev_child}}).toString() + ")" + {{/is_repeated}} + {{^is_repeated}} + index = n{{prev_child}} and result = e.getImmediate{{singular}}() and partialPredicateCall = "{{singular}}()" + {{/is_repeated}} + {{/is_child}} + {{/properties}} + )) + {{/root}} + } + +{{/classes}} cached -Element getAnImmediateChild(Element e) { - // why does this look more complicated than it should? - // * none() simplifies generation, as we can append `or ...` without a special case for the first item - none() - {{#classes}} - {{#properties}} - {{#is_child}} - or - result = e.({{name}}).getImmediate{{singular}}({{#is_repeated}}_{{/is_repeated}}) - {{/is_child}} - {{/properties}} - {{/classes}} +Element getImmediateChild(Element e, int index, string partialAccessor) { +// why does this look more complicated than it should? +// * none() simplifies generation, as we can append `or ...` without a special case for the first item +none() +{{#classes}} + {{#final}} + or + result = getImmediateChildOf{{name}}(e, index, partialAccessor) + {{/final}} +{{/classes}} +} } /** - * Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example - * if `e` has conversions, `getImmediateParent(e)` will give the bottom conversion in the hidden AST. - */ - Element getImmediateParent(Element e) { - // `unique` is used here to tell the optimizer that there is in fact only one result - // this is tested by the `library-tests/parent/no_double_parents.ql` test - result = unique(Element x | e = getAnImmediateChild(x) | x) +* Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example +* if `e` has conversions, `getImmediateParent(e)` will give the innermost conversion in the hidden AST. +*/ +Element getImmediateParent(Element e) { +// `unique` is used here to tell the optimizer that there is in fact only one result +// this is tested by the `library-tests/parent/no_double_parents.ql` test +result = unique(Element x | e = Impl::getImmediateChild(x, _, _) | x) +} + +/** +* Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. +*/ +Element getImmediateChildAndAccessor(Element e, int index, string accessor) { +exists(string partialAccessor | result = Impl::getImmediateChild(e, index, partialAccessor) and accessor = "getImmediate" + partialAccessor) +} + +/** +* Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. +*/ +Element getChildAndAccessor(Element e, int index, string accessor) { +exists(string partialAccessor | result = Impl::getImmediateChild(e, index, partialAccessor).resolve() and accessor = "get" + partialAccessor) } diff --git a/swift/codegen/test/test_ql.py b/swift/codegen/test/test_ql.py index 14d555fee03..babaf7238fc 100644 --- a/swift/codegen/test/test_ql.py +++ b/swift/codegen/test/test_ql.py @@ -78,9 +78,9 @@ def test_property_predicate_getter(): assert prop.getter == "prop" -def test_class_sorts_bases(): +def test_class_processes_bases(): bases = ["B", "Ab", "C", "Aa"] - expected = ["Aa", "Ab", "B", "C"] + expected = [ql.Base("Aa"), ql.Base("Ab", prev="Aa"), ql.Base("B", prev="Ab"), ql.Base("C", prev="B")] cls = ql.Class("Foo", bases=bases) assert cls.bases == expected @@ -105,5 +105,27 @@ def test_non_root_class(): assert not cls.root +@pytest.mark.parametrize("prev_child,is_child", [(None, False), ("", True), ("x", True)]) +def test_is_child(prev_child, is_child): + p = ql.Property("Foo", "int", prev_child=prev_child) + assert p.is_child is is_child + + +def test_empty_class_no_children(): + cls = ql.Class("Class", properties=[]) + assert cls.has_children is False + + +def test_class_no_children(): + cls = ql.Class("Class", properties=[ql.Property("Foo", "int"), ql.Property("Bar", "string")]) + assert cls.has_children is False + + +def test_class_with_children(): + cls = ql.Class("Class", properties=[ql.Property("Foo", "int"), ql.Property("Child", "x", prev_child=""), + ql.Property("Bar", "string")]) + assert cls.has_children is True + + if __name__ == '__main__': sys.exit(pytest.main([__file__] + sys.argv[1:])) diff --git a/swift/codegen/test/test_qlgen.py b/swift/codegen/test/test_qlgen.py index 410c65c4479..53a508467f2 100644 --- a/swift/codegen/test/test_qlgen.py +++ b/swift/codegen/test/test_qlgen.py @@ -29,7 +29,7 @@ def ql_test_output_path(): return paths.swift_dir / "ql/test/path" def import_file(): return stub_path().with_suffix(".qll") -def children_file(): return ql_output_path() / "GetImmediateParent.qll" +def children_file(): return ql_output_path() / "ParentChild.qll" stub_import_prefix = "stub.path." @@ -207,6 +207,42 @@ def test_single_property(generate_classes): } +def test_children(generate_classes): + assert generate_classes([ + schema.Class("MyObject", properties=[ + schema.SingleProperty("a", "int"), + schema.SingleProperty("child1", "int", is_child=True), + schema.RepeatedProperty("b", "int"), + schema.RepeatedProperty("child2", "int", is_child=True), + schema.OptionalProperty("c", "int"), + schema.OptionalProperty("child3", "int", is_child=True), + schema.RepeatedOptionalProperty("d", "int"), + schema.RepeatedOptionalProperty("child4", "int", is_child=True), + ]), + ]) == { + "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + ql.Class(name="MyObject", final=True, + properties=[ + ql.Property(singular="A", type="int", tablename="my_objects", + tableparams=["this", "result", "_"]), + ql.Property(singular="Child1", type="int", tablename="my_objects", + tableparams=["this", "_", "result"], prev_child=""), + ql.Property(singular="B", plural="Bs", type="int", tablename="my_object_bs", + tableparams=["this", "index", "result"]), + ql.Property(singular="Child2", plural="Child2s", type="int", tablename="my_object_child2s", + tableparams=["this", "index", "result"], prev_child="Child1"), + ql.Property(singular="C", type="int", tablename="my_object_cs", + tableparams=["this", "result"], is_optional=True), + ql.Property(singular="Child3", type="int", tablename="my_object_child3s", + tableparams=["this", "result"], is_optional=True, prev_child="Child2"), + ql.Property(singular="D", plural="Ds", type="int", tablename="my_object_ds", + tableparams=["this", "index", "result"], is_optional=True), + ql.Property(singular="Child4", plural="Child4s", type="int", tablename="my_object_child4s", + tableparams=["this", "index", "result"], is_optional=True, prev_child="Child3"), + ])), + } + + def test_single_properties(generate_classes): assert generate_classes([ schema.Class("MyObject", properties=[ @@ -228,8 +264,8 @@ def test_single_properties(generate_classes): } -@pytest.mark.parametrize("is_child", [False, True]) -def test_optional_property(generate_classes, is_child): +@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) +def test_optional_property(generate_classes, is_child, prev_child): assert generate_classes([ schema.Class("MyObject", properties=[ schema.OptionalProperty("foo", "bar", is_child=is_child)]), @@ -238,13 +274,13 @@ def test_optional_property(generate_classes, is_child): ql.Class(name="MyObject", final=True, properties=[ ql.Property(singular="Foo", type="bar", tablename="my_object_foos", tableparams=["this", "result"], - is_optional=True, is_child=is_child), + is_optional=True, prev_child=prev_child), ])), } -@pytest.mark.parametrize("is_child", [False, True]) -def test_repeated_property(generate_classes, is_child): +@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) +def test_repeated_property(generate_classes, is_child, prev_child): assert generate_classes([ schema.Class("MyObject", properties=[ schema.RepeatedProperty("foo", "bar", is_child=is_child)]), @@ -252,13 +288,13 @@ def test_repeated_property(generate_classes, is_child): "MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), ql.Class(name="MyObject", final=True, properties=[ ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", - tableparams=["this", "index", "result"], is_child=is_child), + tableparams=["this", "index", "result"], prev_child=prev_child), ])), } -@pytest.mark.parametrize("is_child", [False, True]) -def test_repeated_optional_property(generate_classes, is_child): +@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) +def test_repeated_optional_property(generate_classes, is_child, prev_child): assert generate_classes([ schema.Class("MyObject", properties=[ schema.RepeatedOptionalProperty("foo", "bar", is_child=is_child)]), @@ -267,7 +303,7 @@ def test_repeated_optional_property(generate_classes, is_child): ql.Class(name="MyObject", final=True, properties=[ ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", tableparams=["this", "index", "result"], is_optional=True, - is_child=is_child), + prev_child=prev_child), ])), } @@ -286,8 +322,8 @@ def test_predicate_property(generate_classes): } -@pytest.mark.parametrize("is_child", [False, True]) -def test_single_class_property(generate_classes, is_child): +@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) +def test_single_class_property(generate_classes, is_child, prev_child): assert generate_classes([ schema.Class("MyObject", properties=[ schema.SingleProperty("foo", "Bar", is_child=is_child)]), @@ -299,7 +335,7 @@ def test_single_class_property(generate_classes, is_child): ql.Property(singular="Foo", type="Bar", tablename="my_objects", tableparams=[ "this", "result"], - is_child=is_child), + prev_child=prev_child), ], )), "Bar.qll": (ql.Stub(name="Bar", base_import=gen_import_prefix + "Bar"), @@ -321,6 +357,13 @@ def test_class_dir(generate_classes): } +def test_root_element_cannot_have_children(generate_classes): + with pytest.raises(qlgen.RootElementHasChildren): + generate_classes([ + schema.Class(schema.root_class_name, properties=[schema.SingleProperty("x", is_child=True)]) + ]) + + def test_class_dir_imports(generate_import_list): dir = pathlib.Path("another/rel/path") assert generate_import_list([ diff --git a/swift/extractor/SwiftBuiltinSymbols.h b/swift/extractor/SwiftBuiltinSymbols.h new file mode 100644 index 00000000000..6e912792da2 --- /dev/null +++ b/swift/extractor/SwiftBuiltinSymbols.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +namespace codeql { +constexpr std::array swiftBuiltins = { + "zeroInitializer", + "BridgeObject", + "Word", + "NativeObject", + "RawPointer", + "Executor", + "Job", + "RawUnsafeContinuation", + "addressof", + "initialize", + "reinterpretCast", + "Int1", + "Int8", + "Int16", + "Int32", + "Int64", + "IntLiteral", + "FPIEEE16", + "FPIEEE32", + "FPIEEE64", + "FPIEEE80", + "Vec2xInt8", + "Vec4xInt8", + "Vec8xInt8", + "Vec16xInt8", + "Vec32xInt8", + "Vec64xInt8", + "Vec2xInt16", + "Vec4xInt16", + "Vec8xInt16", + "Vec16xInt16", + "Vec32xInt16", + "Vec64xInt16", + "Vec2xInt32", + "Vec4xInt32", + "Vec8xInt32", + "Vec16xInt32", + "Vec32xInt32", + "Vec64xInt32", + "Vec2xInt64", + "Vec4xInt64", + "Vec8xInt64", + "Vec16xInt64", + "Vec32xInt64", + "Vec64xInt64", + "Vec2xFPIEEE16", + "Vec4xFPIEEE16", + "Vec8xFPIEEE16", + "Vec16xFPIEEE16", + "Vec32xFPIEEE16", + "Vec64xFPIEEE16", + "Vec2xFPIEEE32", + "Vec4xFPIEEE32", + "Vec8xFPIEEE32", + "Vec16xFPIEEE32", + "Vec32xFPIEEE32", + "Vec64xFPIEEE32", + "Vec2xFPIEEE64", + "Vec4xFPIEEE64", + "Vec8xFPIEEE64", + "Vec16xFPIEEE64", + "Vec32xFPIEEE64", + "Vec64xFPIEEE64", +}; +} diff --git a/swift/extractor/SwiftExtractor.cpp b/swift/extractor/SwiftExtractor.cpp index ecd94ee2211..c6473eca415 100644 --- a/swift/extractor/SwiftExtractor.cpp +++ b/swift/extractor/SwiftExtractor.cpp @@ -6,15 +6,12 @@ #include #include -#include -#include -#include -#include +#include -#include "swift/extractor/trap/generated/TrapClasses.h" #include "swift/extractor/trap/TrapDomain.h" #include "swift/extractor/visitors/SwiftVisitor.h" #include "swift/extractor/TargetTrapFile.h" +#include "swift/extractor/SwiftBuiltinSymbols.h" using namespace codeql; using namespace std::string_literals; @@ -65,7 +62,40 @@ static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* pri filename += module.getName().str(); return filename; } - return module.getModuleFilename().str(); + if (module.isBuiltinModule()) { + // The Builtin module has an empty filename, let's fix that + return "/__Builtin__"; + } + auto filename = module.getModuleFilename().str(); + // there is a special case of a module without an actual filename reporting ``: in this + // case we want to avoid the `<>` characters, in case a dirty DB is imported on Windows + if (filename == "") { + return "/__imports__"; + } + return filename; +} + +/* The builtin module is special, as it does not publish any top-level declaration + * It creates (and caches) declarations on demand when a lookup is carried out + * (see BuiltinUnit in swift/AST/FileUnit.h for the cache details, and getBuiltinValueDecl in + * swift/AST/Builtins.h for the creation details) + * As we want to create the Builtin trap file once and for all so that it works for other + * extraction runs, rather than collecting what we need we pre-populate the builtin trap with + * what we expect. This list might need thus to be expanded. + * Notice, that while swift/AST/Builtins.def has a list of builtin symbols, it does not contain + * all information required to instantiate builtin variants. + * Other possible approaches: + * * create one trap per builtin declaration when encountered + * * expand the list to all possible builtins (of which there are a lot) + */ +static void getBuiltinDecls(swift::ModuleDecl& builtinModule, + llvm::SmallVector& decls) { + llvm::SmallVector values; + for (auto symbol : swiftBuiltins) { + builtinModule.lookupValue(builtinModule.getASTContext().getIdentifier(symbol), + swift::NLKind::QualifiedLookup, values); + } + decls.insert(decls.end(), values.begin(), values.end()); } static llvm::SmallVector getTopLevelDecls(swift::ModuleDecl& module, @@ -74,16 +104,19 @@ static llvm::SmallVector getTopLevelDecls(swift::ModuleDecl& modul ret.push_back(&module); if (primaryFile) { primaryFile->getTopLevelDecls(ret); + } else if (module.isBuiltinModule()) { + getBuiltinDecls(module, ret); } else { module.getTopLevelDecls(ret); } return ret; } -static void extractDeclarations(const SwiftExtractorConfiguration& config, - swift::CompilerInstance& compiler, - swift::ModuleDecl& module, - swift::SourceFile* primaryFile = nullptr) { +static std::unordered_set extractDeclarations( + const SwiftExtractorConfiguration& config, + swift::CompilerInstance& compiler, + swift::ModuleDecl& module, + swift::SourceFile* primaryFile = nullptr) { auto filename = getFilename(module, primaryFile); // The extractor can be called several times from different processes with @@ -92,7 +125,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config, auto trapTarget = createTargetTrapFile(config, filename); if (!trapTarget) { // another process arrived first, nothing to do for us - return; + return {}; } TrapDomain trap{*trapTarget}; @@ -116,6 +149,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config, for (auto& comment : comments) { visitor.extract(comment); } + return std::move(visitor).getEncounteredModules(); } static std::unordered_set collectInputFilenames(swift::CompilerInstance& compiler) { @@ -132,40 +166,27 @@ static std::unordered_set collectInputFilenames(swift::CompilerInst return sourceFiles; } -static std::unordered_set collectModules(swift::CompilerInstance& compiler) { - // getASTContext().getLoadedModules() does not provide all the modules available within the - // program. - // We need to iterate over all the imported modules (recursively) to see the whole "universe." - std::unordered_set allModules; - std::queue worklist; - for (auto& [_, module] : compiler.getASTContext().getLoadedModules()) { - worklist.push(module); - allModules.insert(module); +static std::vector collectLoadedModules(swift::CompilerInstance& compiler) { + std::vector ret; + for (const auto& [id, module] : compiler.getASTContext().getLoadedModules()) { + std::ignore = id; + ret.push_back(module); } - - while (!worklist.empty()) { - auto module = worklist.front(); - worklist.pop(); - llvm::SmallVector importedModules; - // TODO: we may need more than just Exported ones - module->getImportedModules(importedModules, swift::ModuleDecl::ImportFilterKind::Exported); - for (auto& imported : importedModules) { - if (allModules.count(imported.importedModule) == 0) { - worklist.push(imported.importedModule); - allModules.insert(imported.importedModule); - } - } - } - return allModules; + return ret; } void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config, swift::CompilerInstance& compiler) { auto inputFiles = collectInputFilenames(compiler); - auto modules = collectModules(compiler); + std::vector todo = collectLoadedModules(compiler); + std::unordered_set seen{todo.begin(), todo.end()}; - for (auto& module : modules) { + while (!todo.empty()) { + auto module = todo.back(); + todo.pop_back(); + llvm::errs() << "processing module " << module->getName() << '\n'; bool isFromSourceFile = false; + std::unordered_set encounteredModules; for (auto file : module->getFiles()) { auto sourceFile = llvm::dyn_cast(file); if (!sourceFile) { @@ -176,10 +197,16 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config, continue; } archiveFile(config, *sourceFile); - extractDeclarations(config, compiler, *module, sourceFile); + encounteredModules = extractDeclarations(config, compiler, *module, sourceFile); } if (!isFromSourceFile) { - extractDeclarations(config, compiler, *module); + encounteredModules = extractDeclarations(config, compiler, *module); + } + for (auto encountered : encounteredModules) { + if (seen.count(encountered) == 0) { + todo.push_back(encountered); + seen.insert(encountered); + } } } } diff --git a/swift/extractor/infra/SwiftDispatcher.h b/swift/extractor/infra/SwiftDispatcher.h index 44424d6f89e..4f8ad7569a7 100644 --- a/swift/extractor/infra/SwiftDispatcher.h +++ b/swift/extractor/infra/SwiftDispatcher.h @@ -55,6 +55,10 @@ class SwiftDispatcher { } } + const std::unordered_set getEncounteredModules() && { + return std::move(encounteredModules); + } + template void emit(const Entry& entry) { trap.emit(entry); @@ -228,8 +232,16 @@ class SwiftDispatcher { // - extracting a primary source file: in this mode, we extract several files belonging to the // same module one by one. In this mode, we restrict emission only to the same file ignoring // all the other files. + // This is also used to register the modules we encounter. + // TODO calls to this function should be taken away from `DeclVisitor` and moved around with a + // clearer separation between naming entities (some decls, all types), deciding whether to emit + // them and finally visiting emitting the contents of the entity (which should remain in the + // visitors). Then this double responsibility (carrying out the test and registering encountered + // modules) should also be cleared out bool shouldEmitDeclBody(const swift::Decl& decl) { - if (decl.getModuleContext() != ¤tModule) { + auto module = decl.getModuleContext(); + if (module != ¤tModule) { + encounteredModules.insert(module); return false; } // ModuleDecl is a special case: if it passed the previous test, it is the current module @@ -333,6 +345,7 @@ class SwiftDispatcher { Store::Handle waitingForNewLabel{std::monostate{}}; swift::ModuleDecl& currentModule; swift::SourceFile* currentPrimarySourceFile; + std::unordered_set encounteredModules; }; } // namespace codeql diff --git a/swift/extractor/visitors/DeclVisitor.cpp b/swift/extractor/visitors/DeclVisitor.cpp index 1f188406987..62e1fdb753a 100644 --- a/swift/extractor/visitors/DeclVisitor.cpp +++ b/swift/extractor/visitors/DeclVisitor.cpp @@ -22,31 +22,31 @@ std::string constructName(const swift::DeclName& declName) { } } // namespace -std::variant -DeclVisitor::translateFuncDecl(const swift::FuncDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateFuncDecl( + const swift::FuncDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillAbstractFunctionDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant -DeclVisitor::translateConstructorDecl(const swift::ConstructorDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateConstructorDecl( + const swift::ConstructorDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillAbstractFunctionDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant -DeclVisitor::translateDestructorDecl(const swift::DestructorDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateDestructorDecl( + const swift::DestructorDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillAbstractFunctionDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } codeql::PrefixOperatorDecl DeclVisitor::translatePrefixOperatorDecl( @@ -124,40 +124,37 @@ std::optional DeclVisitor::translateVarDecl(const swift return entry; } -std::variant DeclVisitor::translateStructDecl( - const swift::StructDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateStructDecl(const swift::StructDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillNominalTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant DeclVisitor::translateClassDecl( - const swift::ClassDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateClassDecl(const swift::ClassDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillNominalTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant DeclVisitor::translateEnumDecl( - const swift::EnumDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateEnumDecl(const swift::EnumDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillNominalTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant DeclVisitor::translateProtocolDecl( +std::optional DeclVisitor::translateProtocolDecl( const swift::ProtocolDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { + if (auto entry = createNamedEntry(decl)) { fillNominalTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } codeql::EnumCaseDecl DeclVisitor::translateEnumCaseDecl(const swift::EnumCaseDecl& decl) { @@ -166,17 +163,18 @@ codeql::EnumCaseDecl DeclVisitor::translateEnumCaseDecl(const swift::EnumCaseDec return entry; } -std::variant -DeclVisitor::translateEnumElementDecl(const swift::EnumElementDecl& decl) { - auto ret = createNamedEntryOr(decl); - std::visit([&](auto& entry) { entry.name = decl.getNameStr().str(); }, ret); - if (auto entry = get_if(&ret)) { - if (decl.hasParameterList()) { - entry->params = dispatcher_.fetchRepeatedLabels(*decl.getParameterList()); - } - fillValueDecl(decl, *entry); +std::optional DeclVisitor::translateEnumElementDecl( + const swift::EnumElementDecl& decl) { + auto entry = createNamedEntry(decl); + if (!entry) { + return std::nullopt; } - return ret; + entry->name = decl.getNameStr().str(); + if (decl.hasParameterList()) { + entry->params = dispatcher_.fetchRepeatedLabels(*decl.getParameterList()); + } + fillValueDecl(decl, *entry); + return entry; } codeql::GenericTypeParamDecl DeclVisitor::translateGenericTypeParamDecl( @@ -187,45 +185,46 @@ codeql::GenericTypeParamDecl DeclVisitor::translateGenericTypeParamDecl( return entry; } -std::variant -DeclVisitor::translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { +std::optional DeclVisitor::translateAssociatedTypeDecl( + const swift::AssociatedTypeDecl& decl) { + if (auto entry = createNamedEntry(decl)) { fillTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant DeclVisitor::translateTypeAliasDecl( +std::optional DeclVisitor::translateTypeAliasDecl( const swift::TypeAliasDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { + if (auto entry = createNamedEntry(decl)) { fillTypeDecl(decl, *entry); + return entry; } - return ret; + return std::nullopt; } -std::variant DeclVisitor::translateAccessorDecl( +std::optional DeclVisitor::translateAccessorDecl( const swift::AccessorDecl& decl) { - auto ret = createNamedEntryOr(decl); - if (auto entry = get_if(&ret)) { - switch (decl.getAccessorKind()) { - case swift::AccessorKind::Get: - entry->is_getter = true; - break; - case swift::AccessorKind::Set: - entry->is_setter = true; - break; - case swift::AccessorKind::WillSet: - entry->is_will_set = true; - break; - case swift::AccessorKind::DidSet: - entry->is_did_set = true; - break; - } - fillAbstractFunctionDecl(decl, *entry); + auto entry = createNamedEntry(decl); + if (!entry) { + return std::nullopt; } - return ret; + switch (decl.getAccessorKind()) { + case swift::AccessorKind::Get: + entry->is_getter = true; + break; + case swift::AccessorKind::Set: + entry->is_setter = true; + break; + case swift::AccessorKind::WillSet: + entry->is_will_set = true; + break; + case swift::AccessorKind::DidSet: + entry->is_did_set = true; + break; + } + fillAbstractFunctionDecl(decl, *entry); + return entry; } std::optional DeclVisitor::translateSubscriptDecl( @@ -265,6 +264,17 @@ std::optional DeclVisitor::translateModuleDecl(const swift:: } entry->is_builtin_module = decl.isBuiltinModule(); entry->is_system_module = decl.isSystemModule(); + using K = swift::ModuleDecl::ImportFilterKind; + llvm::SmallVector imports; + decl.getImportedModules(imports, K::Default); + for (const auto& import : imports) { + entry->imported_modules.push_back(dispatcher_.fetchLabel(import.importedModule)); + } + imports.clear(); + decl.getImportedModules(imports, K::Exported); + for (const auto& import : imports) { + entry->exported_modules.push_back(dispatcher_.fetchLabel(import.importedModule)); + } fillTypeDecl(decl, *entry); return entry; } diff --git a/swift/extractor/visitors/DeclVisitor.h b/swift/extractor/visitors/DeclVisitor.h index 7fe940b985a..fa0012caff0 100644 --- a/swift/extractor/visitors/DeclVisitor.h +++ b/swift/extractor/visitors/DeclVisitor.h @@ -20,12 +20,10 @@ class DeclVisitor : public AstVisitorBase { dispatcher_.emit(translateIfConfigClause(*clause)); } - std::variant translateFuncDecl( - const swift::FuncDecl& decl); - std::variant translateConstructorDecl( + std::optional translateFuncDecl(const swift::FuncDecl& decl); + std::optional translateConstructorDecl( const swift::ConstructorDecl& decl); - std::variant translateDestructorDecl( - const swift::DestructorDecl& decl); + std::optional translateDestructorDecl(const swift::DestructorDecl& decl); codeql::PrefixOperatorDecl translatePrefixOperatorDecl(const swift::PrefixOperatorDecl& decl); codeql::PostfixOperatorDecl translatePostfixOperatorDecl(const swift::PostfixOperatorDecl& decl); codeql::InfixOperatorDecl translateInfixOperatorDecl(const swift::InfixOperatorDecl& decl); @@ -34,25 +32,19 @@ class DeclVisitor : public AstVisitorBase { codeql::TopLevelCodeDecl translateTopLevelCodeDecl(const swift::TopLevelCodeDecl& decl); codeql::PatternBindingDecl translatePatternBindingDecl(const swift::PatternBindingDecl& decl); std::optional translateVarDecl(const swift::VarDecl& decl); - std::variant translateStructDecl( - const swift::StructDecl& decl); - std::variant translateClassDecl( - const swift::ClassDecl& decl); - std::variant translateEnumDecl( - const swift::EnumDecl& decl); - std::variant translateProtocolDecl( - const swift::ProtocolDecl& decl); + std::optional translateStructDecl(const swift::StructDecl& decl); + std::optional translateClassDecl(const swift::ClassDecl& decl); + std::optional translateEnumDecl(const swift::EnumDecl& decl); + std::optional translateProtocolDecl(const swift::ProtocolDecl& decl); codeql::EnumCaseDecl translateEnumCaseDecl(const swift::EnumCaseDecl& decl); - std::variant translateEnumElementDecl( + std::optional translateEnumElementDecl( const swift::EnumElementDecl& decl); codeql::GenericTypeParamDecl translateGenericTypeParamDecl( const swift::GenericTypeParamDecl& decl); - std::variant - translateAssociatedTypeDecl(const swift::AssociatedTypeDecl& decl); - std::variant translateTypeAliasDecl( - const swift::TypeAliasDecl& decl); - std::variant translateAccessorDecl( - const swift::AccessorDecl& decl); + std::optional translateAssociatedTypeDecl( + const swift::AssociatedTypeDecl& decl); + std::optional translateTypeAliasDecl(const swift::TypeAliasDecl& decl); + std::optional translateAccessorDecl(const swift::AccessorDecl& decl); std::optional translateSubscriptDecl(const swift::SubscriptDecl& decl); codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl); codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl); @@ -86,17 +78,6 @@ class DeclVisitor : public AstVisitorBase { return entry; } - template - std::variant, T> createNamedEntryOr(const D& decl) { - auto id = dispatcher_.assignNewLabel(decl, mangledName(decl)); - if (dispatcher_.shouldEmitDeclBody(decl)) { - TrapClassOf entry{id}; - fillDecl(decl, entry); - return entry; - } - return T{id}; - } - template TrapClassOf createEntry(const D& decl) { TrapClassOf entry{dispatcher_.template assignNewLabel(decl)}; diff --git a/swift/extractor/visitors/SwiftVisitor.h b/swift/extractor/visitors/SwiftVisitor.h index f1828c39689..88ac6dc27a0 100644 --- a/swift/extractor/visitors/SwiftVisitor.h +++ b/swift/extractor/visitors/SwiftVisitor.h @@ -11,6 +11,7 @@ namespace codeql { class SwiftVisitor : private SwiftDispatcher { public: + using SwiftDispatcher::getEncounteredModules; using SwiftDispatcher::SwiftDispatcher; template diff --git a/swift/integration-tests/osx-only/frontend-invocations/Makefile b/swift/integration-tests/osx-only/frontend-invocations/Makefile deleted file mode 100644 index a05c5f1e9f8..00000000000 --- a/swift/integration-tests/osx-only/frontend-invocations/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# TODO: Add linux -SDK=$(shell xcrun -show-sdk-path) -FRONTEND=$(shell xcrun -find swift-frontend) - -all: - $(FRONTEND) -frontend -c A.swift -sdk $(SDK) - $(FRONTEND) -frontend -c B.swift -o B.o -sdk $(SDK) - $(FRONTEND) -frontend -c -primary-file C.swift -sdk $(SDK) - $(FRONTEND) -frontend -c -primary-file D.swift -o D.o -sdk $(SDK) - $(FRONTEND) -frontend -c -primary-file E.swift Esup.swift -o E.o -sdk $(SDK) diff --git a/swift/integration-tests/osx-only/frontend-invocations/B.swift b/swift/integration-tests/posix-only/frontend-invocations/A.swift similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/B.swift rename to swift/integration-tests/posix-only/frontend-invocations/A.swift diff --git a/swift/integration-tests/osx-only/frontend-invocations/C.swift b/swift/integration-tests/posix-only/frontend-invocations/B.swift similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/C.swift rename to swift/integration-tests/posix-only/frontend-invocations/B.swift diff --git a/swift/integration-tests/osx-only/frontend-invocations/D.swift b/swift/integration-tests/posix-only/frontend-invocations/C.swift similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/D.swift rename to swift/integration-tests/posix-only/frontend-invocations/C.swift diff --git a/swift/integration-tests/osx-only/frontend-invocations/E.swift b/swift/integration-tests/posix-only/frontend-invocations/D.swift similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/E.swift rename to swift/integration-tests/posix-only/frontend-invocations/D.swift diff --git a/swift/integration-tests/osx-only/frontend-invocations/Esup.swift b/swift/integration-tests/posix-only/frontend-invocations/E.swift similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/Esup.swift rename to swift/integration-tests/posix-only/frontend-invocations/E.swift diff --git a/swift/integration-tests/posix-only/frontend-invocations/Esup.swift b/swift/integration-tests/posix-only/frontend-invocations/Esup.swift new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/integration-tests/osx-only/frontend-invocations/Files.expected b/swift/integration-tests/posix-only/frontend-invocations/Files.expected similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/Files.expected rename to swift/integration-tests/posix-only/frontend-invocations/Files.expected diff --git a/swift/integration-tests/osx-only/frontend-invocations/Files.ql b/swift/integration-tests/posix-only/frontend-invocations/Files.ql similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/Files.ql rename to swift/integration-tests/posix-only/frontend-invocations/Files.ql diff --git a/swift/integration-tests/posix-only/frontend-invocations/Makefile b/swift/integration-tests/posix-only/frontend-invocations/Makefile new file mode 100644 index 00000000000..d3ddece6b9f --- /dev/null +++ b/swift/integration-tests/posix-only/frontend-invocations/Makefile @@ -0,0 +1,15 @@ +OS=$(shell uname) +ifeq ($(OS),Darwin) +SDK=-sdk $(shell xcrun -show-sdk-path) +FRONTEND=$(shell xcrun -find swift-frontend) +else +SDK="" +FRONTEND=swiftc +endif + +all: + $(FRONTEND) -frontend -c A.swift $(SDK) + $(FRONTEND) -frontend -c B.swift -o B.o $(SDK) + $(FRONTEND) -frontend -c -primary-file C.swift $(SDK) + $(FRONTEND) -frontend -c -primary-file D.swift -o D.o $(SDK) + $(FRONTEND) -frontend -c -primary-file E.swift Esup.swift -o E.o $(SDK) diff --git a/swift/integration-tests/osx-only/frontend-invocations/test.py b/swift/integration-tests/posix-only/frontend-invocations/test.py similarity index 100% rename from swift/integration-tests/osx-only/frontend-invocations/test.py rename to swift/integration-tests/posix-only/frontend-invocations/test.py diff --git a/swift/integration-tests/posix-only/partial-modules/Modules.expected b/swift/integration-tests/posix-only/partial-modules/Modules.expected index 3cdcff9b980..7d7000044dc 100644 --- a/swift/integration-tests/posix-only/partial-modules/Modules.expected +++ b/swift/integration-tests/posix-only/partial-modules/Modules.expected @@ -1,5 +1,6 @@ | file://:0:0:0:0 | A | | file://:0:0:0:0 | B | | file://:0:0:0:0 | PackageDescription | +| file://:0:0:0:0 | __ObjC | | file://:0:0:0:0 | main | | file://:0:0:0:0 | partial_modules | diff --git a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll index 1f24e7c7cc7..b74d001cb6a 100644 --- a/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll +++ b/swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll @@ -1,5 +1,5 @@ private import swift -private import codeql.swift.generated.GetImmediateParent +private import codeql.swift.generated.ParentChild private import codeql.swift.generated.Synth module CallableBase { diff --git a/swift/ql/lib/codeql/swift/elements/AstNode.qll b/swift/ql/lib/codeql/swift/elements/AstNode.qll index 02164b18f80..01f0fedb710 100644 --- a/swift/ql/lib/codeql/swift/elements/AstNode.qll +++ b/swift/ql/lib/codeql/swift/elements/AstNode.qll @@ -1,6 +1,6 @@ private import codeql.swift.generated.AstNode private import codeql.swift.elements.decl.AbstractFunctionDecl -private import codeql.swift.generated.GetImmediateParent +private import codeql.swift.generated.ParentChild private Element getEnclosingFunctionStep(Element e) { not e instanceof AbstractFunctionDecl and diff --git a/swift/ql/lib/codeql/swift/generated/Callable.qll b/swift/ql/lib/codeql/swift/generated/Callable.qll index bd3cd4779b3..4b97524744c 100644 --- a/swift/ql/lib/codeql/swift/generated/Callable.qll +++ b/swift/ql/lib/codeql/swift/generated/Callable.qll @@ -6,6 +6,17 @@ import codeql.swift.elements.Element import codeql.swift.elements.decl.ParamDecl class CallableBase extends Synth::TCallable, Element { + ParamDecl getImmediateSelfParam() { + result = + Synth::convertParamDeclFromRaw(Synth::convertCallableToRaw(this) + .(Raw::Callable) + .getSelfParam()) + } + + final ParamDecl getSelfParam() { result = getImmediateSelfParam().resolve() } + + final predicate hasSelfParam() { exists(getSelfParam()) } + ParamDecl getImmediateParam(int index) { result = Synth::convertParamDeclFromRaw(Synth::convertCallableToRaw(this) @@ -19,17 +30,6 @@ class CallableBase extends Synth::TCallable, Element { final int getNumberOfParams() { result = count(getAParam()) } - ParamDecl getImmediateSelfParam() { - result = - Synth::convertParamDeclFromRaw(Synth::convertCallableToRaw(this) - .(Raw::Callable) - .getSelfParam()) - } - - final ParamDecl getSelfParam() { result = getImmediateSelfParam().resolve() } - - final predicate hasSelfParam() { exists(getSelfParam()) } - BraceStmt getImmediateBody() { result = Synth::convertBraceStmtFromRaw(Synth::convertCallableToRaw(this).(Raw::Callable).getBody()) diff --git a/swift/ql/lib/codeql/swift/generated/GetImmediateParent.qll b/swift/ql/lib/codeql/swift/generated/GetImmediateParent.qll deleted file mode 100644 index 1bec53f9a9f..00000000000 --- a/swift/ql/lib/codeql/swift/generated/GetImmediateParent.qll +++ /dev/null @@ -1,237 +0,0 @@ -// generated by codegen/codegen.py -import codeql.swift.elements - -/** - * Gets any of the "immediate" children of `e`. "Immediate" means not taking into account node resolution: for example - * if the AST child is the first of a series of conversions that would normally be hidden away, this will select the - * next conversion down the hidden AST tree instead of the corresponding fully uncoverted node at the bottom. - * Outside this module this file is mainly intended to be used to test uniqueness of parents. - */ -cached -Element getAnImmediateChild(Element e) { - // why does this look more complicated than it should? - // * none() simplifies generation, as we can append `or ...` without a special case for the first item - none() - or - result = e.(Callable).getImmediateParam(_) - or - result = e.(Callable).getImmediateSelfParam() - or - result = e.(Callable).getImmediateBody() - or - result = e.(AbstractStorageDecl).getImmediateAccessorDecl(_) - or - result = e.(EnumCaseDecl).getImmediateElement(_) - or - result = e.(EnumElementDecl).getImmediateParam(_) - or - result = e.(IfConfigClause).getImmediateCondition() - or - result = e.(IfConfigClause).getImmediateElement(_) - or - result = e.(IfConfigDecl).getImmediateClause(_) - or - result = e.(PatternBindingDecl).getImmediateInit(_) - or - result = e.(PatternBindingDecl).getImmediatePattern(_) - or - result = e.(SubscriptDecl).getImmediateParam(_) - or - result = e.(TopLevelCodeDecl).getImmediateBody() - or - result = e.(AnyTryExpr).getImmediateSubExpr() - or - result = e.(ApplyExpr).getImmediateFunction() - or - result = e.(ApplyExpr).getImmediateArgument(_) - or - result = e.(Argument).getImmediateExpr() - or - result = e.(ArrayExpr).getImmediateElement(_) - or - result = e.(AssignExpr).getImmediateDest() - or - result = e.(AssignExpr).getImmediateSource() - or - result = e.(BindOptionalExpr).getImmediateSubExpr() - or - result = e.(CaptureListExpr).getImmediateBindingDecl(_) - or - result = e.(CaptureListExpr).getImmediateClosureBody() - or - result = e.(DictionaryExpr).getImmediateElement(_) - or - result = e.(DotSyntaxBaseIgnoredExpr).getImmediateQualifier() - or - result = e.(DotSyntaxBaseIgnoredExpr).getImmediateSubExpr() - or - result = e.(DynamicTypeExpr).getImmediateBase() - or - result = e.(EnumIsCaseExpr).getImmediateSubExpr() - or - result = e.(ExplicitCastExpr).getImmediateSubExpr() - or - result = e.(ForceValueExpr).getImmediateSubExpr() - or - result = e.(IdentityExpr).getImmediateSubExpr() - or - result = e.(IfExpr).getImmediateCondition() - or - result = e.(IfExpr).getImmediateThenExpr() - or - result = e.(IfExpr).getImmediateElseExpr() - or - result = e.(ImplicitConversionExpr).getImmediateSubExpr() - or - result = e.(InOutExpr).getImmediateSubExpr() - or - result = e.(InterpolatedStringLiteralExpr).getImmediateInterpolationCountExpr() - or - result = e.(InterpolatedStringLiteralExpr).getImmediateLiteralCapacityExpr() - or - result = e.(InterpolatedStringLiteralExpr).getImmediateAppendingExpr() - or - result = e.(KeyPathApplicationExpr).getImmediateBase() - or - result = e.(KeyPathApplicationExpr).getImmediateKeyPath() - or - result = e.(KeyPathExpr).getImmediateRoot() - or - result = e.(KeyPathExpr).getImmediateParsedPath() - or - result = e.(LazyInitializerExpr).getImmediateSubExpr() - or - result = e.(LookupExpr).getImmediateBase() - or - result = e.(MakeTemporarilyEscapableExpr).getImmediateEscapingClosure() - or - result = e.(MakeTemporarilyEscapableExpr).getImmediateNonescapingClosure() - or - result = e.(MakeTemporarilyEscapableExpr).getImmediateSubExpr() - or - result = e.(ObjCSelectorExpr).getImmediateSubExpr() - or - result = e.(OneWayExpr).getImmediateSubExpr() - or - result = e.(OpenExistentialExpr).getImmediateSubExpr() - or - result = e.(OpenExistentialExpr).getImmediateExistential() - or - result = e.(OpenExistentialExpr).getImmediateOpaqueExpr() - or - result = e.(OptionalEvaluationExpr).getImmediateSubExpr() - or - result = e.(RebindSelfInConstructorExpr).getImmediateSubExpr() - or - result = e.(RebindSelfInConstructorExpr).getImmediateSelf() - or - result = e.(SelfApplyExpr).getImmediateBase() - or - result = e.(SequenceExpr).getImmediateElement(_) - or - result = e.(SubscriptExpr).getImmediateArgument(_) - or - result = e.(TapExpr).getImmediateSubExpr() - or - result = e.(TapExpr).getImmediateBody() - or - result = e.(TupleElementExpr).getImmediateSubExpr() - or - result = e.(TupleExpr).getImmediateElement(_) - or - result = e.(TypeExpr).getImmediateTypeRepr() - or - result = e.(UnresolvedDotExpr).getImmediateBase() - or - result = e.(UnresolvedPatternExpr).getImmediateSubPattern() - or - result = e.(VarargExpansionExpr).getImmediateSubExpr() - or - result = e.(BindingPattern).getImmediateSubPattern() - or - result = e.(EnumElementPattern).getImmediateSubPattern() - or - result = e.(ExprPattern).getImmediateSubExpr() - or - result = e.(IsPattern).getImmediateCastTypeRepr() - or - result = e.(IsPattern).getImmediateSubPattern() - or - result = e.(OptionalSomePattern).getImmediateSubPattern() - or - result = e.(ParenPattern).getImmediateSubPattern() - or - result = e.(TuplePattern).getImmediateElement(_) - or - result = e.(TypedPattern).getImmediateSubPattern() - or - result = e.(TypedPattern).getImmediateTypeRepr() - or - result = e.(BraceStmt).getImmediateElement(_) - or - result = e.(CaseLabelItem).getImmediatePattern() - or - result = e.(CaseLabelItem).getImmediateGuard() - or - result = e.(CaseStmt).getImmediateBody() - or - result = e.(CaseStmt).getImmediateLabel(_) - or - result = e.(ConditionElement).getImmediateBoolean() - or - result = e.(ConditionElement).getImmediatePattern() - or - result = e.(ConditionElement).getImmediateInitializer() - or - result = e.(DeferStmt).getImmediateBody() - or - result = e.(DoCatchStmt).getImmediateBody() - or - result = e.(DoCatchStmt).getImmediateCatch(_) - or - result = e.(DoStmt).getImmediateBody() - or - result = e.(ForEachStmt).getImmediatePattern() - or - result = e.(ForEachStmt).getImmediateSequence() - or - result = e.(ForEachStmt).getImmediateWhere() - or - result = e.(ForEachStmt).getImmediateBody() - or - result = e.(GuardStmt).getImmediateBody() - or - result = e.(IfStmt).getImmediateThen() - or - result = e.(IfStmt).getImmediateElse() - or - result = e.(LabeledConditionalStmt).getImmediateCondition() - or - result = e.(RepeatWhileStmt).getImmediateCondition() - or - result = e.(RepeatWhileStmt).getImmediateBody() - or - result = e.(ReturnStmt).getImmediateResult() - or - result = e.(StmtCondition).getImmediateElement(_) - or - result = e.(SwitchStmt).getImmediateExpr() - or - result = e.(SwitchStmt).getImmediateCase(_) - or - result = e.(ThrowStmt).getImmediateSubExpr() - or - result = e.(WhileStmt).getImmediateBody() - or - result = e.(YieldStmt).getImmediateResult(_) -} - -/** - * Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example - * if `e` has conversions, `getImmediateParent(e)` will give the bottom conversion in the hidden AST. - */ -Element getImmediateParent(Element e) { - // `unique` is used here to tell the optimizer that there is in fact only one result - // this is tested by the `library-tests/parent/no_double_parents.ql` test - result = unique(Element x | e = getAnImmediateChild(x) | x) -} diff --git a/swift/ql/lib/codeql/swift/generated/ParentChild.qll b/swift/ql/lib/codeql/swift/generated/ParentChild.qll new file mode 100644 index 00000000000..82928425342 --- /dev/null +++ b/swift/ql/lib/codeql/swift/generated/ParentChild.qll @@ -0,0 +1,5274 @@ +// generated by codegen/codegen.py +import codeql.swift.elements + +private module Impl { + private Element getImmediateChildOfElement(Element e, int index, string partialPredicateCall) { + none() + } + + private Element getImmediateChildOfCallable(Callable e, int index, string partialPredicateCall) { + exists(int b, int bElement, int n, int nSelfParam, int nParam, int nBody | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + nSelfParam = n + 1 and + nParam = nSelfParam + 1 + max(int i | i = -1 or exists(e.getImmediateParam(i)) | i) and + nBody = nParam + 1 and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSelfParam() and partialPredicateCall = "SelfParam()" + or + result = e.getImmediateParam(index - nSelfParam) and + partialPredicateCall = "Param(" + (index - nSelfParam).toString() + ")" + or + index = nParam and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfFile(File e, int index, string partialPredicateCall) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGenericContext( + GenericContext e, int index, string partialPredicateCall + ) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfIterableDeclContext( + IterableDeclContext e, int index, string partialPredicateCall + ) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLocatable(Locatable e, int index, string partialPredicateCall) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLocation(Location e, int index, string partialPredicateCall) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfType(Type e, int index, string partialPredicateCall) { + exists(int b, int bElement, int n | + b = 0 and + bElement = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfElement(e, i, _)) | i) and + n = bElement and + ( + none() + or + result = getImmediateChildOfElement(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyFunctionType( + AnyFunctionType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyGenericType( + AnyGenericType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyMetatypeType( + AnyMetatypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfArgument(Argument e, int index, string partialPredicateCall) { + exists(int b, int bLocatable, int n, int nExpr | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + nExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateExpr() and partialPredicateCall = "Expr()" + ) + ) + } + + private Element getImmediateChildOfAstNode(AstNode e, int index, string partialPredicateCall) { + exists(int b, int bLocatable, int n | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinType( + BuiltinType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfComment(Comment e, int index, string partialPredicateCall) { + exists(int b, int bLocatable, int n | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConditionElement( + ConditionElement e, int index, string partialPredicateCall + ) { + exists(int b, int bLocatable, int n, int nBoolean, int nPattern, int nInitializer | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + nBoolean = n + 1 and + nPattern = nBoolean + 1 and + nInitializer = nPattern + 1 and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBoolean() and partialPredicateCall = "Boolean()" + or + index = nBoolean and result = e.getImmediatePattern() and partialPredicateCall = "Pattern()" + or + index = nPattern and + result = e.getImmediateInitializer() and + partialPredicateCall = "Initializer()" + ) + ) + } + + private Element getImmediateChildOfDbFile(DbFile e, int index, string partialPredicateCall) { + exists(int b, int bFile, int n | + b = 0 and + bFile = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFile(e, i, _)) | i) and + n = bFile and + ( + none() + or + result = getImmediateChildOfFile(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDbLocation(DbLocation e, int index, string partialPredicateCall) { + exists(int b, int bLocation, int n | + b = 0 and + bLocation = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocation(e, i, _)) | i) and + n = bLocation and + ( + none() + or + result = getImmediateChildOfLocation(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDependentMemberType( + DependentMemberType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDynamicSelfType( + DynamicSelfType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfErrorType(ErrorType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfExistentialType( + ExistentialType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfIfConfigClause( + IfConfigClause e, int index, string partialPredicateCall + ) { + exists(int b, int bLocatable, int n, int nCondition, int nElement | + b = 0 and + bLocatable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocatable(e, i, _)) | i) and + n = bLocatable and + nCondition = n + 1 and + nElement = nCondition + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfLocatable(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateCondition() and partialPredicateCall = "Condition()" + or + result = e.getImmediateElement(index - nCondition) and + partialPredicateCall = "Element(" + (index - nCondition).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfInOutType(InOutType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLValueType(LValueType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfModuleType(ModuleType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPlaceholderType( + PlaceholderType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfProtocolCompositionType( + ProtocolCompositionType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfReferenceStorageType( + ReferenceStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSilBlockStorageType( + SilBlockStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSilBoxType(SilBoxType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSilFunctionType( + SilFunctionType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSilTokenType( + SilTokenType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSubstitutableType( + SubstitutableType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSugarType(SugarType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTupleType(TupleType e, int index, string partialPredicateCall) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTypeVariableType( + TypeVariableType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnknownFile( + UnknownFile e, int index, string partialPredicateCall + ) { + exists(int b, int bFile, int n | + b = 0 and + bFile = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFile(e, i, _)) | i) and + n = bFile and + ( + none() + or + result = getImmediateChildOfFile(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnknownLocation( + UnknownLocation e, int index, string partialPredicateCall + ) { + exists(int b, int bLocation, int n | + b = 0 and + bLocation = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLocation(e, i, _)) | i) and + n = bLocation and + ( + none() + or + result = getImmediateChildOfLocation(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedType( + UnresolvedType e, int index, string partialPredicateCall + ) { + exists(int b, int bType, int n | + b = 0 and + bType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfType(e, i, _)) | i) and + n = bType and + ( + none() + or + result = getImmediateChildOfType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyBuiltinIntegerType( + AnyBuiltinIntegerType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfArchetypeType( + ArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bSubstitutableType, int n | + b = 0 and + bSubstitutableType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSubstitutableType(e, i, _)) | i) and + n = bSubstitutableType and + ( + none() + or + result = getImmediateChildOfSubstitutableType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinBridgeObjectType( + BuiltinBridgeObjectType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinDefaultActorStorageType( + BuiltinDefaultActorStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinExecutorType( + BuiltinExecutorType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinFloatType( + BuiltinFloatType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinJobType( + BuiltinJobType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinNativeObjectType( + BuiltinNativeObjectType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinRawPointerType( + BuiltinRawPointerType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinRawUnsafeContinuationType( + BuiltinRawUnsafeContinuationType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinUnsafeValueBufferType( + BuiltinUnsafeValueBufferType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinVectorType( + BuiltinVectorType e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinType, int n | + b = 0 and + bBuiltinType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinType(e, i, _)) | i) and + n = bBuiltinType and + ( + none() + or + result = getImmediateChildOfBuiltinType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCaseLabelItem( + CaseLabelItem e, int index, string partialPredicateCall + ) { + exists(int b, int bAstNode, int n, int nPattern, int nGuard | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + nPattern = n + 1 and + nGuard = nPattern + 1 and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediatePattern() and partialPredicateCall = "Pattern()" + or + index = nPattern and result = e.getImmediateGuard() and partialPredicateCall = "Guard()" + ) + ) + } + + private Element getImmediateChildOfDecl(Decl e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfExistentialMetatypeType( + ExistentialMetatypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyMetatypeType, int n | + b = 0 and + bAnyMetatypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyMetatypeType(e, i, _)) | i) and + n = bAnyMetatypeType and + ( + none() + or + result = getImmediateChildOfAnyMetatypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfExpr(Expr e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFunctionType( + FunctionType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyFunctionType, int n | + b = 0 and + bAnyFunctionType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyFunctionType(e, i, _)) | i) and + n = bAnyFunctionType and + ( + none() + or + result = getImmediateChildOfAnyFunctionType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGenericFunctionType( + GenericFunctionType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyFunctionType, int n | + b = 0 and + bAnyFunctionType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyFunctionType(e, i, _)) | i) and + n = bAnyFunctionType and + ( + none() + or + result = getImmediateChildOfAnyFunctionType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGenericTypeParamType( + GenericTypeParamType e, int index, string partialPredicateCall + ) { + exists(int b, int bSubstitutableType, int n | + b = 0 and + bSubstitutableType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSubstitutableType(e, i, _)) | i) and + n = bSubstitutableType and + ( + none() + or + result = getImmediateChildOfSubstitutableType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfMetatypeType( + MetatypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyMetatypeType, int n | + b = 0 and + bAnyMetatypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyMetatypeType(e, i, _)) | i) and + n = bAnyMetatypeType and + ( + none() + or + result = getImmediateChildOfAnyMetatypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNominalOrBoundGenericNominalType( + NominalOrBoundGenericNominalType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyGenericType, int n | + b = 0 and + bAnyGenericType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyGenericType(e, i, _)) | i) and + n = bAnyGenericType and + ( + none() + or + result = getImmediateChildOfAnyGenericType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfParenType(ParenType e, int index, string partialPredicateCall) { + exists(int b, int bSugarType, int n | + b = 0 and + bSugarType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSugarType(e, i, _)) | i) and + n = bSugarType and + ( + none() + or + result = getImmediateChildOfSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPattern(Pattern e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfStmt(Stmt e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfStmtCondition( + StmtCondition e, int index, string partialPredicateCall + ) { + exists(int b, int bAstNode, int n, int nElement | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfSyntaxSugarType( + SyntaxSugarType e, int index, string partialPredicateCall + ) { + exists(int b, int bSugarType, int n | + b = 0 and + bSugarType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSugarType(e, i, _)) | i) and + n = bSugarType and + ( + none() + or + result = getImmediateChildOfSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTypeAliasType( + TypeAliasType e, int index, string partialPredicateCall + ) { + exists(int b, int bSugarType, int n | + b = 0 and + bSugarType = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSugarType(e, i, _)) | i) and + n = bSugarType and + ( + none() + or + result = getImmediateChildOfSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTypeRepr(TypeRepr e, int index, string partialPredicateCall) { + exists(int b, int bAstNode, int n | + b = 0 and + bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and + n = bAstNode and + ( + none() + or + result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnboundGenericType( + UnboundGenericType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyGenericType, int n | + b = 0 and + bAnyGenericType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyGenericType(e, i, _)) | i) and + n = bAnyGenericType and + ( + none() + or + result = getImmediateChildOfAnyGenericType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnmanagedStorageType( + UnmanagedStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bReferenceStorageType, int n | + b = 0 and + bReferenceStorageType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfReferenceStorageType(e, i, _)) | i) and + n = bReferenceStorageType and + ( + none() + or + result = getImmediateChildOfReferenceStorageType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnownedStorageType( + UnownedStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bReferenceStorageType, int n | + b = 0 and + bReferenceStorageType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfReferenceStorageType(e, i, _)) | i) and + n = bReferenceStorageType and + ( + none() + or + result = getImmediateChildOfReferenceStorageType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfWeakStorageType( + WeakStorageType e, int index, string partialPredicateCall + ) { + exists(int b, int bReferenceStorageType, int n | + b = 0 and + bReferenceStorageType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfReferenceStorageType(e, i, _)) | i) and + n = bReferenceStorageType and + ( + none() + or + result = getImmediateChildOfReferenceStorageType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAbstractClosureExpr( + AbstractClosureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bCallable, int bExpr, int n | + b = 0 and + bCallable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and + bExpr = bCallable + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfCallable(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfExpr(e, index - bCallable, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyPattern(AnyPattern e, int index, string partialPredicateCall) { + exists(int b, int bPattern, int n | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAnyTryExpr(AnyTryExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfAppliedPropertyWrapperExpr( + AppliedPropertyWrapperExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfApplyExpr(ApplyExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nFunction, int nArgument | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nFunction = n + 1 and + nArgument = nFunction + 1 + max(int i | i = -1 or exists(e.getImmediateArgument(i)) | i) and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateFunction() and partialPredicateCall = "Function()" + or + result = e.getImmediateArgument(index - nFunction) and + partialPredicateCall = "Argument(" + (index - nFunction).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfArrowExpr(ArrowExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAssignExpr(AssignExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nDest, int nSource | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nDest = n + 1 and + nSource = nDest + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateDest() and partialPredicateCall = "Dest()" + or + index = nDest and result = e.getImmediateSource() and partialPredicateCall = "Source()" + ) + ) + } + + private Element getImmediateChildOfBindOptionalExpr( + BindOptionalExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfBindingPattern( + BindingPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubPattern | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubPattern = n + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfBoolPattern( + BoolPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBoundGenericType( + BoundGenericType e, int index, string partialPredicateCall + ) { + exists(int b, int bNominalOrBoundGenericNominalType, int n | + b = 0 and + bNominalOrBoundGenericNominalType = + b + 1 + + max(int i | + i = -1 or exists(getImmediateChildOfNominalOrBoundGenericNominalType(e, i, _)) + | + i + ) and + n = bNominalOrBoundGenericNominalType and + ( + none() + or + result = + getImmediateChildOfNominalOrBoundGenericNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBraceStmt(BraceStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nElement | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfBreakStmt(BreakStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinIntegerLiteralType( + BuiltinIntegerLiteralType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyBuiltinIntegerType, int n | + b = 0 and + bAnyBuiltinIntegerType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyBuiltinIntegerType(e, i, _)) | i) and + n = bAnyBuiltinIntegerType and + ( + none() + or + result = getImmediateChildOfAnyBuiltinIntegerType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinIntegerType( + BuiltinIntegerType e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyBuiltinIntegerType, int n | + b = 0 and + bAnyBuiltinIntegerType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyBuiltinIntegerType(e, i, _)) | i) and + n = bAnyBuiltinIntegerType and + ( + none() + or + result = getImmediateChildOfAnyBuiltinIntegerType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCaptureListExpr( + CaptureListExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nBindingDecl, int nClosureBody | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nBindingDecl = n + 1 + max(int i | i = -1 or exists(e.getImmediateBindingDecl(i)) | i) and + nClosureBody = nBindingDecl + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateBindingDecl(index - n) and + partialPredicateCall = "BindingDecl(" + (index - n).toString() + ")" + or + index = nBindingDecl and + result = e.getImmediateClosureBody() and + partialPredicateCall = "ClosureBody()" + ) + ) + } + + private Element getImmediateChildOfCaseStmt(CaseStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nBody, int nLabel | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nBody = n + 1 and + nLabel = nBody + 1 + max(int i | i = -1 or exists(e.getImmediateLabel(i)) | i) and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + or + result = e.getImmediateLabel(index - nBody) and + partialPredicateCall = "Label(" + (index - nBody).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfCodeCompletionExpr( + CodeCompletionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCollectionExpr( + CollectionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfContinueStmt( + ContinueStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDeclRefExpr( + DeclRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDefaultArgumentExpr( + DefaultArgumentExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDeferStmt(DeferStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nBody | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nBody = n + 1 and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfDictionaryType( + DictionaryType e, int index, string partialPredicateCall + ) { + exists(int b, int bSyntaxSugarType, int n | + b = 0 and + bSyntaxSugarType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSyntaxSugarType(e, i, _)) | i) and + n = bSyntaxSugarType and + ( + none() + or + result = getImmediateChildOfSyntaxSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDiscardAssignmentExpr( + DiscardAssignmentExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDotSyntaxBaseIgnoredExpr( + DotSyntaxBaseIgnoredExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nQualifier, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nQualifier = n + 1 and + nSubExpr = nQualifier + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateQualifier() and partialPredicateCall = "Qualifier()" + or + index = nQualifier and + result = e.getImmediateSubExpr() and + partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfDynamicTypeExpr( + DynamicTypeExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nBase | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nBase = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBase() and partialPredicateCall = "Base()" + ) + ) + } + + private Element getImmediateChildOfEditorPlaceholderExpr( + EditorPlaceholderExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfEnumCaseDecl( + EnumCaseDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n, int nElement | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfEnumElementPattern( + EnumElementPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubPattern | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubPattern = n + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfEnumIsCaseExpr( + EnumIsCaseExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfErrorExpr(ErrorExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfExplicitCastExpr( + ExplicitCastExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfExprPattern( + ExprPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubExpr | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfExtensionDecl( + ExtensionDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int bGenericContext, int bIterableDeclContext, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + bGenericContext = + bDecl + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and + bIterableDeclContext = + bGenericContext + 1 + + max(int i | i = -1 or exists(getImmediateChildOfIterableDeclContext(e, i, _)) | i) and + n = bIterableDeclContext and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfGenericContext(e, index - bDecl, partialPredicateCall) + or + result = + getImmediateChildOfIterableDeclContext(e, index - bGenericContext, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFailStmt(FailStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFallthroughStmt( + FallthroughStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfForceValueExpr( + ForceValueExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfIdentityExpr( + IdentityExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfIfConfigDecl( + IfConfigDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n, int nClause | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + nClause = n + 1 + max(int i | i = -1 or exists(e.getImmediateClause(i)) | i) and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + or + result = e.getImmediateClause(index - n) and + partialPredicateCall = "Clause(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfIfExpr(IfExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nCondition, int nThenExpr, int nElseExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nCondition = n + 1 and + nThenExpr = nCondition + 1 and + nElseExpr = nThenExpr + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateCondition() and partialPredicateCall = "Condition()" + or + index = nCondition and + result = e.getImmediateThenExpr() and + partialPredicateCall = "ThenExpr()" + or + index = nThenExpr and + result = e.getImmediateElseExpr() and + partialPredicateCall = "ElseExpr()" + ) + ) + } + + private Element getImmediateChildOfImplicitConversionExpr( + ImplicitConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfImportDecl(ImportDecl e, int index, string partialPredicateCall) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfInOutExpr(InOutExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfIsPattern(IsPattern e, int index, string partialPredicateCall) { + exists(int b, int bPattern, int n, int nCastTypeRepr, int nSubPattern | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nCastTypeRepr = n + 1 and + nSubPattern = nCastTypeRepr + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and + result = e.getImmediateCastTypeRepr() and + partialPredicateCall = "CastTypeRepr()" + or + index = nCastTypeRepr and + result = e.getImmediateSubPattern() and + partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfKeyPathApplicationExpr( + KeyPathApplicationExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nBase, int nKeyPath | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nBase = n + 1 and + nKeyPath = nBase + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBase() and partialPredicateCall = "Base()" + or + index = nBase and result = e.getImmediateKeyPath() and partialPredicateCall = "KeyPath()" + ) + ) + } + + private Element getImmediateChildOfKeyPathDotExpr( + KeyPathDotExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfKeyPathExpr( + KeyPathExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nRoot, int nParsedPath | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nRoot = n + 1 and + nParsedPath = nRoot + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateRoot() and partialPredicateCall = "Root()" + or + index = nRoot and + result = e.getImmediateParsedPath() and + partialPredicateCall = "ParsedPath()" + ) + ) + } + + private Element getImmediateChildOfLabeledStmt( + LabeledStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLazyInitializerExpr( + LazyInitializerExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfLiteralExpr( + LiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLookupExpr(LookupExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nBase | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nBase = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBase() and partialPredicateCall = "Base()" + ) + ) + } + + private Element getImmediateChildOfMakeTemporarilyEscapableExpr( + MakeTemporarilyEscapableExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nEscapingClosure, int nNonescapingClosure, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nEscapingClosure = n + 1 and + nNonescapingClosure = nEscapingClosure + 1 and + nSubExpr = nNonescapingClosure + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and + result = e.getImmediateEscapingClosure() and + partialPredicateCall = "EscapingClosure()" + or + index = nEscapingClosure and + result = e.getImmediateNonescapingClosure() and + partialPredicateCall = "NonescapingClosure()" + or + index = nNonescapingClosure and + result = e.getImmediateSubExpr() and + partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfMissingMemberDecl( + MissingMemberDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNamedPattern( + NamedPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNestedArchetypeType( + NestedArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bArchetypeType, int n | + b = 0 and + bArchetypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfArchetypeType(e, i, _)) | i) and + n = bArchetypeType and + ( + none() + or + result = getImmediateChildOfArchetypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNominalType( + NominalType e, int index, string partialPredicateCall + ) { + exists(int b, int bNominalOrBoundGenericNominalType, int n | + b = 0 and + bNominalOrBoundGenericNominalType = + b + 1 + + max(int i | + i = -1 or exists(getImmediateChildOfNominalOrBoundGenericNominalType(e, i, _)) + | + i + ) and + n = bNominalOrBoundGenericNominalType and + ( + none() + or + result = + getImmediateChildOfNominalOrBoundGenericNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfObjCSelectorExpr( + ObjCSelectorExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfOneWayExpr(OneWayExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfOpaqueTypeArchetypeType( + OpaqueTypeArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bArchetypeType, int n | + b = 0 and + bArchetypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfArchetypeType(e, i, _)) | i) and + n = bArchetypeType and + ( + none() + or + result = getImmediateChildOfArchetypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOpaqueValueExpr( + OpaqueValueExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOpenExistentialExpr( + OpenExistentialExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr, int nExistential, int nOpaqueExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + nExistential = nSubExpr + 1 and + nOpaqueExpr = nExistential + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + or + index = nSubExpr and + result = e.getImmediateExistential() and + partialPredicateCall = "Existential()" + or + index = nExistential and + result = e.getImmediateOpaqueExpr() and + partialPredicateCall = "OpaqueExpr()" + ) + ) + } + + private Element getImmediateChildOfOpenedArchetypeType( + OpenedArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bArchetypeType, int n | + b = 0 and + bArchetypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfArchetypeType(e, i, _)) | i) and + n = bArchetypeType and + ( + none() + or + result = getImmediateChildOfArchetypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOperatorDecl( + OperatorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOptionalEvaluationExpr( + OptionalEvaluationExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfOptionalSomePattern( + OptionalSomePattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubPattern | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubPattern = n + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfOtherConstructorDeclRefExpr( + OtherConstructorDeclRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOverloadSetRefExpr( + OverloadSetRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfParenPattern( + ParenPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubPattern | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubPattern = n + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfPatternBindingDecl( + PatternBindingDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n, int nInit, int nPattern | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + nInit = n + 1 + max(int i | i = -1 or exists(e.getImmediateInit(i)) | i) and + nPattern = nInit + 1 + max(int i | i = -1 or exists(e.getImmediatePattern(i)) | i) and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + or + result = e.getImmediateInit(index - n) and + partialPredicateCall = "Init(" + (index - n).toString() + ")" + or + result = e.getImmediatePattern(index - nInit) and + partialPredicateCall = "Pattern(" + (index - nInit).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfPoundAssertStmt( + PoundAssertStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bStmt, int n | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPoundDiagnosticDecl( + PoundDiagnosticDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPrecedenceGroupDecl( + PrecedenceGroupDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPrimaryArchetypeType( + PrimaryArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bArchetypeType, int n | + b = 0 and + bArchetypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfArchetypeType(e, i, _)) | i) and + n = bArchetypeType and + ( + none() + or + result = getImmediateChildOfArchetypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPropertyWrapperValuePlaceholderExpr( + PropertyWrapperValuePlaceholderExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfRebindSelfInConstructorExpr( + RebindSelfInConstructorExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfReturnStmt(ReturnStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nResult | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nResult = n + 1 and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateResult() and partialPredicateCall = "Result()" + ) + ) + } + + private Element getImmediateChildOfSequenceArchetypeType( + SequenceArchetypeType e, int index, string partialPredicateCall + ) { + exists(int b, int bArchetypeType, int n | + b = 0 and + bArchetypeType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfArchetypeType(e, i, _)) | i) and + n = bArchetypeType and + ( + none() + or + result = getImmediateChildOfArchetypeType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSequenceExpr( + SequenceExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nElement | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfSuperRefExpr( + SuperRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTapExpr(TapExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nSubExpr, int nBody | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + nBody = nSubExpr + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + or + index = nSubExpr and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfThrowStmt(ThrowStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nSubExpr | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfTopLevelCodeDecl( + TopLevelCodeDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bDecl, int n, int nBody | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + nBody = n + 1 and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfTupleElementExpr( + TupleElementExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfTupleExpr(TupleExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nElement | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfTuplePattern( + TuplePattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nElement | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfTypeExpr(TypeExpr e, int index, string partialPredicateCall) { + exists(int b, int bExpr, int n, int nTypeRepr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nTypeRepr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateTypeRepr() and partialPredicateCall = "TypeRepr()" + ) + ) + } + + private Element getImmediateChildOfTypedPattern( + TypedPattern e, int index, string partialPredicateCall + ) { + exists(int b, int bPattern, int n, int nSubPattern, int nTypeRepr | + b = 0 and + bPattern = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfPattern(e, i, _)) | i) and + n = bPattern and + nSubPattern = n + 1 and + nTypeRepr = nSubPattern + 1 and + ( + none() + or + result = getImmediateChildOfPattern(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + or + index = nSubPattern and + result = e.getImmediateTypeRepr() and + partialPredicateCall = "TypeRepr()" + ) + ) + } + + private Element getImmediateChildOfUnarySyntaxSugarType( + UnarySyntaxSugarType e, int index, string partialPredicateCall + ) { + exists(int b, int bSyntaxSugarType, int n | + b = 0 and + bSyntaxSugarType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSyntaxSugarType(e, i, _)) | i) and + n = bSyntaxSugarType and + ( + none() + or + result = getImmediateChildOfSyntaxSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedDeclRefExpr( + UnresolvedDeclRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedDotExpr( + UnresolvedDotExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nBase | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nBase = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBase() and partialPredicateCall = "Base()" + ) + ) + } + + private Element getImmediateChildOfUnresolvedMemberExpr( + UnresolvedMemberExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedPatternExpr( + UnresolvedPatternExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubPattern | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubPattern = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubPattern() and partialPredicateCall = "SubPattern()" + ) + ) + } + + private Element getImmediateChildOfUnresolvedSpecializeExpr( + UnresolvedSpecializeExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfValueDecl(ValueDecl e, int index, string partialPredicateCall) { + exists(int b, int bDecl, int n | + b = 0 and + bDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDecl(e, i, _)) | i) and + n = bDecl and + ( + none() + or + result = getImmediateChildOfDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfVarargExpansionExpr( + VarargExpansionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExpr, int n, int nSubExpr | + b = 0 and + bExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExpr(e, i, _)) | i) and + n = bExpr and + nSubExpr = n + 1 and + ( + none() + or + result = getImmediateChildOfExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateSubExpr() and partialPredicateCall = "SubExpr()" + ) + ) + } + + private Element getImmediateChildOfYieldStmt(YieldStmt e, int index, string partialPredicateCall) { + exists(int b, int bStmt, int n, int nResult | + b = 0 and + bStmt = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfStmt(e, i, _)) | i) and + n = bStmt and + nResult = n + 1 + max(int i | i = -1 or exists(e.getImmediateResult(i)) | i) and + ( + none() + or + result = getImmediateChildOfStmt(e, index - b, partialPredicateCall) + or + result = e.getImmediateResult(index - n) and + partialPredicateCall = "Result(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfAbstractFunctionDecl( + AbstractFunctionDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bCallable, int bGenericContext, int bValueDecl, int n | + b = 0 and + bCallable = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCallable(e, i, _)) | i) and + bGenericContext = + bCallable + 1 + + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and + bValueDecl = + bGenericContext + 1 + + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and + n = bValueDecl and + ( + none() + or + result = getImmediateChildOfCallable(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfGenericContext(e, index - bCallable, partialPredicateCall) + or + result = getImmediateChildOfValueDecl(e, index - bGenericContext, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAbstractStorageDecl( + AbstractStorageDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bValueDecl, int n, int nAccessorDecl | + b = 0 and + bValueDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and + n = bValueDecl and + nAccessorDecl = n + 1 + max(int i | i = -1 or exists(e.getImmediateAccessorDecl(i)) | i) and + ( + none() + or + result = getImmediateChildOfValueDecl(e, index - b, partialPredicateCall) + or + result = e.getImmediateAccessorDecl(index - n) and + partialPredicateCall = "AccessorDecl(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfAnyHashableErasureExpr( + AnyHashableErasureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfArchetypeToSuperExpr( + ArchetypeToSuperExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfArrayExpr(ArrayExpr e, int index, string partialPredicateCall) { + exists(int b, int bCollectionExpr, int n, int nElement | + b = 0 and + bCollectionExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCollectionExpr(e, i, _)) | i) and + n = bCollectionExpr and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfCollectionExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfArraySliceType( + ArraySliceType e, int index, string partialPredicateCall + ) { + exists(int b, int bUnarySyntaxSugarType, int n | + b = 0 and + bUnarySyntaxSugarType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfUnarySyntaxSugarType(e, i, _)) | i) and + n = bUnarySyntaxSugarType and + ( + none() + or + result = getImmediateChildOfUnarySyntaxSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfArrayToPointerExpr( + ArrayToPointerExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAutoClosureExpr( + AutoClosureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractClosureExpr, int n | + b = 0 and + bAbstractClosureExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractClosureExpr(e, i, _)) | i) and + n = bAbstractClosureExpr and + ( + none() + or + result = getImmediateChildOfAbstractClosureExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAwaitExpr(AwaitExpr e, int index, string partialPredicateCall) { + exists(int b, int bIdentityExpr, int n | + b = 0 and + bIdentityExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfIdentityExpr(e, i, _)) | i) and + n = bIdentityExpr and + ( + none() + or + result = getImmediateChildOfIdentityExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBinaryExpr(BinaryExpr e, int index, string partialPredicateCall) { + exists(int b, int bApplyExpr, int n | + b = 0 and + bApplyExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfApplyExpr(e, i, _)) | i) and + n = bApplyExpr and + ( + none() + or + result = getImmediateChildOfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBoundGenericClassType( + BoundGenericClassType e, int index, string partialPredicateCall + ) { + exists(int b, int bBoundGenericType, int n | + b = 0 and + bBoundGenericType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBoundGenericType(e, i, _)) | i) and + n = bBoundGenericType and + ( + none() + or + result = getImmediateChildOfBoundGenericType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBoundGenericEnumType( + BoundGenericEnumType e, int index, string partialPredicateCall + ) { + exists(int b, int bBoundGenericType, int n | + b = 0 and + bBoundGenericType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBoundGenericType(e, i, _)) | i) and + n = bBoundGenericType and + ( + none() + or + result = getImmediateChildOfBoundGenericType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBoundGenericStructType( + BoundGenericStructType e, int index, string partialPredicateCall + ) { + exists(int b, int bBoundGenericType, int n | + b = 0 and + bBoundGenericType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBoundGenericType(e, i, _)) | i) and + n = bBoundGenericType and + ( + none() + or + result = getImmediateChildOfBoundGenericType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBridgeFromObjCExpr( + BridgeFromObjCExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBridgeToObjCExpr( + BridgeToObjCExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBuiltinLiteralExpr( + BuiltinLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLiteralExpr, int n | + b = 0 and + bLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLiteralExpr(e, i, _)) | i) and + n = bLiteralExpr and + ( + none() + or + result = getImmediateChildOfLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCallExpr(CallExpr e, int index, string partialPredicateCall) { + exists(int b, int bApplyExpr, int n | + b = 0 and + bApplyExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfApplyExpr(e, i, _)) | i) and + n = bApplyExpr and + ( + none() + or + result = getImmediateChildOfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCheckedCastExpr( + CheckedCastExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bExplicitCastExpr, int n | + b = 0 and + bExplicitCastExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExplicitCastExpr(e, i, _)) | i) and + n = bExplicitCastExpr and + ( + none() + or + result = getImmediateChildOfExplicitCastExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfClassMetatypeToObjectExpr( + ClassMetatypeToObjectExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfClassType(ClassType e, int index, string partialPredicateCall) { + exists(int b, int bNominalType, int n | + b = 0 and + bNominalType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalType(e, i, _)) | i) and + n = bNominalType and + ( + none() + or + result = getImmediateChildOfNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfClosureExpr( + ClosureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractClosureExpr, int n | + b = 0 and + bAbstractClosureExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractClosureExpr(e, i, _)) | i) and + n = bAbstractClosureExpr and + ( + none() + or + result = getImmediateChildOfAbstractClosureExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCoerceExpr(CoerceExpr e, int index, string partialPredicateCall) { + exists(int b, int bExplicitCastExpr, int n | + b = 0 and + bExplicitCastExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfExplicitCastExpr(e, i, _)) | i) and + n = bExplicitCastExpr and + ( + none() + or + result = getImmediateChildOfExplicitCastExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCollectionUpcastConversionExpr( + CollectionUpcastConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConditionalBridgeFromObjCExpr( + ConditionalBridgeFromObjCExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCovariantFunctionConversionExpr( + CovariantFunctionConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfCovariantReturnConversionExpr( + CovariantReturnConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDerivedToBaseExpr( + DerivedToBaseExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDestructureTupleExpr( + DestructureTupleExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDictionaryExpr( + DictionaryExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bCollectionExpr, int n, int nElement | + b = 0 and + bCollectionExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCollectionExpr(e, i, _)) | i) and + n = bCollectionExpr and + nElement = n + 1 + max(int i | i = -1 or exists(e.getImmediateElement(i)) | i) and + ( + none() + or + result = getImmediateChildOfCollectionExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateElement(index - n) and + partialPredicateCall = "Element(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfDifferentiableFunctionExpr( + DifferentiableFunctionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDifferentiableFunctionExtractOriginalExpr( + DifferentiableFunctionExtractOriginalExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDoCatchStmt( + DoCatchStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bLabeledStmt, int n, int nBody, int nCatch | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nBody = n + 1 and + nCatch = nBody + 1 + max(int i | i = -1 or exists(e.getImmediateCatch(i)) | i) and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + or + result = e.getImmediateCatch(index - nBody) and + partialPredicateCall = "Catch(" + (index - nBody).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfDoStmt(DoStmt e, int index, string partialPredicateCall) { + exists(int b, int bLabeledStmt, int n, int nBody | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nBody = n + 1 and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfDotSelfExpr( + DotSelfExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bIdentityExpr, int n | + b = 0 and + bIdentityExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfIdentityExpr(e, i, _)) | i) and + n = bIdentityExpr and + ( + none() + or + result = getImmediateChildOfIdentityExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDynamicLookupExpr( + DynamicLookupExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLookupExpr, int n | + b = 0 and + bLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLookupExpr(e, i, _)) | i) and + n = bLookupExpr and + ( + none() + or + result = getImmediateChildOfLookupExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfEnumElementDecl( + EnumElementDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bValueDecl, int n, int nParam | + b = 0 and + bValueDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and + n = bValueDecl and + nParam = n + 1 + max(int i | i = -1 or exists(e.getImmediateParam(i)) | i) and + ( + none() + or + result = getImmediateChildOfValueDecl(e, index - b, partialPredicateCall) + or + result = e.getImmediateParam(index - n) and + partialPredicateCall = "Param(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfEnumType(EnumType e, int index, string partialPredicateCall) { + exists(int b, int bNominalType, int n | + b = 0 and + bNominalType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalType(e, i, _)) | i) and + n = bNominalType and + ( + none() + or + result = getImmediateChildOfNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfErasureExpr( + ErasureExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfExistentialMetatypeToObjectExpr( + ExistentialMetatypeToObjectExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfForEachStmt( + ForEachStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bLabeledStmt, int n, int nPattern, int nSequence, int nWhere, int nBody | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nPattern = n + 1 and + nSequence = nPattern + 1 and + nWhere = nSequence + 1 and + nBody = nWhere + 1 and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediatePattern() and partialPredicateCall = "Pattern()" + or + index = nPattern and + result = e.getImmediateSequence() and + partialPredicateCall = "Sequence()" + or + index = nSequence and result = e.getImmediateWhere() and partialPredicateCall = "Where()" + or + index = nWhere and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfForceTryExpr( + ForceTryExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyTryExpr, int n | + b = 0 and + bAnyTryExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyTryExpr(e, i, _)) | i) and + n = bAnyTryExpr and + ( + none() + or + result = getImmediateChildOfAnyTryExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfForeignObjectConversionExpr( + ForeignObjectConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFunctionConversionExpr( + FunctionConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfInOutToPointerExpr( + InOutToPointerExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfInfixOperatorDecl( + InfixOperatorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bOperatorDecl, int n | + b = 0 and + bOperatorDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfOperatorDecl(e, i, _)) | i) and + n = bOperatorDecl and + ( + none() + or + result = getImmediateChildOfOperatorDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfInjectIntoOptionalExpr( + InjectIntoOptionalExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfInterpolatedStringLiteralExpr( + InterpolatedStringLiteralExpr e, int index, string partialPredicateCall + ) { + exists( + int b, int bLiteralExpr, int n, int nInterpolationCountExpr, int nLiteralCapacityExpr, + int nAppendingExpr + | + b = 0 and + bLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLiteralExpr(e, i, _)) | i) and + n = bLiteralExpr and + nInterpolationCountExpr = n + 1 and + nLiteralCapacityExpr = nInterpolationCountExpr + 1 and + nAppendingExpr = nLiteralCapacityExpr + 1 and + ( + none() + or + result = getImmediateChildOfLiteralExpr(e, index - b, partialPredicateCall) + or + index = n and + result = e.getImmediateInterpolationCountExpr() and + partialPredicateCall = "InterpolationCountExpr()" + or + index = nInterpolationCountExpr and + result = e.getImmediateLiteralCapacityExpr() and + partialPredicateCall = "LiteralCapacityExpr()" + or + index = nLiteralCapacityExpr and + result = e.getImmediateAppendingExpr() and + partialPredicateCall = "AppendingExpr()" + ) + ) + } + + private Element getImmediateChildOfLabeledConditionalStmt( + LabeledConditionalStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bLabeledStmt, int n, int nCondition | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nCondition = n + 1 and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateCondition() and partialPredicateCall = "Condition()" + ) + ) + } + + private Element getImmediateChildOfLinearFunctionExpr( + LinearFunctionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLinearFunctionExtractOriginalExpr( + LinearFunctionExtractOriginalExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLinearToDifferentiableFunctionExpr( + LinearToDifferentiableFunctionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfLoadExpr(LoadExpr e, int index, string partialPredicateCall) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfMemberRefExpr( + MemberRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLookupExpr, int n | + b = 0 and + bLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLookupExpr(e, i, _)) | i) and + n = bLookupExpr and + ( + none() + or + result = getImmediateChildOfLookupExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfMetatypeConversionExpr( + MetatypeConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfMethodRefExpr( + MethodRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLookupExpr, int n | + b = 0 and + bLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLookupExpr(e, i, _)) | i) and + n = bLookupExpr and + ( + none() + or + result = getImmediateChildOfLookupExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNilLiteralExpr( + NilLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLiteralExpr, int n | + b = 0 and + bLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLiteralExpr(e, i, _)) | i) and + n = bLiteralExpr and + ( + none() + or + result = getImmediateChildOfLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfObjectLiteralExpr( + ObjectLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLiteralExpr, int n | + b = 0 and + bLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLiteralExpr(e, i, _)) | i) and + n = bLiteralExpr and + ( + none() + or + result = getImmediateChildOfLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOptionalTryExpr( + OptionalTryExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bAnyTryExpr, int n | + b = 0 and + bAnyTryExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyTryExpr(e, i, _)) | i) and + n = bAnyTryExpr and + ( + none() + or + result = getImmediateChildOfAnyTryExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOptionalType( + OptionalType e, int index, string partialPredicateCall + ) { + exists(int b, int bUnarySyntaxSugarType, int n | + b = 0 and + bUnarySyntaxSugarType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfUnarySyntaxSugarType(e, i, _)) | i) and + n = bUnarySyntaxSugarType and + ( + none() + or + result = getImmediateChildOfUnarySyntaxSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOverloadedDeclRefExpr( + OverloadedDeclRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bOverloadSetRefExpr, int n | + b = 0 and + bOverloadSetRefExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfOverloadSetRefExpr(e, i, _)) | i) and + n = bOverloadSetRefExpr and + ( + none() + or + result = getImmediateChildOfOverloadSetRefExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfParenExpr(ParenExpr e, int index, string partialPredicateCall) { + exists(int b, int bIdentityExpr, int n | + b = 0 and + bIdentityExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfIdentityExpr(e, i, _)) | i) and + n = bIdentityExpr and + ( + none() + or + result = getImmediateChildOfIdentityExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPointerToPointerExpr( + PointerToPointerExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPostfixOperatorDecl( + PostfixOperatorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bOperatorDecl, int n | + b = 0 and + bOperatorDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfOperatorDecl(e, i, _)) | i) and + n = bOperatorDecl and + ( + none() + or + result = getImmediateChildOfOperatorDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPostfixUnaryExpr( + PostfixUnaryExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bApplyExpr, int n | + b = 0 and + bApplyExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfApplyExpr(e, i, _)) | i) and + n = bApplyExpr and + ( + none() + or + result = getImmediateChildOfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPrefixOperatorDecl( + PrefixOperatorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bOperatorDecl, int n | + b = 0 and + bOperatorDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfOperatorDecl(e, i, _)) | i) and + n = bOperatorDecl and + ( + none() + or + result = getImmediateChildOfOperatorDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfPrefixUnaryExpr( + PrefixUnaryExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bApplyExpr, int n | + b = 0 and + bApplyExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfApplyExpr(e, i, _)) | i) and + n = bApplyExpr and + ( + none() + or + result = getImmediateChildOfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfProtocolMetatypeToObjectExpr( + ProtocolMetatypeToObjectExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfProtocolType( + ProtocolType e, int index, string partialPredicateCall + ) { + exists(int b, int bNominalType, int n | + b = 0 and + bNominalType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalType(e, i, _)) | i) and + n = bNominalType and + ( + none() + or + result = getImmediateChildOfNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfRegexLiteralExpr( + RegexLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLiteralExpr, int n | + b = 0 and + bLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLiteralExpr(e, i, _)) | i) and + n = bLiteralExpr and + ( + none() + or + result = getImmediateChildOfLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfRepeatWhileStmt( + RepeatWhileStmt e, int index, string partialPredicateCall + ) { + exists(int b, int bLabeledStmt, int n, int nCondition, int nBody | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nCondition = n + 1 and + nBody = nCondition + 1 and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateCondition() and partialPredicateCall = "Condition()" + or + index = nCondition and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfSelfApplyExpr( + SelfApplyExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bApplyExpr, int n, int nBase | + b = 0 and + bApplyExpr = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfApplyExpr(e, i, _)) | i) and + n = bApplyExpr and + nBase = n + 1 and + ( + none() + or + result = getImmediateChildOfApplyExpr(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBase() and partialPredicateCall = "Base()" + ) + ) + } + + private Element getImmediateChildOfStringToPointerExpr( + StringToPointerExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfStructType(StructType e, int index, string partialPredicateCall) { + exists(int b, int bNominalType, int n | + b = 0 and + bNominalType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalType(e, i, _)) | i) and + n = bNominalType and + ( + none() + or + result = getImmediateChildOfNominalType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSubscriptExpr( + SubscriptExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bLookupExpr, int n, int nArgument | + b = 0 and + bLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLookupExpr(e, i, _)) | i) and + n = bLookupExpr and + nArgument = n + 1 + max(int i | i = -1 or exists(e.getImmediateArgument(i)) | i) and + ( + none() + or + result = getImmediateChildOfLookupExpr(e, index - b, partialPredicateCall) + or + result = e.getImmediateArgument(index - n) and + partialPredicateCall = "Argument(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfSwitchStmt(SwitchStmt e, int index, string partialPredicateCall) { + exists(int b, int bLabeledStmt, int n, int nExpr, int nCase | + b = 0 and + bLabeledStmt = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfLabeledStmt(e, i, _)) | i) and + n = bLabeledStmt and + nExpr = n + 1 and + nCase = nExpr + 1 + max(int i | i = -1 or exists(e.getImmediateCase(i)) | i) and + ( + none() + or + result = getImmediateChildOfLabeledStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateExpr() and partialPredicateCall = "Expr()" + or + result = e.getImmediateCase(index - nExpr) and + partialPredicateCall = "Case(" + (index - nExpr).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfTryExpr(TryExpr e, int index, string partialPredicateCall) { + exists(int b, int bAnyTryExpr, int n | + b = 0 and + bAnyTryExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAnyTryExpr(e, i, _)) | i) and + n = bAnyTryExpr and + ( + none() + or + result = getImmediateChildOfAnyTryExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTypeDecl(TypeDecl e, int index, string partialPredicateCall) { + exists(int b, int bValueDecl, int n | + b = 0 and + bValueDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and + n = bValueDecl and + ( + none() + or + result = getImmediateChildOfValueDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnderlyingToOpaqueExpr( + UnderlyingToOpaqueExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnevaluatedInstanceExpr( + UnevaluatedInstanceExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedMemberChainResultExpr( + UnresolvedMemberChainResultExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bIdentityExpr, int n | + b = 0 and + bIdentityExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfIdentityExpr(e, i, _)) | i) and + n = bIdentityExpr and + ( + none() + or + result = getImmediateChildOfIdentityExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfUnresolvedTypeConversionExpr( + UnresolvedTypeConversionExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bImplicitConversionExpr, int n | + b = 0 and + bImplicitConversionExpr = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfImplicitConversionExpr(e, i, _)) | i) and + n = bImplicitConversionExpr and + ( + none() + or + result = getImmediateChildOfImplicitConversionExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfVariadicSequenceType( + VariadicSequenceType e, int index, string partialPredicateCall + ) { + exists(int b, int bUnarySyntaxSugarType, int n | + b = 0 and + bUnarySyntaxSugarType = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfUnarySyntaxSugarType(e, i, _)) | i) and + n = bUnarySyntaxSugarType and + ( + none() + or + result = getImmediateChildOfUnarySyntaxSugarType(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAbstractTypeParamDecl( + AbstractTypeParamDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bTypeDecl, int n | + b = 0 and + bTypeDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfTypeDecl(e, i, _)) | i) and + n = bTypeDecl and + ( + none() + or + result = getImmediateChildOfTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfBooleanLiteralExpr( + BooleanLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinLiteralExpr, int n | + b = 0 and + bBuiltinLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinLiteralExpr(e, i, _)) | i) and + n = bBuiltinLiteralExpr and + ( + none() + or + result = getImmediateChildOfBuiltinLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConditionalCheckedCastExpr( + ConditionalCheckedCastExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bCheckedCastExpr, int n | + b = 0 and + bCheckedCastExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCheckedCastExpr(e, i, _)) | i) and + n = bCheckedCastExpr and + ( + none() + or + result = getImmediateChildOfCheckedCastExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConstructorDecl( + ConstructorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractFunctionDecl, int n | + b = 0 and + bAbstractFunctionDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and + n = bAbstractFunctionDecl and + ( + none() + or + result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConstructorRefCallExpr( + ConstructorRefCallExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bSelfApplyExpr, int n | + b = 0 and + bSelfApplyExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSelfApplyExpr(e, i, _)) | i) and + n = bSelfApplyExpr and + ( + none() + or + result = getImmediateChildOfSelfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDestructorDecl( + DestructorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractFunctionDecl, int n | + b = 0 and + bAbstractFunctionDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and + n = bAbstractFunctionDecl and + ( + none() + or + result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDotSyntaxCallExpr( + DotSyntaxCallExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bSelfApplyExpr, int n | + b = 0 and + bSelfApplyExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfSelfApplyExpr(e, i, _)) | i) and + n = bSelfApplyExpr and + ( + none() + or + result = getImmediateChildOfSelfApplyExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDynamicMemberRefExpr( + DynamicMemberRefExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bDynamicLookupExpr, int n | + b = 0 and + bDynamicLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDynamicLookupExpr(e, i, _)) | i) and + n = bDynamicLookupExpr and + ( + none() + or + result = getImmediateChildOfDynamicLookupExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfDynamicSubscriptExpr( + DynamicSubscriptExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bDynamicLookupExpr, int n | + b = 0 and + bDynamicLookupExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfDynamicLookupExpr(e, i, _)) | i) and + n = bDynamicLookupExpr and + ( + none() + or + result = getImmediateChildOfDynamicLookupExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfForcedCheckedCastExpr( + ForcedCheckedCastExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bCheckedCastExpr, int n | + b = 0 and + bCheckedCastExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCheckedCastExpr(e, i, _)) | i) and + n = bCheckedCastExpr and + ( + none() + or + result = getImmediateChildOfCheckedCastExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFuncDecl(FuncDecl e, int index, string partialPredicateCall) { + exists(int b, int bAbstractFunctionDecl, int n | + b = 0 and + bAbstractFunctionDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractFunctionDecl(e, i, _)) | i) and + n = bAbstractFunctionDecl and + ( + none() + or + result = getImmediateChildOfAbstractFunctionDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGenericTypeDecl( + GenericTypeDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bGenericContext, int bTypeDecl, int n | + b = 0 and + bGenericContext = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and + bTypeDecl = + bGenericContext + 1 + + max(int i | i = -1 or exists(getImmediateChildOfTypeDecl(e, i, _)) | i) and + n = bTypeDecl and + ( + none() + or + result = getImmediateChildOfGenericContext(e, index - b, partialPredicateCall) + or + result = getImmediateChildOfTypeDecl(e, index - bGenericContext, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGuardStmt(GuardStmt e, int index, string partialPredicateCall) { + exists(int b, int bLabeledConditionalStmt, int n, int nBody | + b = 0 and + bLabeledConditionalStmt = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfLabeledConditionalStmt(e, i, _)) | i) and + n = bLabeledConditionalStmt and + nBody = n + 1 and + ( + none() + or + result = getImmediateChildOfLabeledConditionalStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfIfStmt(IfStmt e, int index, string partialPredicateCall) { + exists(int b, int bLabeledConditionalStmt, int n, int nThen, int nElse | + b = 0 and + bLabeledConditionalStmt = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfLabeledConditionalStmt(e, i, _)) | i) and + n = bLabeledConditionalStmt and + nThen = n + 1 and + nElse = nThen + 1 and + ( + none() + or + result = getImmediateChildOfLabeledConditionalStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateThen() and partialPredicateCall = "Then()" + or + index = nThen and result = e.getImmediateElse() and partialPredicateCall = "Else()" + ) + ) + } + + private Element getImmediateChildOfIsExpr(IsExpr e, int index, string partialPredicateCall) { + exists(int b, int bCheckedCastExpr, int n | + b = 0 and + bCheckedCastExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfCheckedCastExpr(e, i, _)) | i) and + n = bCheckedCastExpr and + ( + none() + or + result = getImmediateChildOfCheckedCastExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfMagicIdentifierLiteralExpr( + MagicIdentifierLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinLiteralExpr, int n | + b = 0 and + bBuiltinLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinLiteralExpr(e, i, _)) | i) and + n = bBuiltinLiteralExpr and + ( + none() + or + result = getImmediateChildOfBuiltinLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfModuleDecl(ModuleDecl e, int index, string partialPredicateCall) { + exists(int b, int bTypeDecl, int n | + b = 0 and + bTypeDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfTypeDecl(e, i, _)) | i) and + n = bTypeDecl and + ( + none() + or + result = getImmediateChildOfTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNumberLiteralExpr( + NumberLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinLiteralExpr, int n | + b = 0 and + bBuiltinLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinLiteralExpr(e, i, _)) | i) and + n = bBuiltinLiteralExpr and + ( + none() + or + result = getImmediateChildOfBuiltinLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfStringLiteralExpr( + StringLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bBuiltinLiteralExpr, int n | + b = 0 and + bBuiltinLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfBuiltinLiteralExpr(e, i, _)) | i) and + n = bBuiltinLiteralExpr and + ( + none() + or + result = getImmediateChildOfBuiltinLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfSubscriptDecl( + SubscriptDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractStorageDecl, int bGenericContext, int n, int nParam | + b = 0 and + bAbstractStorageDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractStorageDecl(e, i, _)) | i) and + bGenericContext = + bAbstractStorageDecl + 1 + + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and + n = bGenericContext and + nParam = n + 1 + max(int i | i = -1 or exists(e.getImmediateParam(i)) | i) and + ( + none() + or + result = getImmediateChildOfAbstractStorageDecl(e, index - b, partialPredicateCall) + or + result = + getImmediateChildOfGenericContext(e, index - bAbstractStorageDecl, partialPredicateCall) + or + result = e.getImmediateParam(index - n) and + partialPredicateCall = "Param(" + (index - n).toString() + ")" + ) + ) + } + + private Element getImmediateChildOfVarDecl(VarDecl e, int index, string partialPredicateCall) { + exists(int b, int bAbstractStorageDecl, int n | + b = 0 and + bAbstractStorageDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractStorageDecl(e, i, _)) | i) and + n = bAbstractStorageDecl and + ( + none() + or + result = getImmediateChildOfAbstractStorageDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfWhileStmt(WhileStmt e, int index, string partialPredicateCall) { + exists(int b, int bLabeledConditionalStmt, int n, int nBody | + b = 0 and + bLabeledConditionalStmt = + b + 1 + + max(int i | i = -1 or exists(getImmediateChildOfLabeledConditionalStmt(e, i, _)) | i) and + n = bLabeledConditionalStmt and + nBody = n + 1 and + ( + none() + or + result = getImmediateChildOfLabeledConditionalStmt(e, index - b, partialPredicateCall) + or + index = n and result = e.getImmediateBody() and partialPredicateCall = "Body()" + ) + ) + } + + private Element getImmediateChildOfAccessorDecl( + AccessorDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bFuncDecl, int n | + b = 0 and + bFuncDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFuncDecl(e, i, _)) | i) and + n = bFuncDecl and + ( + none() + or + result = getImmediateChildOfFuncDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfAssociatedTypeDecl( + AssociatedTypeDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractTypeParamDecl, int n | + b = 0 and + bAbstractTypeParamDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractTypeParamDecl(e, i, _)) | i) and + n = bAbstractTypeParamDecl and + ( + none() + or + result = getImmediateChildOfAbstractTypeParamDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConcreteFuncDecl( + ConcreteFuncDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bFuncDecl, int n | + b = 0 and + bFuncDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfFuncDecl(e, i, _)) | i) and + n = bFuncDecl and + ( + none() + or + result = getImmediateChildOfFuncDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfConcreteVarDecl( + ConcreteVarDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bVarDecl, int n | + b = 0 and + bVarDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfVarDecl(e, i, _)) | i) and + n = bVarDecl and + ( + none() + or + result = getImmediateChildOfVarDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfFloatLiteralExpr( + FloatLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bNumberLiteralExpr, int n | + b = 0 and + bNumberLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNumberLiteralExpr(e, i, _)) | i) and + n = bNumberLiteralExpr and + ( + none() + or + result = getImmediateChildOfNumberLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfGenericTypeParamDecl( + GenericTypeParamDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bAbstractTypeParamDecl, int n | + b = 0 and + bAbstractTypeParamDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAbstractTypeParamDecl(e, i, _)) | i) and + n = bAbstractTypeParamDecl and + ( + none() + or + result = getImmediateChildOfAbstractTypeParamDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfIntegerLiteralExpr( + IntegerLiteralExpr e, int index, string partialPredicateCall + ) { + exists(int b, int bNumberLiteralExpr, int n | + b = 0 and + bNumberLiteralExpr = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNumberLiteralExpr(e, i, _)) | i) and + n = bNumberLiteralExpr and + ( + none() + or + result = getImmediateChildOfNumberLiteralExpr(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfNominalTypeDecl( + NominalTypeDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bGenericTypeDecl, int bIterableDeclContext, int n | + b = 0 and + bGenericTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericTypeDecl(e, i, _)) | i) and + bIterableDeclContext = + bGenericTypeDecl + 1 + + max(int i | i = -1 or exists(getImmediateChildOfIterableDeclContext(e, i, _)) | i) and + n = bIterableDeclContext and + ( + none() + or + result = getImmediateChildOfGenericTypeDecl(e, index - b, partialPredicateCall) + or + result = + getImmediateChildOfIterableDeclContext(e, index - bGenericTypeDecl, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfOpaqueTypeDecl( + OpaqueTypeDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bGenericTypeDecl, int n | + b = 0 and + bGenericTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericTypeDecl(e, i, _)) | i) and + n = bGenericTypeDecl and + ( + none() + or + result = getImmediateChildOfGenericTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfParamDecl(ParamDecl e, int index, string partialPredicateCall) { + exists(int b, int bVarDecl, int n | + b = 0 and + bVarDecl = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfVarDecl(e, i, _)) | i) and + n = bVarDecl and + ( + none() + or + result = getImmediateChildOfVarDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfTypeAliasDecl( + TypeAliasDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bGenericTypeDecl, int n | + b = 0 and + bGenericTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericTypeDecl(e, i, _)) | i) and + n = bGenericTypeDecl and + ( + none() + or + result = getImmediateChildOfGenericTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfClassDecl(ClassDecl e, int index, string partialPredicateCall) { + exists(int b, int bNominalTypeDecl, int n | + b = 0 and + bNominalTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalTypeDecl(e, i, _)) | i) and + n = bNominalTypeDecl and + ( + none() + or + result = getImmediateChildOfNominalTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfEnumDecl(EnumDecl e, int index, string partialPredicateCall) { + exists(int b, int bNominalTypeDecl, int n | + b = 0 and + bNominalTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalTypeDecl(e, i, _)) | i) and + n = bNominalTypeDecl and + ( + none() + or + result = getImmediateChildOfNominalTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfProtocolDecl( + ProtocolDecl e, int index, string partialPredicateCall + ) { + exists(int b, int bNominalTypeDecl, int n | + b = 0 and + bNominalTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalTypeDecl(e, i, _)) | i) and + n = bNominalTypeDecl and + ( + none() + or + result = getImmediateChildOfNominalTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + private Element getImmediateChildOfStructDecl(StructDecl e, int index, string partialPredicateCall) { + exists(int b, int bNominalTypeDecl, int n | + b = 0 and + bNominalTypeDecl = + b + 1 + max(int i | i = -1 or exists(getImmediateChildOfNominalTypeDecl(e, i, _)) | i) and + n = bNominalTypeDecl and + ( + none() + or + result = getImmediateChildOfNominalTypeDecl(e, index - b, partialPredicateCall) + ) + ) + } + + cached + Element getImmediateChild(Element e, int index, string partialAccessor) { + // why does this look more complicated than it should? + // * none() simplifies generation, as we can append `or ...` without a special case for the first item + none() + or + result = getImmediateChildOfArgument(e, index, partialAccessor) + or + result = getImmediateChildOfComment(e, index, partialAccessor) + or + result = getImmediateChildOfConditionElement(e, index, partialAccessor) + or + result = getImmediateChildOfDbFile(e, index, partialAccessor) + or + result = getImmediateChildOfDbLocation(e, index, partialAccessor) + or + result = getImmediateChildOfDependentMemberType(e, index, partialAccessor) + or + result = getImmediateChildOfDynamicSelfType(e, index, partialAccessor) + or + result = getImmediateChildOfErrorType(e, index, partialAccessor) + or + result = getImmediateChildOfExistentialType(e, index, partialAccessor) + or + result = getImmediateChildOfIfConfigClause(e, index, partialAccessor) + or + result = getImmediateChildOfInOutType(e, index, partialAccessor) + or + result = getImmediateChildOfLValueType(e, index, partialAccessor) + or + result = getImmediateChildOfModuleType(e, index, partialAccessor) + or + result = getImmediateChildOfPlaceholderType(e, index, partialAccessor) + or + result = getImmediateChildOfProtocolCompositionType(e, index, partialAccessor) + or + result = getImmediateChildOfSilBlockStorageType(e, index, partialAccessor) + or + result = getImmediateChildOfSilBoxType(e, index, partialAccessor) + or + result = getImmediateChildOfSilFunctionType(e, index, partialAccessor) + or + result = getImmediateChildOfSilTokenType(e, index, partialAccessor) + or + result = getImmediateChildOfTupleType(e, index, partialAccessor) + or + result = getImmediateChildOfTypeVariableType(e, index, partialAccessor) + or + result = getImmediateChildOfUnknownFile(e, index, partialAccessor) + or + result = getImmediateChildOfUnknownLocation(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinBridgeObjectType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinDefaultActorStorageType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinExecutorType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinFloatType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinJobType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinNativeObjectType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinRawPointerType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinRawUnsafeContinuationType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinUnsafeValueBufferType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinVectorType(e, index, partialAccessor) + or + result = getImmediateChildOfCaseLabelItem(e, index, partialAccessor) + or + result = getImmediateChildOfExistentialMetatypeType(e, index, partialAccessor) + or + result = getImmediateChildOfFunctionType(e, index, partialAccessor) + or + result = getImmediateChildOfGenericFunctionType(e, index, partialAccessor) + or + result = getImmediateChildOfGenericTypeParamType(e, index, partialAccessor) + or + result = getImmediateChildOfMetatypeType(e, index, partialAccessor) + or + result = getImmediateChildOfParenType(e, index, partialAccessor) + or + result = getImmediateChildOfStmtCondition(e, index, partialAccessor) + or + result = getImmediateChildOfTypeAliasType(e, index, partialAccessor) + or + result = getImmediateChildOfTypeRepr(e, index, partialAccessor) + or + result = getImmediateChildOfUnboundGenericType(e, index, partialAccessor) + or + result = getImmediateChildOfUnmanagedStorageType(e, index, partialAccessor) + or + result = getImmediateChildOfUnownedStorageType(e, index, partialAccessor) + or + result = getImmediateChildOfWeakStorageType(e, index, partialAccessor) + or + result = getImmediateChildOfAnyPattern(e, index, partialAccessor) + or + result = getImmediateChildOfAppliedPropertyWrapperExpr(e, index, partialAccessor) + or + result = getImmediateChildOfArrowExpr(e, index, partialAccessor) + or + result = getImmediateChildOfAssignExpr(e, index, partialAccessor) + or + result = getImmediateChildOfBindOptionalExpr(e, index, partialAccessor) + or + result = getImmediateChildOfBindingPattern(e, index, partialAccessor) + or + result = getImmediateChildOfBoolPattern(e, index, partialAccessor) + or + result = getImmediateChildOfBraceStmt(e, index, partialAccessor) + or + result = getImmediateChildOfBreakStmt(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinIntegerLiteralType(e, index, partialAccessor) + or + result = getImmediateChildOfBuiltinIntegerType(e, index, partialAccessor) + or + result = getImmediateChildOfCaptureListExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCaseStmt(e, index, partialAccessor) + or + result = getImmediateChildOfCodeCompletionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfContinueStmt(e, index, partialAccessor) + or + result = getImmediateChildOfDeclRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDefaultArgumentExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDeferStmt(e, index, partialAccessor) + or + result = getImmediateChildOfDictionaryType(e, index, partialAccessor) + or + result = getImmediateChildOfDiscardAssignmentExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDotSyntaxBaseIgnoredExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDynamicTypeExpr(e, index, partialAccessor) + or + result = getImmediateChildOfEditorPlaceholderExpr(e, index, partialAccessor) + or + result = getImmediateChildOfEnumCaseDecl(e, index, partialAccessor) + or + result = getImmediateChildOfEnumElementPattern(e, index, partialAccessor) + or + result = getImmediateChildOfEnumIsCaseExpr(e, index, partialAccessor) + or + result = getImmediateChildOfErrorExpr(e, index, partialAccessor) + or + result = getImmediateChildOfExprPattern(e, index, partialAccessor) + or + result = getImmediateChildOfExtensionDecl(e, index, partialAccessor) + or + result = getImmediateChildOfFailStmt(e, index, partialAccessor) + or + result = getImmediateChildOfFallthroughStmt(e, index, partialAccessor) + or + result = getImmediateChildOfForceValueExpr(e, index, partialAccessor) + or + result = getImmediateChildOfIfConfigDecl(e, index, partialAccessor) + or + result = getImmediateChildOfIfExpr(e, index, partialAccessor) + or + result = getImmediateChildOfImportDecl(e, index, partialAccessor) + or + result = getImmediateChildOfInOutExpr(e, index, partialAccessor) + or + result = getImmediateChildOfIsPattern(e, index, partialAccessor) + or + result = getImmediateChildOfKeyPathApplicationExpr(e, index, partialAccessor) + or + result = getImmediateChildOfKeyPathDotExpr(e, index, partialAccessor) + or + result = getImmediateChildOfKeyPathExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLazyInitializerExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMakeTemporarilyEscapableExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMissingMemberDecl(e, index, partialAccessor) + or + result = getImmediateChildOfNamedPattern(e, index, partialAccessor) + or + result = getImmediateChildOfNestedArchetypeType(e, index, partialAccessor) + or + result = getImmediateChildOfObjCSelectorExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOneWayExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOpaqueTypeArchetypeType(e, index, partialAccessor) + or + result = getImmediateChildOfOpaqueValueExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOpenExistentialExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOpenedArchetypeType(e, index, partialAccessor) + or + result = getImmediateChildOfOptionalEvaluationExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOptionalSomePattern(e, index, partialAccessor) + or + result = getImmediateChildOfOtherConstructorDeclRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfParenPattern(e, index, partialAccessor) + or + result = getImmediateChildOfPatternBindingDecl(e, index, partialAccessor) + or + result = getImmediateChildOfPoundAssertStmt(e, index, partialAccessor) + or + result = getImmediateChildOfPoundDiagnosticDecl(e, index, partialAccessor) + or + result = getImmediateChildOfPrecedenceGroupDecl(e, index, partialAccessor) + or + result = getImmediateChildOfPrimaryArchetypeType(e, index, partialAccessor) + or + result = getImmediateChildOfPropertyWrapperValuePlaceholderExpr(e, index, partialAccessor) + or + result = getImmediateChildOfRebindSelfInConstructorExpr(e, index, partialAccessor) + or + result = getImmediateChildOfReturnStmt(e, index, partialAccessor) + or + result = getImmediateChildOfSequenceArchetypeType(e, index, partialAccessor) + or + result = getImmediateChildOfSequenceExpr(e, index, partialAccessor) + or + result = getImmediateChildOfSuperRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfTapExpr(e, index, partialAccessor) + or + result = getImmediateChildOfThrowStmt(e, index, partialAccessor) + or + result = getImmediateChildOfTopLevelCodeDecl(e, index, partialAccessor) + or + result = getImmediateChildOfTupleElementExpr(e, index, partialAccessor) + or + result = getImmediateChildOfTupleExpr(e, index, partialAccessor) + or + result = getImmediateChildOfTuplePattern(e, index, partialAccessor) + or + result = getImmediateChildOfTypeExpr(e, index, partialAccessor) + or + result = getImmediateChildOfTypedPattern(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedDeclRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedDotExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedMemberExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedPatternExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedSpecializeExpr(e, index, partialAccessor) + or + result = getImmediateChildOfVarargExpansionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfYieldStmt(e, index, partialAccessor) + or + result = getImmediateChildOfAnyHashableErasureExpr(e, index, partialAccessor) + or + result = getImmediateChildOfArchetypeToSuperExpr(e, index, partialAccessor) + or + result = getImmediateChildOfArrayExpr(e, index, partialAccessor) + or + result = getImmediateChildOfArraySliceType(e, index, partialAccessor) + or + result = getImmediateChildOfArrayToPointerExpr(e, index, partialAccessor) + or + result = getImmediateChildOfAutoClosureExpr(e, index, partialAccessor) + or + result = getImmediateChildOfAwaitExpr(e, index, partialAccessor) + or + result = getImmediateChildOfBinaryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfBoundGenericClassType(e, index, partialAccessor) + or + result = getImmediateChildOfBoundGenericEnumType(e, index, partialAccessor) + or + result = getImmediateChildOfBoundGenericStructType(e, index, partialAccessor) + or + result = getImmediateChildOfBridgeFromObjCExpr(e, index, partialAccessor) + or + result = getImmediateChildOfBridgeToObjCExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCallExpr(e, index, partialAccessor) + or + result = getImmediateChildOfClassMetatypeToObjectExpr(e, index, partialAccessor) + or + result = getImmediateChildOfClassType(e, index, partialAccessor) + or + result = getImmediateChildOfClosureExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCoerceExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCollectionUpcastConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfConditionalBridgeFromObjCExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCovariantFunctionConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfCovariantReturnConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDerivedToBaseExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDestructureTupleExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDictionaryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDifferentiableFunctionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDifferentiableFunctionExtractOriginalExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDoCatchStmt(e, index, partialAccessor) + or + result = getImmediateChildOfDoStmt(e, index, partialAccessor) + or + result = getImmediateChildOfDotSelfExpr(e, index, partialAccessor) + or + result = getImmediateChildOfEnumElementDecl(e, index, partialAccessor) + or + result = getImmediateChildOfEnumType(e, index, partialAccessor) + or + result = getImmediateChildOfErasureExpr(e, index, partialAccessor) + or + result = getImmediateChildOfExistentialMetatypeToObjectExpr(e, index, partialAccessor) + or + result = getImmediateChildOfForEachStmt(e, index, partialAccessor) + or + result = getImmediateChildOfForceTryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfForeignObjectConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfFunctionConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfInOutToPointerExpr(e, index, partialAccessor) + or + result = getImmediateChildOfInfixOperatorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfInjectIntoOptionalExpr(e, index, partialAccessor) + or + result = getImmediateChildOfInterpolatedStringLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLinearFunctionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLinearFunctionExtractOriginalExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLinearToDifferentiableFunctionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfLoadExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMemberRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMetatypeConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMethodRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfNilLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfObjectLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOptionalTryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOptionalType(e, index, partialAccessor) + or + result = getImmediateChildOfOverloadedDeclRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfParenExpr(e, index, partialAccessor) + or + result = getImmediateChildOfPointerToPointerExpr(e, index, partialAccessor) + or + result = getImmediateChildOfPostfixOperatorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfPostfixUnaryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfPrefixOperatorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfPrefixUnaryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfProtocolMetatypeToObjectExpr(e, index, partialAccessor) + or + result = getImmediateChildOfProtocolType(e, index, partialAccessor) + or + result = getImmediateChildOfRegexLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfRepeatWhileStmt(e, index, partialAccessor) + or + result = getImmediateChildOfStringToPointerExpr(e, index, partialAccessor) + or + result = getImmediateChildOfStructType(e, index, partialAccessor) + or + result = getImmediateChildOfSubscriptExpr(e, index, partialAccessor) + or + result = getImmediateChildOfSwitchStmt(e, index, partialAccessor) + or + result = getImmediateChildOfTryExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnderlyingToOpaqueExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnevaluatedInstanceExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedMemberChainResultExpr(e, index, partialAccessor) + or + result = getImmediateChildOfUnresolvedTypeConversionExpr(e, index, partialAccessor) + or + result = getImmediateChildOfVariadicSequenceType(e, index, partialAccessor) + or + result = getImmediateChildOfBooleanLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfConditionalCheckedCastExpr(e, index, partialAccessor) + or + result = getImmediateChildOfConstructorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfConstructorRefCallExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDestructorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfDotSyntaxCallExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDynamicMemberRefExpr(e, index, partialAccessor) + or + result = getImmediateChildOfDynamicSubscriptExpr(e, index, partialAccessor) + or + result = getImmediateChildOfForcedCheckedCastExpr(e, index, partialAccessor) + or + result = getImmediateChildOfGuardStmt(e, index, partialAccessor) + or + result = getImmediateChildOfIfStmt(e, index, partialAccessor) + or + result = getImmediateChildOfIsExpr(e, index, partialAccessor) + or + result = getImmediateChildOfMagicIdentifierLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfModuleDecl(e, index, partialAccessor) + or + result = getImmediateChildOfStringLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfSubscriptDecl(e, index, partialAccessor) + or + result = getImmediateChildOfWhileStmt(e, index, partialAccessor) + or + result = getImmediateChildOfAccessorDecl(e, index, partialAccessor) + or + result = getImmediateChildOfAssociatedTypeDecl(e, index, partialAccessor) + or + result = getImmediateChildOfConcreteFuncDecl(e, index, partialAccessor) + or + result = getImmediateChildOfConcreteVarDecl(e, index, partialAccessor) + or + result = getImmediateChildOfFloatLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfGenericTypeParamDecl(e, index, partialAccessor) + or + result = getImmediateChildOfIntegerLiteralExpr(e, index, partialAccessor) + or + result = getImmediateChildOfOpaqueTypeDecl(e, index, partialAccessor) + or + result = getImmediateChildOfParamDecl(e, index, partialAccessor) + or + result = getImmediateChildOfTypeAliasDecl(e, index, partialAccessor) + or + result = getImmediateChildOfClassDecl(e, index, partialAccessor) + or + result = getImmediateChildOfEnumDecl(e, index, partialAccessor) + or + result = getImmediateChildOfProtocolDecl(e, index, partialAccessor) + or + result = getImmediateChildOfStructDecl(e, index, partialAccessor) + } +} + +/** + * Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example + * if `e` has conversions, `getImmediateParent(e)` will give the innermost conversion in the hidden AST. + */ +Element getImmediateParent(Element e) { + // `unique` is used here to tell the optimizer that there is in fact only one result + // this is tested by the `library-tests/parent/no_double_parents.ql` test + result = unique(Element x | e = Impl::getImmediateChild(x, _, _) | x) +} + +/** + * Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. + */ +Element getImmediateChildAndAccessor(Element e, int index, string accessor) { + exists(string partialAccessor | + result = Impl::getImmediateChild(e, index, partialAccessor) and + accessor = "getImmediate" + partialAccessor + ) +} + +/** + * Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. + */ +Element getChildAndAccessor(Element e, int index, string accessor) { + exists(string partialAccessor | + result = Impl::getImmediateChild(e, index, partialAccessor).resolve() and + accessor = "get" + partialAccessor + ) +} diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index ac0feeac66f..a875fa25c79 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -6,10 +6,10 @@ module Raw { } class Callable extends @callable, Element { - ParamDecl getParam(int index) { callable_params(this, index, result) } - ParamDecl getSelfParam() { callable_self_params(this, result) } + ParamDecl getParam(int index) { callable_params(this, index, result) } + BraceStmt getBody() { callable_bodies(this, result) } } @@ -1398,6 +1398,10 @@ module Raw { predicate isBuiltinModule() { module_decl_is_builtin_module(this) } predicate isSystemModule() { module_decl_is_system_module(this) } + + ModuleDecl getImportedModule(int index) { module_decl_imported_modules(this, index, result) } + + ModuleDecl getExportedModule(int index) { module_decl_exported_modules(this, index, result) } } class NumberLiteralExpr extends @number_literal_expr, BuiltinLiteralExpr { } diff --git a/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll index c1997dba254..eb064816333 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll @@ -1,6 +1,7 @@ // generated by codegen/codegen.py private import codeql.swift.generated.Synth private import codeql.swift.generated.Raw +import codeql.swift.elements.decl.ModuleDecl import codeql.swift.elements.decl.TypeDecl class ModuleDeclBase extends Synth::TModuleDecl, TypeDecl { @@ -13,4 +14,34 @@ class ModuleDeclBase extends Synth::TModuleDecl, TypeDecl { predicate isSystemModule() { Synth::convertModuleDeclToRaw(this).(Raw::ModuleDecl).isSystemModule() } + + ModuleDecl getImmediateImportedModule(int index) { + result = + Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this) + .(Raw::ModuleDecl) + .getImportedModule(index)) + } + + final ModuleDecl getImportedModule(int index) { + result = getImmediateImportedModule(index).resolve() + } + + final ModuleDecl getAnImportedModule() { result = getImportedModule(_) } + + final int getNumberOfImportedModules() { result = count(getAnImportedModule()) } + + ModuleDecl getImmediateExportedModule(int index) { + result = + Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this) + .(Raw::ModuleDecl) + .getExportedModule(index)) + } + + final ModuleDecl getExportedModule(int index) { + result = getImmediateExportedModule(index).resolve() + } + + final ModuleDecl getAnExportedModule() { result = getExportedModule(_) } + + final int getNumberOfExportedModules() { result = count(getAnExportedModule()) } } diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index 74dc5296695..64cfe3f8335 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -166,6 +166,12 @@ nominal_type_decls( //dir=decl | @abstract_function_decl ; +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl ref +); + #keyset[id, index] callable_params( int id: @callable ref, @@ -173,12 +179,6 @@ callable_params( int param: @param_decl ref ); -#keyset[id] -callable_self_params( - int id: @callable ref, - int self_param: @param_decl ref -); - #keyset[id] callable_bodies( int id: @callable ref, @@ -2116,6 +2116,20 @@ module_decl_is_system_module( //dir=decl int id: @module_decl ref ); +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl ref +); + constructor_ref_call_exprs( //dir=expr unique int id: @constructor_ref_call_expr ); diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.expected index 1d8b00ccfa8..068e959b885 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.expected +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.expected @@ -1,2 +1,3 @@ | file://:0:0:0:0 | Foo | getModule: | file://:0:0:0:0 | Foo | getInterfaceType: | module | getName: | Foo | isBuiltinModule: | no | isSystemModule: | no | +| file://:0:0:0:0 | __ObjC | getModule: | file://:0:0:0:0 | __ObjC | getInterfaceType: | module<__ObjC> | getName: | __ObjC | isBuiltinModule: | no | isSystemModule: | no | | file://:0:0:0:0 | default_module_name | getModule: | file://:0:0:0:0 | default_module_name | getInterfaceType: | module | getName: | default_module_name | isBuiltinModule: | no | isSystemModule: | no | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getDefaultImportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getDefaultImportedModule.expected new file mode 100644 index 00000000000..7e29a9ce479 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getDefaultImportedModule.expected @@ -0,0 +1,7 @@ +| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | Foo | 1 | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | Foo | 2 | file://:0:0:0:0 | SwiftOnoneSupport | +| file://:0:0:0:0 | __ObjC | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | 1 | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | default_module_name | 2 | file://:0:0:0:0 | SwiftOnoneSupport | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected new file mode 100644 index 00000000000..a0865f2c40a --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected @@ -0,0 +1 @@ +| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql new file mode 100644 index 00000000000..012f1501665 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from ModuleDecl x, int index +where toBeTested(x) and not x.isUnknown() +select x, index, x.getExportedModule(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected new file mode 100644 index 00000000000..7e29a9ce479 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected @@ -0,0 +1,7 @@ +| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | Foo | 1 | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | Foo | 2 | file://:0:0:0:0 | SwiftOnoneSupport | +| file://:0:0:0:0 | __ObjC | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | 0 | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | 1 | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | default_module_name | 2 | file://:0:0:0:0 | SwiftOnoneSupport | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql new file mode 100644 index 00000000000..c5c8e83e23b --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql @@ -0,0 +1,7 @@ +// generated by codegen/codegen.py +import codeql.swift.elements +import TestUtils + +from ModuleDecl x, int index +where toBeTested(x) and not x.isUnknown() +select x, index, x.getImportedModule(index) diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/modules.swift b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/modules.swift index bb12ed63ddd..e72e772b808 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/modules.swift +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/modules.swift @@ -1 +1,2 @@ //codeql-extractor-options: -module-name Foo +@_exported import Swift diff --git a/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected b/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected index 5df760136c3..ba77afccac6 100644 --- a/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected +++ b/swift/ql/test/extractor-tests/generated/type/BuiltinType/BuiltinType.expected @@ -1,5 +1,4 @@ | Builtin.BridgeObject | getName: | Builtin.BridgeObject | getCanonicalType: | Builtin.BridgeObject | -| Builtin.DefaultActorStorage | getName: | Builtin.DefaultActorStorage | getCanonicalType: | Builtin.DefaultActorStorage | | Builtin.Executor | getName: | Builtin.Executor | getCanonicalType: | Builtin.Executor | | Builtin.FPIEEE32 | getName: | Builtin.FPIEEE32 | getCanonicalType: | Builtin.FPIEEE32 | | Builtin.FPIEEE64 | getName: | Builtin.FPIEEE64 | getCanonicalType: | Builtin.FPIEEE64 | @@ -8,4 +7,3 @@ | Builtin.NativeObject | getName: | Builtin.NativeObject | getCanonicalType: | Builtin.NativeObject | | Builtin.RawPointer | getName: | Builtin.RawPointer | getCanonicalType: | Builtin.RawPointer | | Builtin.RawUnsafeContinuation | getName: | Builtin.RawUnsafeContinuation | getCanonicalType: | Builtin.RawUnsafeContinuation | -| Builtin.UnsafeValueBuffer | getName: | Builtin.UnsafeValueBuffer | getCanonicalType: | Builtin.UnsafeValueBuffer | diff --git a/swift/ql/test/extractor-tests/generated/type/BuiltinType/builtin_types.swift b/swift/ql/test/extractor-tests/generated/type/BuiltinType/builtin_types.swift index 671a1b8eca7..a5d07267265 100644 --- a/swift/ql/test/extractor-tests/generated/type/BuiltinType/builtin_types.swift +++ b/swift/ql/test/extractor-tests/generated/type/BuiltinType/builtin_types.swift @@ -4,11 +4,9 @@ func foo( _: Builtin.FPIEEE32, _: Builtin.FPIEEE64, _: Builtin.BridgeObject, - _: Builtin.DefaultActorStorage, - _: Builtin.Executor, - _: Builtin.Job, _: Builtin.NativeObject, _: Builtin.RawPointer, - _: Builtin.RawUnsafeContinuation, - _: Builtin.UnsafeValueBuffer + _: Builtin.Executor, + _: Builtin.Job, + _: Builtin.RawUnsafeContinuation ) {} diff --git a/swift/ql/test/extractor-tests/generated/type/ModuleType/ModuleType.expected b/swift/ql/test/extractor-tests/generated/type/ModuleType/ModuleType.expected index 3a688c7fbd6..c354ac71377 100644 --- a/swift/ql/test/extractor-tests/generated/type/ModuleType/ModuleType.expected +++ b/swift/ql/test/extractor-tests/generated/type/ModuleType/ModuleType.expected @@ -1,2 +1,3 @@ | module | getName: | module | getCanonicalType: | module | getModule: | file://:0:0:0:0 | Foo | +| module<__ObjC> | getName: | module<__ObjC> | getCanonicalType: | module<__ObjC> | getModule: | file://:0:0:0:0 | __ObjC | | module | getName: | module | getCanonicalType: | module | getModule: | file://:0:0:0:0 | default_module_name | diff --git a/swift/ql/test/library-tests/parent/child.expected b/swift/ql/test/library-tests/parent/child.expected new file mode 100644 index 00000000000..f3eaf574b0b --- /dev/null +++ b/swift/ql/test/library-tests/parent/child.expected @@ -0,0 +1,1319 @@ +| declarations.swift:1:8:1:8 | init | 0 | getImmediateSelfParam() | declarations.swift:1:8:1:8 | self | +| declarations.swift:1:8:1:8 | init | 0 | getImmediateSelfParam() | declarations.swift:1:8:1:8 | self | +| declarations.swift:1:8:1:8 | init | 1 | getImmediateBody() | declarations.swift:1:8:1:8 | { ... } | +| declarations.swift:1:8:1:8 | init | 1 | getImmediateParam(0) | declarations.swift:1:8:1:8 | x | +| declarations.swift:1:8:1:8 | { ... } | 0 | getImmediateElement(0) | declarations.swift:1:8:1:8 | return | +| declarations.swift:2:3:2:11 | var ... = ... | 0 | getImmediateInit(0) | declarations.swift:2:11:2:11 | 11 | +| declarations.swift:2:3:2:11 | var ... = ... | 1 | getImmediatePattern(0) | declarations.swift:2:7:2:7 | x | +| declarations.swift:2:7:2:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:2:7:2:7 | self | +| declarations.swift:2:7:2:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:2:7:2:7 | { ... } | +| declarations.swift:2:7:2:7 | get | 0 | getImmediateSelfParam() | declarations.swift:2:7:2:7 | self | +| declarations.swift:2:7:2:7 | get | 1 | getImmediateBody() | declarations.swift:2:7:2:7 | { ... } | +| declarations.swift:2:7:2:7 | set | 0 | getImmediateSelfParam() | declarations.swift:2:7:2:7 | self | +| declarations.swift:2:7:2:7 | set | 1 | getImmediateParam(0) | declarations.swift:2:7:2:7 | value | +| declarations.swift:2:7:2:7 | set | 2 | getImmediateBody() | declarations.swift:2:7:2:7 | { ... } | +| declarations.swift:2:7:2:7 | x | 0 | getImmediateAccessorDecl(0) | declarations.swift:2:7:2:7 | get | +| declarations.swift:2:7:2:7 | x | 1 | getImmediateAccessorDecl(1) | declarations.swift:2:7:2:7 | set | +| declarations.swift:2:7:2:7 | x | 2 | getImmediateAccessorDecl(2) | declarations.swift:2:7:2:7 | (unnamed function decl) | +| declarations.swift:2:7:2:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:2:7:2:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:2:7:2:7 | yield ... | +| declarations.swift:2:7:2:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| declarations.swift:2:7:2:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:3:3:6:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:3:7:3:14 | ... as ... | +| declarations.swift:3:7:3:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:3:7:3:7 | self | +| declarations.swift:3:7:3:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:3:7:3:7 | { ... } | +| declarations.swift:3:7:3:7 | next | 0 | getImmediateAccessorDecl(0) | declarations.swift:4:5:4:24 | get | +| declarations.swift:3:7:3:7 | next | 1 | getImmediateAccessorDecl(1) | declarations.swift:5:5:5:38 | set | +| declarations.swift:3:7:3:7 | next | 2 | getImmediateAccessorDecl(2) | declarations.swift:3:7:3:7 | (unnamed function decl) | +| declarations.swift:3:7:3:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:3:7:3:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:3:7:3:7 | yield ... | +| declarations.swift:3:7:3:14 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:3:7:3:7 | next | +| declarations.swift:3:7:3:14 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:3:14:3:14 | Int | +| declarations.swift:4:5:4:24 | get | 0 | getImmediateSelfParam() | declarations.swift:4:5:4:5 | self | +| declarations.swift:4:5:4:24 | get | 1 | getImmediateBody() | declarations.swift:4:9:4:24 | { ... } | +| declarations.swift:4:9:4:24 | { ... } | 0 | getImmediateElement(0) | declarations.swift:4:11:4:22 | return ... | +| declarations.swift:4:11:4:22 | return ... | 0 | getImmediateResult() | declarations.swift:4:18:4:22 | ... .+(_:_:) ... | +| declarations.swift:4:18:4:18 | .x | 0 | getImmediateBase() | declarations.swift:4:18:4:18 | self | +| declarations.swift:4:18:4:22 | ... .+(_:_:) ... | 0 | getImmediateFunction() | declarations.swift:4:20:4:20 | .+(_:_:) | +| declarations.swift:4:20:4:20 | .+(_:_:) | 0 | getImmediateBase() | declarations.swift:4:20:4:20 | Int.Type | +| declarations.swift:4:20:4:20 | Int.Type | 0 | getImmediateTypeRepr() | declarations.swift:4:20:4:20 | Int | +| declarations.swift:5:5:5:38 | set | 0 | getImmediateSelfParam() | declarations.swift:5:5:5:5 | self | +| declarations.swift:5:5:5:38 | set | 1 | getImmediateParam(0) | declarations.swift:5:9:5:9 | newValue | +| declarations.swift:5:5:5:38 | set | 2 | getImmediateBody() | declarations.swift:5:19:5:38 | { ... } | +| declarations.swift:5:19:5:38 | { ... } | 0 | getImmediateElement(0) | declarations.swift:5:21:5:36 | ... = ... | +| declarations.swift:5:21:5:21 | .x | 0 | getImmediateBase() | declarations.swift:5:21:5:21 | self | +| declarations.swift:5:21:5:36 | ... = ... | 0 | getImmediateDest() | declarations.swift:5:21:5:21 | .x | +| declarations.swift:5:21:5:36 | ... = ... | 1 | getImmediateSource() | declarations.swift:5:25:5:36 | ... .-(_:_:) ... | +| declarations.swift:5:25:5:36 | ... .-(_:_:) ... | 0 | getImmediateFunction() | declarations.swift:5:34:5:34 | .-(_:_:) | +| declarations.swift:5:34:5:34 | .-(_:_:) | 0 | getImmediateBase() | declarations.swift:5:34:5:34 | Int.Type | +| declarations.swift:5:34:5:34 | Int.Type | 0 | getImmediateTypeRepr() | declarations.swift:5:34:5:34 | Int | +| declarations.swift:9:7:9:7 | deinit | 0 | getImmediateSelfParam() | declarations.swift:9:7:9:7 | self | +| declarations.swift:9:7:9:7 | deinit | 1 | getImmediateBody() | declarations.swift:9:7:9:7 | { ... } | +| declarations.swift:9:7:9:7 | init | 0 | getImmediateSelfParam() | declarations.swift:9:7:9:7 | self | +| declarations.swift:9:7:9:7 | init | 1 | getImmediateBody() | declarations.swift:9:7:9:7 | { ... } | +| declarations.swift:9:7:9:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:9:7:9:7 | return | +| declarations.swift:9:13:9:30 | var ... = ... | 0 | getImmediateInit(0) | declarations.swift:9:30:9:30 | 1.3 | +| declarations.swift:9:13:9:30 | var ... = ... | 1 | getImmediatePattern(0) | declarations.swift:9:17:9:21 | ... as ... | +| declarations.swift:9:17:9:17 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:9:17:9:17 | self | +| declarations.swift:9:17:9:17 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:9:17:9:17 | { ... } | +| declarations.swift:9:17:9:17 | get | 0 | getImmediateSelfParam() | declarations.swift:9:17:9:17 | self | +| declarations.swift:9:17:9:17 | get | 1 | getImmediateBody() | declarations.swift:9:17:9:17 | { ... } | +| declarations.swift:9:17:9:17 | set | 0 | getImmediateSelfParam() | declarations.swift:9:17:9:17 | self | +| declarations.swift:9:17:9:17 | set | 1 | getImmediateParam(0) | declarations.swift:9:17:9:17 | value | +| declarations.swift:9:17:9:17 | set | 2 | getImmediateBody() | declarations.swift:9:17:9:17 | { ... } | +| declarations.swift:9:17:9:17 | x | 0 | getImmediateAccessorDecl(0) | declarations.swift:9:17:9:17 | get | +| declarations.swift:9:17:9:17 | x | 1 | getImmediateAccessorDecl(1) | declarations.swift:9:17:9:17 | set | +| declarations.swift:9:17:9:17 | x | 2 | getImmediateAccessorDecl(2) | declarations.swift:9:17:9:17 | (unnamed function decl) | +| declarations.swift:9:17:9:17 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:9:17:9:17 | { ... } | 0 | getImmediateElement(0) | declarations.swift:9:17:9:17 | yield ... | +| declarations.swift:9:17:9:17 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| declarations.swift:9:17:9:17 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:9:17:9:21 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:9:17:9:17 | x | +| declarations.swift:9:17:9:21 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:9:21:9:21 | Double | +| declarations.swift:12:5:12:18 | case ... | 0 | getImmediateElement(0) | declarations.swift:12:10:12:10 | value1 | +| declarations.swift:12:5:12:18 | case ... | 1 | getImmediateElement(1) | declarations.swift:12:18:12:18 | value2 | +| declarations.swift:13:5:13:26 | case ... | 0 | getImmediateElement(0) | declarations.swift:13:10:13:10 | value3 | +| declarations.swift:13:5:13:26 | case ... | 1 | getImmediateElement(1) | declarations.swift:13:18:13:18 | value4 | +| declarations.swift:13:5:13:26 | case ... | 2 | getImmediateElement(2) | declarations.swift:13:26:13:26 | value5 | +| declarations.swift:17:5:17:22 | case ... | 0 | getImmediateElement(0) | declarations.swift:17:10:17:22 | nodata1 | +| declarations.swift:17:10:17:22 | nodata1 | 0 | getImmediateParam(0) | declarations.swift:17:18:17:18 | _ | +| declarations.swift:18:5:18:21 | case ... | 0 | getImmediateElement(0) | declarations.swift:18:10:18:21 | intdata | +| declarations.swift:18:10:18:21 | intdata | 0 | getImmediateParam(0) | declarations.swift:18:18:18:18 | _ | +| declarations.swift:19:5:19:35 | case ... | 0 | getImmediateElement(0) | declarations.swift:19:10:19:35 | tuple | +| declarations.swift:19:10:19:35 | tuple | 0 | getImmediateParam(0) | declarations.swift:19:16:19:16 | _ | +| declarations.swift:19:10:19:35 | tuple | 1 | getImmediateParam(1) | declarations.swift:19:21:19:21 | _ | +| declarations.swift:19:10:19:35 | tuple | 2 | getImmediateParam(2) | declarations.swift:19:29:19:29 | _ | +| declarations.swift:23:5:23:39 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:23:9:23:25 | ... as ... | +| declarations.swift:23:9:23:9 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:23:9:23:9 | self | +| declarations.swift:23:9:23:9 | mustBeSettable | 0 | getImmediateAccessorDecl(0) | declarations.swift:23:31:23:31 | get | +| declarations.swift:23:9:23:9 | mustBeSettable | 1 | getImmediateAccessorDecl(1) | declarations.swift:23:35:23:35 | set | +| declarations.swift:23:9:23:9 | mustBeSettable | 2 | getImmediateAccessorDecl(2) | declarations.swift:23:9:23:9 | (unnamed function decl) | +| declarations.swift:23:9:23:25 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:23:9:23:9 | mustBeSettable | +| declarations.swift:23:9:23:25 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:23:25:23:25 | Int | +| declarations.swift:23:31:23:31 | get | 0 | getImmediateSelfParam() | declarations.swift:23:31:23:31 | self | +| declarations.swift:23:35:23:35 | set | 0 | getImmediateSelfParam() | declarations.swift:23:35:23:35 | self | +| declarations.swift:23:35:23:35 | set | 1 | getImmediateParam(0) | declarations.swift:23:35:23:35 | newValue | +| declarations.swift:24:5:24:44 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:24:9:24:34 | ... as ... | +| declarations.swift:24:9:24:9 | doesNotNeedToBeSettable | 0 | getImmediateAccessorDecl(0) | declarations.swift:24:40:24:40 | get | +| declarations.swift:24:9:24:34 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:24:9:24:9 | doesNotNeedToBeSettable | +| declarations.swift:24:9:24:34 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:24:34:24:34 | Int | +| declarations.swift:24:40:24:40 | get | 0 | getImmediateSelfParam() | declarations.swift:24:40:24:40 | self | +| declarations.swift:25:5:25:22 | random() | 0 | getImmediateSelfParam() | declarations.swift:25:10:25:10 | self | +| declarations.swift:28:1:28:37 | a_function(a_parameter:) | 1 | getImmediateParam(0) | declarations.swift:28:17:28:31 | a_parameter | +| declarations.swift:28:1:28:37 | a_function(a_parameter:) | 2 | getImmediateBody() | declarations.swift:28:36:28:37 | { ... } | +| declarations.swift:30:1:30:18 | var ... = ... | 0 | getImmediateInit(0) | declarations.swift:30:18:30:18 | 42 | +| declarations.swift:30:1:30:18 | var ... = ... | 1 | getImmediatePattern(0) | declarations.swift:30:5:30:5 | a_variable | +| declarations.swift:30:1:30:18 | { ... } | 0 | getImmediateBody() | declarations.swift:30:1:30:18 | { ... } | +| declarations.swift:30:1:30:18 | { ... } | 0 | getImmediateElement(0) | declarations.swift:30:1:30:18 | var ... = ... | +| declarations.swift:31:1:36:1 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:31:5:31:18 | ... as ... | +| declarations.swift:31:1:36:1 | { ... } | 0 | getImmediateBody() | declarations.swift:31:1:36:1 | { ... } | +| declarations.swift:31:1:36:1 | { ... } | 0 | getImmediateElement(0) | declarations.swift:31:1:36:1 | var ... = ... | +| declarations.swift:31:5:31:5 | a_property | 0 | getImmediateAccessorDecl(0) | declarations.swift:32:3:34:3 | get | +| declarations.swift:31:5:31:5 | a_property | 1 | getImmediateAccessorDecl(1) | declarations.swift:35:3:35:18 | set | +| declarations.swift:31:5:31:18 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:31:5:31:5 | a_property | +| declarations.swift:31:5:31:18 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:31:18:31:18 | String | +| declarations.swift:32:3:34:3 | get | 1 | getImmediateBody() | declarations.swift:32:7:34:3 | { ... } | +| declarations.swift:32:7:34:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:33:5:33:12 | return ... | +| declarations.swift:33:5:33:12 | return ... | 0 | getImmediateResult() | declarations.swift:33:12:33:12 | here | +| declarations.swift:35:3:35:18 | set | 1 | getImmediateParam(0) | declarations.swift:35:7:35:7 | newValue | +| declarations.swift:35:3:35:18 | set | 2 | getImmediateBody() | declarations.swift:35:17:35:18 | { ... } | +| declarations.swift:38:1:38:33 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | declarations.swift:38:1:38:1 | print(_:separator:terminator:) | +| declarations.swift:38:1:38:33 | { ... } | 0 | getImmediateBody() | declarations.swift:38:1:38:33 | { ... } | +| declarations.swift:38:1:38:33 | { ... } | 0 | getImmediateElement(0) | declarations.swift:38:1:38:33 | call to print(_:separator:terminator:) | +| declarations.swift:38:7:38:7 | (Any) ... | 0 | getImmediateSubExpr() | declarations.swift:38:7:38:7 | some top level statement | +| declarations.swift:38:7:38:7 | [...] | 0 | getImmediateElement(0) | declarations.swift:38:7:38:7 | (Any) ... | +| declarations.swift:38:7:38:7 | [...] | 0 | getImmediateSubExpr() | declarations.swift:38:7:38:7 | [...] | +| declarations.swift:41:3:41:14 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:41:7:41:14 | ... as ... | +| declarations.swift:41:7:41:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:41:7:41:7 | self | +| declarations.swift:41:7:41:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:41:7:41:7 | { ... } | +| declarations.swift:41:7:41:7 | field | 0 | getImmediateAccessorDecl(0) | declarations.swift:41:7:41:7 | get | +| declarations.swift:41:7:41:7 | field | 1 | getImmediateAccessorDecl(1) | declarations.swift:41:7:41:7 | set | +| declarations.swift:41:7:41:7 | field | 2 | getImmediateAccessorDecl(2) | declarations.swift:41:7:41:7 | (unnamed function decl) | +| declarations.swift:41:7:41:7 | get | 0 | getImmediateSelfParam() | declarations.swift:41:7:41:7 | self | +| declarations.swift:41:7:41:7 | get | 1 | getImmediateBody() | declarations.swift:41:7:41:7 | { ... } | +| declarations.swift:41:7:41:7 | set | 0 | getImmediateSelfParam() | declarations.swift:41:7:41:7 | self | +| declarations.swift:41:7:41:7 | set | 1 | getImmediateParam(0) | declarations.swift:41:7:41:7 | value | +| declarations.swift:41:7:41:7 | set | 2 | getImmediateBody() | declarations.swift:41:7:41:7 | { ... } | +| declarations.swift:41:7:41:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:41:7:41:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:41:7:41:7 | yield ... | +| declarations.swift:41:7:41:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| declarations.swift:41:7:41:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:41:7:41:14 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:41:7:41:7 | field | +| declarations.swift:41:7:41:14 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:41:14:41:14 | Int | +| declarations.swift:42:3:44:3 | init | 0 | getImmediateSelfParam() | declarations.swift:42:3:42:3 | self | +| declarations.swift:42:3:44:3 | init | 1 | getImmediateBody() | declarations.swift:42:10:44:3 | { ... } | +| declarations.swift:42:10:44:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:43:5:43:13 | ... = ... | +| declarations.swift:42:10:44:3 | { ... } | 1 | getImmediateElement(1) | declarations.swift:44:3:44:3 | return | +| declarations.swift:43:5:43:5 | .field | 0 | getImmediateBase() | declarations.swift:43:5:43:5 | self | +| declarations.swift:43:5:43:13 | ... = ... | 0 | getImmediateDest() | declarations.swift:43:5:43:5 | .field | +| declarations.swift:43:5:43:13 | ... = ... | 1 | getImmediateSource() | declarations.swift:43:13:43:13 | 10 | +| declarations.swift:46:3:48:3 | deinit | 0 | getImmediateSelfParam() | declarations.swift:46:3:46:3 | self | +| declarations.swift:46:3:48:3 | deinit | 1 | getImmediateBody() | declarations.swift:46:10:48:3 | { ... } | +| declarations.swift:46:10:48:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:47:5:47:13 | ... = ... | +| declarations.swift:47:5:47:5 | .field | 0 | getImmediateBase() | declarations.swift:47:5:47:5 | self | +| declarations.swift:47:5:47:13 | ... = ... | 0 | getImmediateDest() | declarations.swift:47:5:47:5 | .field | +| declarations.swift:47:5:47:13 | ... = ... | 1 | getImmediateSource() | declarations.swift:47:13:47:13 | 0 | +| declarations.swift:50:3:52:3 | +-(_:) | 0 | getImmediateSelfParam() | declarations.swift:50:22:50:22 | self | +| declarations.swift:50:3:52:3 | +-(_:) | 1 | getImmediateParam(0) | declarations.swift:50:26:50:33 | other | +| declarations.swift:50:3:52:3 | +-(_:) | 2 | getImmediateBody() | declarations.swift:50:45:52:3 | { ... } | +| declarations.swift:50:45:52:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:51:5:51:12 | return ... | +| declarations.swift:51:5:51:12 | return ... | 0 | getImmediateResult() | declarations.swift:51:12:51:12 | other | +| declarations.swift:68:25:68:25 | init | 0 | getImmediateSelfParam() | declarations.swift:68:25:68:25 | self | +| declarations.swift:68:25:68:25 | init | 1 | getImmediateBody() | declarations.swift:68:25:68:25 | { ... } | +| declarations.swift:68:25:68:25 | { ... } | 0 | getImmediateElement(0) | declarations.swift:68:25:68:25 | return | +| declarations.swift:69:3:73:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:69:7:69:21 | ... as ... | +| declarations.swift:69:7:69:7 | wrappedValue | 0 | getImmediateAccessorDecl(0) | declarations.swift:70:5:72:5 | get | +| declarations.swift:69:7:69:21 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:69:7:69:7 | wrappedValue | +| declarations.swift:69:7:69:21 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:69:21:69:21 | Int | +| declarations.swift:70:5:72:5 | get | 0 | getImmediateSelfParam() | declarations.swift:70:5:70:5 | self | +| declarations.swift:70:5:72:5 | get | 1 | getImmediateBody() | declarations.swift:70:9:72:5 | { ... } | +| declarations.swift:70:9:72:5 | { ... } | 0 | getImmediateElement(0) | declarations.swift:71:7:71:14 | return ... | +| declarations.swift:71:7:71:14 | return ... | 0 | getImmediateResult() | declarations.swift:71:14:71:14 | 0 | +| declarations.swift:76:1:79:1 | foo() | 1 | getImmediateBody() | declarations.swift:76:19:79:1 | { ... } | +| declarations.swift:76:19:79:1 | { ... } | 0 | getImmediateElement(0) | declarations.swift:77:16:77:23 | var ... = ... | +| declarations.swift:76:19:79:1 | { ... } | 1 | getImmediateElement(1) | declarations.swift:77:20:77:20 | x | +| declarations.swift:76:19:79:1 | { ... } | 2 | getImmediateElement(2) | declarations.swift:78:3:78:10 | return ... | +| declarations.swift:77:4:77:4 | ZeroWrapper.Type | 0 | getImmediateTypeRepr() | declarations.swift:77:4:77:4 | ZeroWrapper | +| declarations.swift:77:4:77:4 | call to init | 0 | getImmediateFunction() | declarations.swift:77:4:77:4 | call to init | +| declarations.swift:77:4:77:4 | call to init | 0 | getImmediateFunction() | declarations.swift:77:4:77:4 | init | +| declarations.swift:77:4:77:4 | call to init | 2 | getImmediateBase() | declarations.swift:77:4:77:4 | ZeroWrapper.Type | +| declarations.swift:77:16:77:23 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:77:20:77:23 | ... as ... | +| declarations.swift:77:20:77:20 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:77:20:77:20 | _x | +| declarations.swift:77:20:77:20 | get | 1 | getImmediateBody() | declarations.swift:77:20:77:20 | { ... } | +| declarations.swift:77:20:77:20 | x | 0 | getImmediateAccessorDecl(0) | declarations.swift:77:20:77:20 | get | +| declarations.swift:77:20:77:20 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:77:20:77:23 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:77:20:77:20 | x | +| declarations.swift:77:20:77:23 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:77:23:77:23 | Int | +| declarations.swift:78:3:78:10 | return ... | 0 | getImmediateResult() | declarations.swift:78:10:78:10 | x | +| declarations.swift:81:8:81:8 | init | 0 | getImmediateSelfParam() | declarations.swift:81:8:81:8 | self | +| declarations.swift:81:8:81:8 | init | 1 | getImmediateParam(0) | declarations.swift:81:8:81:8 | normalField | +| declarations.swift:81:8:81:8 | init | 2 | getImmediateParam(1) | declarations.swift:81:8:81:8 | hasWillSet1 | +| declarations.swift:81:8:81:8 | init | 3 | getImmediateParam(2) | declarations.swift:81:8:81:8 | hasWillSet2 | +| declarations.swift:81:8:81:8 | init | 4 | getImmediateParam(3) | declarations.swift:81:8:81:8 | hasDidSet1 | +| declarations.swift:81:8:81:8 | init | 5 | getImmediateParam(4) | declarations.swift:81:8:81:8 | hasDidSet2 | +| declarations.swift:81:8:81:8 | init | 6 | getImmediateParam(5) | declarations.swift:81:8:81:8 | hasBoth | +| declarations.swift:82:3:87:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:82:7:82:22 | ... as ... | +| declarations.swift:82:7:82:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:82:7:82:7 | self | +| declarations.swift:82:7:82:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:82:7:82:7 | { ... } | +| declarations.swift:82:7:82:7 | settableField | 0 | getImmediateAccessorDecl(0) | declarations.swift:83:5:83:11 | set | +| declarations.swift:82:7:82:7 | settableField | 1 | getImmediateAccessorDecl(1) | declarations.swift:84:5:86:5 | get | +| declarations.swift:82:7:82:7 | settableField | 2 | getImmediateAccessorDecl(2) | declarations.swift:82:7:82:7 | (unnamed function decl) | +| declarations.swift:82:7:82:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:82:7:82:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:82:7:82:7 | yield ... | +| declarations.swift:82:7:82:22 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:82:7:82:7 | settableField | +| declarations.swift:82:7:82:22 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:82:22:82:22 | Int | +| declarations.swift:83:5:83:11 | set | 0 | getImmediateSelfParam() | declarations.swift:83:5:83:5 | self | +| declarations.swift:83:5:83:11 | set | 1 | getImmediateParam(0) | declarations.swift:83:5:83:5 | newValue | +| declarations.swift:83:5:83:11 | set | 2 | getImmediateBody() | declarations.swift:83:9:83:11 | { ... } | +| declarations.swift:84:5:86:5 | get | 0 | getImmediateSelfParam() | declarations.swift:84:5:84:5 | self | +| declarations.swift:84:5:86:5 | get | 1 | getImmediateBody() | declarations.swift:84:9:86:5 | { ... } | +| declarations.swift:84:9:86:5 | { ... } | 0 | getImmediateElement(0) | declarations.swift:85:7:85:14 | return ... | +| declarations.swift:85:7:85:14 | return ... | 0 | getImmediateResult() | declarations.swift:85:14:85:14 | 0 | +| declarations.swift:91:3:93:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:91:7:91:23 | ... as ... | +| declarations.swift:91:7:91:7 | readOnlyField1 | 0 | getImmediateAccessorDecl(0) | declarations.swift:91:27:93:3 | get | +| declarations.swift:91:7:91:23 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:91:7:91:7 | readOnlyField1 | +| declarations.swift:91:7:91:23 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:91:23:91:23 | Int | +| declarations.swift:91:27:93:3 | get | 0 | getImmediateSelfParam() | declarations.swift:91:27:91:27 | self | +| declarations.swift:91:27:93:3 | get | 1 | getImmediateBody() | declarations.swift:91:27:93:3 | { ... } | +| declarations.swift:91:27:93:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:92:5:92:12 | return ... | +| declarations.swift:92:5:92:12 | return ... | 0 | getImmediateResult() | declarations.swift:92:12:92:12 | 0 | +| declarations.swift:96:3:100:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:96:7:96:23 | ... as ... | +| declarations.swift:96:7:96:7 | readOnlyField2 | 0 | getImmediateAccessorDecl(0) | declarations.swift:97:5:99:5 | get | +| declarations.swift:96:7:96:23 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:96:7:96:7 | readOnlyField2 | +| declarations.swift:96:7:96:23 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:96:23:96:23 | Int | +| declarations.swift:97:5:99:5 | get | 0 | getImmediateSelfParam() | declarations.swift:97:5:97:5 | self | +| declarations.swift:97:5:99:5 | get | 1 | getImmediateBody() | declarations.swift:97:9:99:5 | { ... } | +| declarations.swift:97:9:99:5 | { ... } | 0 | getImmediateElement(0) | declarations.swift:98:7:98:14 | return ... | +| declarations.swift:98:7:98:14 | return ... | 0 | getImmediateResult() | declarations.swift:98:14:98:14 | 0 | +| declarations.swift:102:3:102:21 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:102:7:102:21 | ... as ... | +| declarations.swift:102:7:102:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:102:7:102:7 | self | +| declarations.swift:102:7:102:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:102:7:102:7 | { ... } | +| declarations.swift:102:7:102:7 | get | 0 | getImmediateSelfParam() | declarations.swift:102:7:102:7 | self | +| declarations.swift:102:7:102:7 | get | 1 | getImmediateBody() | declarations.swift:102:7:102:7 | { ... } | +| declarations.swift:102:7:102:7 | normalField | 0 | getImmediateAccessorDecl(0) | declarations.swift:102:7:102:7 | get | +| declarations.swift:102:7:102:7 | normalField | 1 | getImmediateAccessorDecl(1) | declarations.swift:102:7:102:7 | set | +| declarations.swift:102:7:102:7 | normalField | 2 | getImmediateAccessorDecl(2) | declarations.swift:102:7:102:7 | (unnamed function decl) | +| declarations.swift:102:7:102:7 | set | 0 | getImmediateSelfParam() | declarations.swift:102:7:102:7 | self | +| declarations.swift:102:7:102:7 | set | 1 | getImmediateParam(0) | declarations.swift:102:7:102:7 | value | +| declarations.swift:102:7:102:7 | set | 2 | getImmediateBody() | declarations.swift:102:7:102:7 | { ... } | +| declarations.swift:102:7:102:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:102:7:102:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:102:7:102:7 | yield ... | +| declarations.swift:102:7:102:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| declarations.swift:102:7:102:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:102:7:102:21 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:102:7:102:7 | normalField | +| declarations.swift:102:7:102:21 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:102:21:102:21 | Int | +| declarations.swift:104:3:104:3 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:104:3:104:3 | self | +| declarations.swift:104:3:104:3 | (unnamed function decl) | 1 | getImmediateParam(0) | file://:0:0:0:0 | x | +| declarations.swift:104:3:104:3 | (unnamed function decl) | 2 | getImmediateBody() | declarations.swift:104:3:104:3 | { ... } | +| declarations.swift:104:3:104:3 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:104:3:104:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:104:3:104:3 | yield ... | +| declarations.swift:104:3:109:3 | subscript ... | 0 | getImmediateAccessorDecl(0) | declarations.swift:105:5:107:5 | get | +| declarations.swift:104:3:109:3 | subscript ... | 1 | getImmediateAccessorDecl(1) | declarations.swift:108:5:108:11 | set | +| declarations.swift:104:3:109:3 | subscript ... | 2 | getImmediateAccessorDecl(2) | declarations.swift:104:3:104:3 | (unnamed function decl) | +| declarations.swift:104:3:109:3 | subscript ... | 3 | getImmediateParam(0) | declarations.swift:104:13:104:16 | x | +| declarations.swift:105:5:107:5 | get | 0 | getImmediateSelfParam() | declarations.swift:105:5:105:5 | self | +| declarations.swift:105:5:107:5 | get | 1 | getImmediateParam(0) | declarations.swift:104:13:104:13 | x | +| declarations.swift:105:5:107:5 | get | 2 | getImmediateBody() | declarations.swift:105:9:107:5 | { ... } | +| declarations.swift:105:9:107:5 | { ... } | 0 | getImmediateElement(0) | declarations.swift:106:7:106:14 | return ... | +| declarations.swift:106:7:106:14 | return ... | 0 | getImmediateResult() | declarations.swift:106:14:106:14 | 0 | +| declarations.swift:108:5:108:11 | set | 0 | getImmediateSelfParam() | declarations.swift:108:5:108:5 | self | +| declarations.swift:108:5:108:11 | set | 1 | getImmediateParam(0) | declarations.swift:108:5:108:5 | newValue | +| declarations.swift:108:5:108:11 | set | 2 | getImmediateParam(1) | declarations.swift:104:13:104:13 | x | +| declarations.swift:108:5:108:11 | set | 3 | getImmediateBody() | declarations.swift:108:9:108:11 | { ... } | +| declarations.swift:111:3:113:3 | subscript ... | 0 | getImmediateAccessorDecl(0) | declarations.swift:111:37:113:3 | get | +| declarations.swift:111:3:113:3 | subscript ... | 1 | getImmediateParam(0) | declarations.swift:111:13:111:16 | x | +| declarations.swift:111:3:113:3 | subscript ... | 2 | getImmediateParam(1) | declarations.swift:111:21:111:25 | y | +| declarations.swift:111:37:113:3 | get | 0 | getImmediateSelfParam() | declarations.swift:111:37:111:37 | self | +| declarations.swift:111:37:113:3 | get | 1 | getImmediateParam(0) | declarations.swift:111:13:111:13 | x | +| declarations.swift:111:37:113:3 | get | 2 | getImmediateParam(1) | declarations.swift:111:21:111:21 | y | +| declarations.swift:111:37:113:3 | get | 3 | getImmediateBody() | declarations.swift:111:37:113:3 | { ... } | +| declarations.swift:111:37:113:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:112:5:112:12 | return ... | +| declarations.swift:112:5:112:12 | return ... | 0 | getImmediateResult() | declarations.swift:112:12:112:12 | 0 | +| declarations.swift:115:3:117:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:115:7:115:21 | ... as ... | +| declarations.swift:115:7:115:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:115:7:115:7 | self | +| declarations.swift:115:7:115:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:115:7:115:7 | { ... } | +| declarations.swift:115:7:115:7 | get | 0 | getImmediateSelfParam() | declarations.swift:115:7:115:7 | self | +| declarations.swift:115:7:115:7 | get | 1 | getImmediateBody() | declarations.swift:115:7:115:7 | { ... } | +| declarations.swift:115:7:115:7 | hasWillSet1 | 0 | getImmediateAccessorDecl(0) | declarations.swift:116:5:116:25 | willSet | +| declarations.swift:115:7:115:7 | hasWillSet1 | 1 | getImmediateAccessorDecl(1) | declarations.swift:115:7:115:7 | get | +| declarations.swift:115:7:115:7 | hasWillSet1 | 2 | getImmediateAccessorDecl(2) | declarations.swift:115:7:115:7 | set | +| declarations.swift:115:7:115:7 | hasWillSet1 | 3 | getImmediateAccessorDecl(3) | declarations.swift:115:7:115:7 | (unnamed function decl) | +| declarations.swift:115:7:115:7 | set | 0 | getImmediateSelfParam() | declarations.swift:115:7:115:7 | self | +| declarations.swift:115:7:115:7 | set | 1 | getImmediateParam(0) | declarations.swift:115:7:115:7 | value | +| declarations.swift:115:7:115:7 | set | 2 | getImmediateBody() | declarations.swift:115:7:115:7 | { ... } | +| declarations.swift:115:7:115:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:115:7:115:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:115:7:115:7 | yield ... | +| declarations.swift:115:7:115:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | call to willSet | +| declarations.swift:115:7:115:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:115:7:115:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | ... = ... | +| declarations.swift:115:7:115:21 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:115:7:115:7 | hasWillSet1 | +| declarations.swift:115:7:115:21 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:115:21:115:21 | Int | +| declarations.swift:116:5:116:25 | willSet | 0 | getImmediateSelfParam() | declarations.swift:116:5:116:5 | self | +| declarations.swift:116:5:116:25 | willSet | 1 | getImmediateParam(0) | declarations.swift:116:13:116:13 | newValue | +| declarations.swift:116:5:116:25 | willSet | 2 | getImmediateBody() | declarations.swift:116:23:116:25 | { ... } | +| declarations.swift:119:3:121:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:119:7:119:21 | ... as ... | +| declarations.swift:119:7:119:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:119:7:119:7 | self | +| declarations.swift:119:7:119:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:119:7:119:7 | { ... } | +| declarations.swift:119:7:119:7 | get | 0 | getImmediateSelfParam() | declarations.swift:119:7:119:7 | self | +| declarations.swift:119:7:119:7 | get | 1 | getImmediateBody() | declarations.swift:119:7:119:7 | { ... } | +| declarations.swift:119:7:119:7 | hasWillSet2 | 0 | getImmediateAccessorDecl(0) | declarations.swift:120:5:120:15 | willSet | +| declarations.swift:119:7:119:7 | hasWillSet2 | 1 | getImmediateAccessorDecl(1) | declarations.swift:119:7:119:7 | get | +| declarations.swift:119:7:119:7 | hasWillSet2 | 2 | getImmediateAccessorDecl(2) | declarations.swift:119:7:119:7 | set | +| declarations.swift:119:7:119:7 | hasWillSet2 | 3 | getImmediateAccessorDecl(3) | declarations.swift:119:7:119:7 | (unnamed function decl) | +| declarations.swift:119:7:119:7 | set | 0 | getImmediateSelfParam() | declarations.swift:119:7:119:7 | self | +| declarations.swift:119:7:119:7 | set | 1 | getImmediateParam(0) | declarations.swift:119:7:119:7 | value | +| declarations.swift:119:7:119:7 | set | 2 | getImmediateBody() | declarations.swift:119:7:119:7 | { ... } | +| declarations.swift:119:7:119:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:119:7:119:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:119:7:119:7 | yield ... | +| declarations.swift:119:7:119:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | call to willSet | +| declarations.swift:119:7:119:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:119:7:119:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | ... = ... | +| declarations.swift:119:7:119:21 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:119:7:119:7 | hasWillSet2 | +| declarations.swift:119:7:119:21 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:119:21:119:21 | Int | +| declarations.swift:120:5:120:15 | willSet | 0 | getImmediateSelfParam() | declarations.swift:120:5:120:5 | self | +| declarations.swift:120:5:120:15 | willSet | 1 | getImmediateParam(0) | declarations.swift:120:5:120:5 | newValue | +| declarations.swift:120:5:120:15 | willSet | 2 | getImmediateBody() | declarations.swift:120:13:120:15 | { ... } | +| declarations.swift:123:3:125:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:123:7:123:20 | ... as ... | +| declarations.swift:123:7:123:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:123:7:123:7 | self | +| declarations.swift:123:7:123:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:123:7:123:7 | { ... } | +| declarations.swift:123:7:123:7 | get | 0 | getImmediateSelfParam() | declarations.swift:123:7:123:7 | self | +| declarations.swift:123:7:123:7 | get | 1 | getImmediateBody() | declarations.swift:123:7:123:7 | { ... } | +| declarations.swift:123:7:123:7 | hasDidSet1 | 0 | getImmediateAccessorDecl(0) | declarations.swift:124:5:124:24 | didSet | +| declarations.swift:123:7:123:7 | hasDidSet1 | 1 | getImmediateAccessorDecl(1) | declarations.swift:123:7:123:7 | get | +| declarations.swift:123:7:123:7 | hasDidSet1 | 2 | getImmediateAccessorDecl(2) | declarations.swift:123:7:123:7 | set | +| declarations.swift:123:7:123:7 | hasDidSet1 | 3 | getImmediateAccessorDecl(3) | declarations.swift:123:7:123:7 | (unnamed function decl) | +| declarations.swift:123:7:123:7 | set | 0 | getImmediateSelfParam() | declarations.swift:123:7:123:7 | self | +| declarations.swift:123:7:123:7 | set | 1 | getImmediateParam(0) | declarations.swift:123:7:123:7 | value | +| declarations.swift:123:7:123:7 | set | 2 | getImmediateBody() | declarations.swift:123:7:123:7 | { ... } | +| declarations.swift:123:7:123:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:123:7:123:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:123:7:123:7 | yield ... | +| declarations.swift:123:7:123:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:123:7:123:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | var ... = ... | +| declarations.swift:123:7:123:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | tmp | +| declarations.swift:123:7:123:7 | { ... } | 2 | getImmediateElement(2) | file://:0:0:0:0 | ... = ... | +| declarations.swift:123:7:123:7 | { ... } | 3 | getImmediateElement(3) | file://:0:0:0:0 | call to didSet | +| declarations.swift:123:7:123:20 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:123:7:123:7 | hasDidSet1 | +| declarations.swift:123:7:123:20 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:123:20:123:20 | Int | +| declarations.swift:124:5:124:24 | didSet | 0 | getImmediateSelfParam() | declarations.swift:124:5:124:5 | self | +| declarations.swift:124:5:124:24 | didSet | 1 | getImmediateParam(0) | declarations.swift:124:12:124:12 | oldValue | +| declarations.swift:124:5:124:24 | didSet | 2 | getImmediateBody() | declarations.swift:124:22:124:24 | { ... } | +| declarations.swift:127:3:129:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:127:7:127:20 | ... as ... | +| declarations.swift:127:7:127:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:127:7:127:7 | self | +| declarations.swift:127:7:127:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:127:7:127:7 | { ... } | +| declarations.swift:127:7:127:7 | get | 0 | getImmediateSelfParam() | declarations.swift:127:7:127:7 | self | +| declarations.swift:127:7:127:7 | get | 1 | getImmediateBody() | declarations.swift:127:7:127:7 | { ... } | +| declarations.swift:127:7:127:7 | hasDidSet2 | 0 | getImmediateAccessorDecl(0) | declarations.swift:128:5:128:14 | didSet | +| declarations.swift:127:7:127:7 | hasDidSet2 | 1 | getImmediateAccessorDecl(1) | declarations.swift:127:7:127:7 | get | +| declarations.swift:127:7:127:7 | hasDidSet2 | 2 | getImmediateAccessorDecl(2) | declarations.swift:127:7:127:7 | set | +| declarations.swift:127:7:127:7 | hasDidSet2 | 3 | getImmediateAccessorDecl(3) | declarations.swift:127:7:127:7 | (unnamed function decl) | +| declarations.swift:127:7:127:7 | set | 0 | getImmediateSelfParam() | declarations.swift:127:7:127:7 | self | +| declarations.swift:127:7:127:7 | set | 1 | getImmediateParam(0) | declarations.swift:127:7:127:7 | value | +| declarations.swift:127:7:127:7 | set | 2 | getImmediateBody() | declarations.swift:127:7:127:7 | { ... } | +| declarations.swift:127:7:127:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:127:7:127:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:127:7:127:7 | yield ... | +| declarations.swift:127:7:127:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| declarations.swift:127:7:127:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:127:7:127:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | call to didSet | +| declarations.swift:127:7:127:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | call to didSet | +| declarations.swift:127:7:127:20 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:127:7:127:7 | hasDidSet2 | +| declarations.swift:127:7:127:20 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:127:20:127:20 | Int | +| declarations.swift:128:5:128:14 | didSet | 0 | getImmediateSelfParam() | declarations.swift:128:5:128:5 | self | +| declarations.swift:128:5:128:14 | didSet | 1 | getImmediateBody() | declarations.swift:128:12:128:14 | { ... } | +| declarations.swift:131:3:135:3 | var ... = ... | 0 | getImmediatePattern(0) | declarations.swift:131:7:131:17 | ... as ... | +| declarations.swift:131:7:131:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | declarations.swift:131:7:131:7 | self | +| declarations.swift:131:7:131:7 | (unnamed function decl) | 1 | getImmediateBody() | declarations.swift:131:7:131:7 | { ... } | +| declarations.swift:131:7:131:7 | get | 0 | getImmediateSelfParam() | declarations.swift:131:7:131:7 | self | +| declarations.swift:131:7:131:7 | get | 1 | getImmediateBody() | declarations.swift:131:7:131:7 | { ... } | +| declarations.swift:131:7:131:7 | hasBoth | 0 | getImmediateAccessorDecl(0) | declarations.swift:132:5:132:15 | willSet | +| declarations.swift:131:7:131:7 | hasBoth | 1 | getImmediateAccessorDecl(1) | declarations.swift:134:5:134:14 | didSet | +| declarations.swift:131:7:131:7 | hasBoth | 2 | getImmediateAccessorDecl(2) | declarations.swift:131:7:131:7 | get | +| declarations.swift:131:7:131:7 | hasBoth | 3 | getImmediateAccessorDecl(3) | declarations.swift:131:7:131:7 | set | +| declarations.swift:131:7:131:7 | hasBoth | 4 | getImmediateAccessorDecl(4) | declarations.swift:131:7:131:7 | (unnamed function decl) | +| declarations.swift:131:7:131:7 | set | 0 | getImmediateSelfParam() | declarations.swift:131:7:131:7 | self | +| declarations.swift:131:7:131:7 | set | 1 | getImmediateParam(0) | declarations.swift:131:7:131:7 | value | +| declarations.swift:131:7:131:7 | set | 2 | getImmediateBody() | declarations.swift:131:7:131:7 | { ... } | +| declarations.swift:131:7:131:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| declarations.swift:131:7:131:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:131:7:131:7 | yield ... | +| declarations.swift:131:7:131:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | call to willSet | +| declarations.swift:131:7:131:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| declarations.swift:131:7:131:7 | { ... } | 1 | getImmediateElement(1) | file://:0:0:0:0 | ... = ... | +| declarations.swift:131:7:131:7 | { ... } | 2 | getImmediateElement(2) | file://:0:0:0:0 | call to didSet | +| declarations.swift:131:7:131:17 | ... as ... | 0 | getImmediateSubPattern() | declarations.swift:131:7:131:7 | hasBoth | +| declarations.swift:131:7:131:17 | ... as ... | 1 | getImmediateTypeRepr() | declarations.swift:131:17:131:17 | Int | +| declarations.swift:132:5:132:15 | willSet | 0 | getImmediateSelfParam() | declarations.swift:132:5:132:5 | self | +| declarations.swift:132:5:132:15 | willSet | 1 | getImmediateParam(0) | declarations.swift:132:5:132:5 | newValue | +| declarations.swift:132:5:132:15 | willSet | 2 | getImmediateBody() | declarations.swift:132:13:132:15 | { ... } | +| declarations.swift:134:5:134:14 | didSet | 0 | getImmediateSelfParam() | declarations.swift:134:5:134:5 | self | +| declarations.swift:134:5:134:14 | didSet | 1 | getImmediateBody() | declarations.swift:134:12:134:14 | { ... } | +| declarations.swift:139:3:141:3 | id() | 0 | getImmediateSelfParam() | declarations.swift:139:8:139:8 | self | +| declarations.swift:139:3:141:3 | id() | 1 | getImmediateBody() | declarations.swift:139:20:141:3 | { ... } | +| declarations.swift:139:20:141:3 | { ... } | 0 | getImmediateElement(0) | declarations.swift:140:5:140:12 | return ... | +| declarations.swift:140:5:140:12 | return ... | 0 | getImmediateResult() | declarations.swift:140:12:140:12 | self | +| declarations.swift:144:1:144:4 | .id() | 0 | getImmediateBase() | declarations.swift:144:1:144:1 | 42 | +| declarations.swift:144:1:144:7 | call to id() | 0 | getImmediateFunction() | declarations.swift:144:1:144:4 | .id() | +| declarations.swift:144:1:144:7 | { ... } | 0 | getImmediateBody() | declarations.swift:144:1:144:7 | { ... } | +| declarations.swift:144:1:144:7 | { ... } | 0 | getImmediateElement(0) | declarations.swift:144:1:144:7 | call to id() | +| expressions.swift:1:1:1:9 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:1:9:1:9 | 15 | +| expressions.swift:1:1:1:9 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:1:5:1:5 | a | +| expressions.swift:1:1:1:9 | { ... } | 0 | getImmediateBody() | expressions.swift:1:1:1:9 | { ... } | +| expressions.swift:1:1:1:9 | { ... } | 0 | getImmediateElement(0) | expressions.swift:1:1:1:9 | var ... = ... | +| expressions.swift:2:1:2:9 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:2:9:2:9 | 15.15 | +| expressions.swift:2:1:2:9 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:2:5:2:5 | b | +| expressions.swift:2:1:2:9 | { ... } | 0 | getImmediateBody() | expressions.swift:2:1:2:9 | { ... } | +| expressions.swift:2:1:2:9 | { ... } | 0 | getImmediateElement(0) | expressions.swift:2:1:2:9 | var ... = ... | +| expressions.swift:3:1:3:10 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:3:10:3:10 | true | +| expressions.swift:3:1:3:10 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:3:5:3:5 | b1 | +| expressions.swift:3:1:3:10 | { ... } | 0 | getImmediateBody() | expressions.swift:3:1:3:10 | { ... } | +| expressions.swift:3:1:3:10 | { ... } | 0 | getImmediateElement(0) | expressions.swift:3:1:3:10 | var ... = ... | +| expressions.swift:4:1:4:10 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:4:10:4:10 | false | +| expressions.swift:4:1:4:10 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:4:5:4:5 | b2 | +| expressions.swift:4:1:4:10 | { ... } | 0 | getImmediateBody() | expressions.swift:4:1:4:10 | { ... } | +| expressions.swift:4:1:4:10 | { ... } | 0 | getImmediateElement(0) | expressions.swift:4:1:4:10 | var ... = ... | +| expressions.swift:5:1:5:9 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:5:9:5:9 | #... | +| expressions.swift:5:1:5:9 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:5:5:5:5 | m | +| expressions.swift:5:1:5:9 | { ... } | 0 | getImmediateBody() | expressions.swift:5:1:5:9 | { ... } | +| expressions.swift:5:1:5:9 | { ... } | 0 | getImmediateElement(0) | expressions.swift:5:1:5:9 | var ... = ... | +| expressions.swift:6:1:6:9 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:6:9:6:9 | hello world | +| expressions.swift:6:1:6:9 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:6:5:6:5 | s | +| expressions.swift:6:1:6:9 | { ... } | 0 | getImmediateBody() | expressions.swift:6:1:6:9 | { ... } | +| expressions.swift:6:1:6:9 | { ... } | 0 | getImmediateElement(0) | expressions.swift:6:1:6:9 | var ... = ... | +| expressions.swift:7:1:7:10 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:7:10:7:10 | "..." | +| expressions.swift:7:1:7:10 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:7:5:7:5 | s1 | +| expressions.swift:7:1:7:10 | { ... } | 0 | getImmediateBody() | expressions.swift:7:1:7:10 | { ... } | +| expressions.swift:7:1:7:10 | { ... } | 0 | getImmediateElement(0) | expressions.swift:7:1:7:10 | var ... = ... | +| expressions.swift:7:10:7:10 | "..." | 0 | getImmediateInterpolationCountExpr() | file://:0:0:0:0 | 1 | +| expressions.swift:7:10:7:10 | "..." | 1 | getImmediateLiteralCapacityExpr() | file://:0:0:0:0 | 6 | +| expressions.swift:7:10:7:10 | "..." | 2 | getImmediateAppendingExpr() | expressions.swift:7:10:7:10 | TapExpr | +| expressions.swift:7:10:7:10 | TapExpr | 0 | getImmediateSubExpr() | expressions.swift:7:10:7:10 | OpaqueValueExpr | +| expressions.swift:7:10:7:10 | TapExpr | 1 | getImmediateBody() | expressions.swift:7:10:7:10 | { ... } | +| expressions.swift:7:10:7:10 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | $interpolation | +| expressions.swift:7:10:7:10 | { ... } | 1 | getImmediateElement(1) | expressions.swift:7:11:7:10 | call to appendLiteral(_:) | +| expressions.swift:7:10:7:10 | { ... } | 2 | getImmediateElement(2) | expressions.swift:7:18:7:20 | call to appendInterpolation(_:) | +| expressions.swift:7:10:7:10 | { ... } | 3 | getImmediateElement(3) | expressions.swift:7:21:7:21 | call to appendLiteral(_:) | +| expressions.swift:7:11:7:10 | call to appendLiteral(_:) | 0 | getImmediateFunction() | expressions.swift:7:11:7:11 | .appendLiteral(_:) | +| expressions.swift:7:11:7:11 | &... | 0 | getImmediateSubExpr() | expressions.swift:7:11:7:11 | $interpolation | +| expressions.swift:7:11:7:11 | .appendLiteral(_:) | 0 | getImmediateBase() | expressions.swift:7:11:7:11 | &... | +| expressions.swift:7:18:7:18 | &... | 0 | getImmediateSubExpr() | expressions.swift:7:18:7:18 | $interpolation | +| expressions.swift:7:18:7:18 | .appendInterpolation(_:) | 0 | getImmediateBase() | expressions.swift:7:18:7:18 | &... | +| expressions.swift:7:18:7:20 | call to appendInterpolation(_:) | 0 | getImmediateFunction() | expressions.swift:7:18:7:18 | .appendInterpolation(_:) | +| expressions.swift:7:21:7:21 | &... | 0 | getImmediateSubExpr() | expressions.swift:7:21:7:21 | $interpolation | +| expressions.swift:7:21:7:21 | .appendLiteral(_:) | 0 | getImmediateBase() | expressions.swift:7:21:7:21 | &... | +| expressions.swift:7:21:7:21 | call to appendLiteral(_:) | 0 | getImmediateFunction() | expressions.swift:7:21:7:21 | .appendLiteral(_:) | +| expressions.swift:8:1:8:15 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:8:15:8:15 | nil | +| expressions.swift:8:1:8:15 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:8:5:8:11 | ... as ... | +| expressions.swift:8:1:8:15 | { ... } | 0 | getImmediateBody() | expressions.swift:8:1:8:15 | { ... } | +| expressions.swift:8:1:8:15 | { ... } | 0 | getImmediateElement(0) | expressions.swift:8:1:8:15 | var ... = ... | +| expressions.swift:8:5:8:11 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:8:5:8:5 | n | +| expressions.swift:8:5:8:11 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:8:8:8:11 | Int? | +| expressions.swift:11:3:11:8 | case ... | 0 | getImmediateElement(0) | expressions.swift:11:8:11:8 | failed | +| expressions.swift:14:1:18:1 | failure(_:) | 1 | getImmediateParam(0) | expressions.swift:14:14:14:19 | x | +| expressions.swift:14:1:18:1 | failure(_:) | 2 | getImmediateBody() | expressions.swift:14:31:18:1 | { ... } | +| expressions.swift:14:31:18:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:15:3:17:3 | guard ... else { ... } | +| expressions.swift:15:3:17:3 | guard ... else { ... } | 0 | getImmediateCondition() | expressions.swift:15:9:15:14 | StmtCondition | +| expressions.swift:15:3:17:3 | guard ... else { ... } | 1 | getImmediateBody() | expressions.swift:15:21:17:3 | { ... } | +| expressions.swift:15:9:15:14 | ... .!=(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:15:11:15:11 | .!=(_:_:) | +| expressions.swift:15:11:15:11 | .!=(_:_:) | 0 | getImmediateBase() | expressions.swift:15:11:15:11 | Int.Type | +| expressions.swift:15:11:15:11 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:15:11:15:11 | Int | +| expressions.swift:15:21:17:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:16:5:16:19 | throw ... | +| expressions.swift:16:5:16:19 | throw ... | 0 | getImmediateSubExpr() | expressions.swift:16:11:16:19 | (Error) ... | +| expressions.swift:16:11:16:11 | AnError.Type | 0 | getImmediateTypeRepr() | expressions.swift:16:11:16:11 | AnError | +| expressions.swift:16:11:16:19 | (Error) ... | 0 | getImmediateSubExpr() | expressions.swift:16:11:16:19 | .failed | +| expressions.swift:16:11:16:19 | .failed | 0 | getImmediateBase() | expressions.swift:16:11:16:11 | AnError.Type | +| expressions.swift:20:1:20:16 | try! ... | 0 | getImmediateSubExpr() | expressions.swift:20:6:20:16 | call to failure(_:) | +| expressions.swift:20:1:20:16 | { ... } | 0 | getImmediateBody() | expressions.swift:20:1:20:16 | { ... } | +| expressions.swift:20:1:20:16 | { ... } | 0 | getImmediateElement(0) | expressions.swift:20:1:20:16 | try! ... | +| expressions.swift:20:6:20:16 | call to failure(_:) | 0 | getImmediateFunction() | expressions.swift:20:6:20:6 | failure(_:) | +| expressions.swift:21:1:21:16 | try? ... | 0 | getImmediateSubExpr() | expressions.swift:21:6:21:16 | (()?) ... | +| expressions.swift:21:1:21:16 | { ... } | 0 | getImmediateBody() | expressions.swift:21:1:21:16 | { ... } | +| expressions.swift:21:1:21:16 | { ... } | 0 | getImmediateElement(0) | expressions.swift:21:1:21:16 | try? ... | +| expressions.swift:21:6:21:16 | (()?) ... | 0 | getImmediateSubExpr() | expressions.swift:21:6:21:16 | call to failure(_:) | +| expressions.swift:21:6:21:16 | call to failure(_:) | 0 | getImmediateFunction() | expressions.swift:21:6:21:6 | failure(_:) | +| expressions.swift:23:7:23:7 | deinit | 0 | getImmediateSelfParam() | expressions.swift:23:7:23:7 | self | +| expressions.swift:23:7:23:7 | deinit | 1 | getImmediateBody() | expressions.swift:23:7:23:7 | { ... } | +| expressions.swift:24:3:24:11 | init | 0 | getImmediateSelfParam() | expressions.swift:24:3:24:3 | self | +| expressions.swift:24:3:24:11 | init | 1 | getImmediateBody() | expressions.swift:24:10:24:11 | { ... } | +| expressions.swift:24:10:24:11 | { ... } | 0 | getImmediateElement(0) | expressions.swift:24:11:24:11 | return | +| expressions.swift:27:1:27:19 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:27:13:27:19 | call to init | +| expressions.swift:27:1:27:19 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:27:5:27:5 | klass | +| expressions.swift:27:1:27:19 | { ... } | 0 | getImmediateBody() | expressions.swift:27:1:27:19 | { ... } | +| expressions.swift:27:1:27:19 | { ... } | 0 | getImmediateElement(0) | expressions.swift:27:1:27:19 | var ... = ... | +| expressions.swift:27:13:27:13 | Klass.Type | 0 | getImmediateTypeRepr() | expressions.swift:27:13:27:13 | Klass | +| expressions.swift:27:13:27:13 | call to init | 0 | getImmediateFunction() | expressions.swift:27:13:27:13 | init | +| expressions.swift:27:13:27:13 | call to init | 2 | getImmediateBase() | expressions.swift:27:13:27:13 | Klass.Type | +| expressions.swift:27:13:27:19 | call to init | 0 | getImmediateFunction() | expressions.swift:27:13:27:13 | call to init | +| expressions.swift:29:1:29:19 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:29:9:29:19 | [...] | +| expressions.swift:29:1:29:19 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:29:5:29:5 | d | +| expressions.swift:29:1:29:19 | { ... } | 0 | getImmediateBody() | expressions.swift:29:1:29:19 | { ... } | +| expressions.swift:29:1:29:19 | { ... } | 0 | getImmediateElement(0) | expressions.swift:29:1:29:19 | var ... = ... | +| expressions.swift:29:9:29:19 | [...] | 0 | getImmediateElement(0) | expressions.swift:29:10:29:16 | (...) | +| expressions.swift:29:10:29:16 | (...) | 0 | getImmediateElement(0) | expressions.swift:29:10:29:10 | 1 | +| expressions.swift:29:10:29:16 | (...) | 1 | getImmediateElement(1) | expressions.swift:29:16:29:16 | 2 | +| expressions.swift:30:1:30:5 | ... = ... | 0 | getImmediateDest() | expressions.swift:30:1:30:1 | _ | +| expressions.swift:30:1:30:5 | ... = ... | 1 | getImmediateSource() | expressions.swift:30:5:30:5 | 15 | +| expressions.swift:30:1:30:5 | { ... } | 0 | getImmediateBody() | expressions.swift:30:1:30:5 | { ... } | +| expressions.swift:30:1:30:5 | { ... } | 0 | getImmediateElement(0) | expressions.swift:30:1:30:5 | ... = ... | +| expressions.swift:31:1:31:11 | ... = ... | 0 | getImmediateDest() | expressions.swift:31:1:31:1 | _ | +| expressions.swift:31:1:31:11 | ... = ... | 1 | getImmediateSource() | expressions.swift:31:5:31:11 | ... is ... | +| expressions.swift:31:1:31:11 | { ... } | 0 | getImmediateBody() | expressions.swift:31:1:31:11 | { ... } | +| expressions.swift:31:1:31:11 | { ... } | 0 | getImmediateElement(0) | expressions.swift:31:1:31:11 | ... = ... | +| expressions.swift:31:5:31:11 | ... is ... | 0 | getImmediateSubExpr() | expressions.swift:31:5:31:5 | 15 | +| expressions.swift:32:1:32:11 | ... = ... | 0 | getImmediateDest() | expressions.swift:32:1:32:1 | _ | +| expressions.swift:32:1:32:11 | ... = ... | 1 | getImmediateSource() | expressions.swift:32:5:32:11 | (Double) ... | +| expressions.swift:32:1:32:11 | { ... } | 0 | getImmediateBody() | expressions.swift:32:1:32:11 | { ... } | +| expressions.swift:32:1:32:11 | { ... } | 0 | getImmediateElement(0) | expressions.swift:32:1:32:11 | ... = ... | +| expressions.swift:32:5:32:11 | (Double) ... | 0 | getImmediateSubExpr() | expressions.swift:32:5:32:5 | 15 | +| expressions.swift:33:1:33:12 | ... = ... | 0 | getImmediateDest() | expressions.swift:33:1:33:1 | _ | +| expressions.swift:33:1:33:12 | ... = ... | 1 | getImmediateSource() | expressions.swift:33:5:33:12 | (Double?) ... | +| expressions.swift:33:1:33:12 | { ... } | 0 | getImmediateBody() | expressions.swift:33:1:33:12 | { ... } | +| expressions.swift:33:1:33:12 | { ... } | 0 | getImmediateElement(0) | expressions.swift:33:1:33:12 | ... = ... | +| expressions.swift:33:5:33:12 | (Double?) ... | 0 | getImmediateSubExpr() | expressions.swift:33:5:33:5 | 15 | +| expressions.swift:34:1:34:12 | ... = ... | 0 | getImmediateDest() | expressions.swift:34:1:34:1 | _ | +| expressions.swift:34:1:34:12 | ... = ... | 1 | getImmediateSource() | expressions.swift:34:5:34:12 | (Double) ... | +| expressions.swift:34:1:34:12 | { ... } | 0 | getImmediateBody() | expressions.swift:34:1:34:12 | { ... } | +| expressions.swift:34:1:34:12 | { ... } | 0 | getImmediateElement(0) | expressions.swift:34:1:34:12 | ... = ... | +| expressions.swift:34:5:34:12 | (Double) ... | 0 | getImmediateSubExpr() | expressions.swift:34:5:34:5 | 15 | +| expressions.swift:35:1:35:13 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | expressions.swift:35:1:35:1 | print(_:separator:terminator:) | +| expressions.swift:35:1:35:13 | { ... } | 0 | getImmediateBody() | expressions.swift:35:1:35:13 | { ... } | +| expressions.swift:35:1:35:13 | { ... } | 0 | getImmediateElement(0) | expressions.swift:35:1:35:13 | call to print(_:separator:terminator:) | +| expressions.swift:35:7:35:12 | (Any) ... | 0 | getImmediateSubExpr() | expressions.swift:35:7:35:12 | ...[...] | +| expressions.swift:35:7:35:12 | ...[...] | 0 | getImmediateBase() | expressions.swift:35:7:35:7 | d | +| expressions.swift:35:7:35:12 | [...] | 0 | getImmediateElement(0) | expressions.swift:35:7:35:12 | (Any) ... | +| expressions.swift:35:7:35:12 | [...] | 0 | getImmediateSubExpr() | expressions.swift:35:7:35:12 | [...] | +| expressions.swift:37:1:39:1 | closured(closure:) | 1 | getImmediateParam(0) | expressions.swift:37:15:37:38 | closure | +| expressions.swift:37:1:39:1 | closured(closure:) | 2 | getImmediateBody() | expressions.swift:37:43:39:1 | { ... } | +| expressions.swift:37:43:39:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:38:3:38:15 | call to ... | +| expressions.swift:38:3:38:15 | call to ... | 0 | getImmediateFunction() | expressions.swift:38:3:38:3 | closure | +| expressions.swift:41:1:43:1 | call to closured(closure:) | 0 | getImmediateFunction() | expressions.swift:41:1:41:1 | closured(closure:) | +| expressions.swift:41:1:43:1 | { ... } | 0 | getImmediateBody() | expressions.swift:41:1:43:1 | { ... } | +| expressions.swift:41:1:43:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:41:1:43:1 | call to closured(closure:) | +| expressions.swift:41:10:43:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:42:5:42:16 | return ... | +| expressions.swift:41:10:43:1 | { ... } | 1 | getImmediateParam(0) | expressions.swift:41:13:41:16 | x | +| expressions.swift:41:10:43:1 | { ... } | 2 | getImmediateParam(1) | expressions.swift:41:21:41:24 | y | +| expressions.swift:41:10:43:1 | { ... } | 3 | getImmediateBody() | expressions.swift:41:10:43:1 | { ... } | +| expressions.swift:42:5:42:16 | return ... | 0 | getImmediateResult() | expressions.swift:42:12:42:16 | ... .+(_:_:) ... | +| expressions.swift:42:12:42:16 | ... .+(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:42:14:42:14 | .+(_:_:) | +| expressions.swift:42:14:42:14 | .+(_:_:) | 0 | getImmediateBase() | expressions.swift:42:14:42:14 | Int.Type | +| expressions.swift:42:14:42:14 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:42:14:42:14 | Int | +| expressions.swift:44:1:46:1 | call to closured(closure:) | 0 | getImmediateFunction() | expressions.swift:44:1:44:1 | closured(closure:) | +| expressions.swift:44:1:46:1 | { ... } | 0 | getImmediateBody() | expressions.swift:44:1:46:1 | { ... } | +| expressions.swift:44:1:46:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:44:1:46:1 | call to closured(closure:) | +| expressions.swift:44:10:46:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:45:5:45:16 | return ... | +| expressions.swift:44:10:46:1 | { ... } | 1 | getImmediateParam(0) | expressions.swift:44:12:44:12 | x | +| expressions.swift:44:10:46:1 | { ... } | 2 | getImmediateParam(1) | expressions.swift:44:15:44:15 | y | +| expressions.swift:44:10:46:1 | { ... } | 3 | getImmediateBody() | expressions.swift:44:10:46:1 | { ... } | +| expressions.swift:45:5:45:16 | return ... | 0 | getImmediateResult() | expressions.swift:45:12:45:16 | ... .+(_:_:) ... | +| expressions.swift:45:12:45:16 | ... .+(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:45:14:45:14 | .+(_:_:) | +| expressions.swift:45:14:45:14 | .+(_:_:) | 0 | getImmediateBase() | expressions.swift:45:14:45:14 | Int.Type | +| expressions.swift:45:14:45:14 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:45:14:45:14 | Int | +| expressions.swift:47:1:47:27 | call to closured(closure:) | 0 | getImmediateFunction() | expressions.swift:47:1:47:1 | closured(closure:) | +| expressions.swift:47:1:47:27 | { ... } | 0 | getImmediateBody() | expressions.swift:47:1:47:27 | { ... } | +| expressions.swift:47:1:47:27 | { ... } | 0 | getImmediateElement(0) | expressions.swift:47:1:47:27 | call to closured(closure:) | +| expressions.swift:47:10:47:27 | { ... } | 0 | getImmediateElement(0) | expressions.swift:47:12:47:24 | return ... | +| expressions.swift:47:10:47:27 | { ... } | 1 | getImmediateParam(0) | expressions.swift:47:10:47:10 | $0 | +| expressions.swift:47:10:47:27 | { ... } | 2 | getImmediateParam(1) | expressions.swift:47:10:47:10 | $1 | +| expressions.swift:47:10:47:27 | { ... } | 3 | getImmediateBody() | expressions.swift:47:10:47:27 | { ... } | +| expressions.swift:47:12:47:24 | return ... | 0 | getImmediateResult() | expressions.swift:47:19:47:24 | ... .+(_:_:) ... | +| expressions.swift:47:19:47:24 | ... .+(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:47:22:47:22 | .+(_:_:) | +| expressions.swift:47:22:47:22 | .+(_:_:) | 0 | getImmediateBase() | expressions.swift:47:22:47:22 | Int.Type | +| expressions.swift:47:22:47:22 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:47:22:47:22 | Int | +| expressions.swift:48:1:48:20 | call to closured(closure:) | 0 | getImmediateFunction() | expressions.swift:48:1:48:1 | closured(closure:) | +| expressions.swift:48:1:48:20 | { ... } | 0 | getImmediateBody() | expressions.swift:48:1:48:20 | { ... } | +| expressions.swift:48:1:48:20 | { ... } | 0 | getImmediateElement(0) | expressions.swift:48:1:48:20 | call to closured(closure:) | +| expressions.swift:48:10:48:20 | { ... } | 0 | getImmediateElement(0) | expressions.swift:48:12:48:17 | return ... | +| expressions.swift:48:10:48:20 | { ... } | 1 | getImmediateParam(0) | expressions.swift:48:10:48:10 | $0 | +| expressions.swift:48:10:48:20 | { ... } | 2 | getImmediateParam(1) | expressions.swift:48:10:48:10 | $1 | +| expressions.swift:48:10:48:20 | { ... } | 3 | getImmediateBody() | expressions.swift:48:10:48:20 | { ... } | +| expressions.swift:48:12:48:17 | ... .+(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:48:15:48:15 | .+(_:_:) | +| expressions.swift:48:12:48:17 | return ... | 0 | getImmediateResult() | expressions.swift:48:12:48:17 | ... .+(_:_:) ... | +| expressions.swift:48:15:48:15 | .+(_:_:) | 0 | getImmediateBase() | expressions.swift:48:15:48:15 | Int.Type | +| expressions.swift:48:15:48:15 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:48:15:48:15 | Int | +| expressions.swift:50:8:50:8 | init | 0 | getImmediateSelfParam() | expressions.swift:50:8:50:8 | self | +| expressions.swift:50:8:50:8 | init | 1 | getImmediateParam(0) | expressions.swift:50:8:50:8 | x | +| expressions.swift:51:3:51:10 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:51:7:51:10 | ... as ... | +| expressions.swift:51:7:51:7 | get | 0 | getImmediateSelfParam() | expressions.swift:51:7:51:7 | self | +| expressions.swift:51:7:51:7 | get | 1 | getImmediateBody() | expressions.swift:51:7:51:7 | { ... } | +| expressions.swift:51:7:51:7 | x | 0 | getImmediateAccessorDecl(0) | expressions.swift:51:7:51:7 | get | +| expressions.swift:51:7:51:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:51:7:51:10 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:51:7:51:7 | x | +| expressions.swift:51:7:51:10 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:51:10:51:10 | Int | +| expressions.swift:54:1:54:8 | ... = ... | 0 | getImmediateDest() | expressions.swift:54:1:54:1 | _ | +| expressions.swift:54:1:54:8 | ... = ... | 1 | getImmediateSource() | expressions.swift:54:5:54:8 | #keyPath(...) | +| expressions.swift:54:1:54:8 | { ... } | 0 | getImmediateBody() | expressions.swift:54:1:54:8 | { ... } | +| expressions.swift:54:1:54:8 | { ... } | 0 | getImmediateElement(0) | expressions.swift:54:1:54:8 | ... = ... | +| expressions.swift:54:5:54:8 | #keyPath(...) | 0 | getImmediateRoot() | expressions.swift:54:6:54:6 | S | +| expressions.swift:56:1:57:1 | unsafeFunction(pointer:) | 1 | getImmediateParam(0) | expressions.swift:56:21:56:47 | pointer | +| expressions.swift:56:1:57:1 | unsafeFunction(pointer:) | 2 | getImmediateBody() | expressions.swift:56:50:57:1 | { ... } | +| expressions.swift:58:1:58:16 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:58:16:58:16 | 1234 | +| expressions.swift:58:1:58:16 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:58:5:58:5 | myNumber | +| expressions.swift:58:1:58:16 | { ... } | 0 | getImmediateBody() | expressions.swift:58:1:58:16 | { ... } | +| expressions.swift:58:1:58:16 | { ... } | 0 | getImmediateElement(0) | expressions.swift:58:1:58:16 | var ... = ... | +| expressions.swift:59:1:59:34 | call to unsafeFunction(pointer:) | 0 | getImmediateFunction() | expressions.swift:59:1:59:1 | unsafeFunction(pointer:) | +| expressions.swift:59:1:59:34 | { ... } | 0 | getImmediateBody() | expressions.swift:59:1:59:34 | { ... } | +| expressions.swift:59:1:59:34 | { ... } | 0 | getImmediateElement(0) | expressions.swift:59:1:59:34 | call to unsafeFunction(pointer:) | +| expressions.swift:59:25:59:26 | &... | 0 | getImmediateSubExpr() | expressions.swift:59:26:59:26 | myNumber | +| expressions.swift:59:25:59:26 | (UnsafePointer) ... | 0 | getImmediateSubExpr() | expressions.swift:59:25:59:26 | &... | +| expressions.swift:60:1:60:63 | call to withUnsafePointer(to:_:) | 0 | getImmediateFunction() | expressions.swift:60:1:60:1 | withUnsafePointer(to:_:) | +| expressions.swift:60:1:60:63 | { ... } | 0 | getImmediateBody() | expressions.swift:60:1:60:63 | { ... } | +| expressions.swift:60:1:60:63 | { ... } | 0 | getImmediateElement(0) | expressions.swift:60:1:60:63 | call to withUnsafePointer(to:_:) | +| expressions.swift:60:23:60:23 | (Int) ... | 0 | getImmediateSubExpr() | expressions.swift:60:23:60:23 | myNumber | +| expressions.swift:60:33:60:63 | ((UnsafePointer) throws -> ()) ... | 0 | getImmediateSubExpr() | expressions.swift:60:33:60:63 | { ... } | +| expressions.swift:60:33:60:63 | { ... } | 0 | getImmediateElement(0) | expressions.swift:60:35:60:61 | return ... | +| expressions.swift:60:33:60:63 | { ... } | 1 | getImmediateParam(0) | expressions.swift:60:33:60:33 | $0 | +| expressions.swift:60:33:60:63 | { ... } | 2 | getImmediateBody() | expressions.swift:60:33:60:63 | { ... } | +| expressions.swift:60:35:60:61 | call to unsafeFunction(pointer:) | 0 | getImmediateFunction() | expressions.swift:60:35:60:35 | unsafeFunction(pointer:) | +| expressions.swift:60:35:60:61 | return ... | 0 | getImmediateResult() | expressions.swift:60:35:60:61 | call to unsafeFunction(pointer:) | +| expressions.swift:62:7:62:7 | deinit | 0 | getImmediateSelfParam() | expressions.swift:62:7:62:7 | self | +| expressions.swift:62:7:62:7 | deinit | 1 | getImmediateBody() | expressions.swift:62:7:62:7 | { ... } | +| expressions.swift:63:3:67:3 | init | 0 | getImmediateSelfParam() | expressions.swift:63:3:63:3 | self | +| expressions.swift:63:3:67:3 | init | 1 | getImmediateParam(0) | expressions.swift:63:9:63:12 | x | +| expressions.swift:63:3:67:3 | init | 2 | getImmediateBody() | expressions.swift:63:17:67:3 | { ... } | +| expressions.swift:63:17:67:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:64:5:66:5 | if ... then { ... } | +| expressions.swift:63:17:67:3 | { ... } | 1 | getImmediateElement(1) | expressions.swift:67:3:67:3 | return | +| expressions.swift:64:5:66:5 | if ... then { ... } | 0 | getImmediateCondition() | expressions.swift:64:8:64:12 | StmtCondition | +| expressions.swift:64:5:66:5 | if ... then { ... } | 1 | getImmediateThen() | expressions.swift:64:14:66:5 | { ... } | +| expressions.swift:64:8:64:12 | ... .<(_:_:) ... | 0 | getImmediateFunction() | expressions.swift:64:10:64:10 | .<(_:_:) | +| expressions.swift:64:10:64:10 | .<(_:_:) | 0 | getImmediateBase() | expressions.swift:64:10:64:10 | Int.Type | +| expressions.swift:64:10:64:10 | Int.Type | 0 | getImmediateTypeRepr() | expressions.swift:64:10:64:10 | Int | +| expressions.swift:64:14:66:5 | { ... } | 0 | getImmediateElement(0) | expressions.swift:65:7:65:14 | fail | +| expressions.swift:70:7:70:7 | deinit | 0 | getImmediateSelfParam() | expressions.swift:70:7:70:7 | self | +| expressions.swift:70:7:70:7 | deinit | 1 | getImmediateBody() | expressions.swift:70:7:70:7 | { ... } | +| expressions.swift:71:3:71:11 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:71:7:71:11 | ... as ... | +| expressions.swift:71:7:71:7 | get | 0 | getImmediateSelfParam() | expressions.swift:71:7:71:7 | self | +| expressions.swift:71:7:71:7 | get | 1 | getImmediateBody() | expressions.swift:71:7:71:7 | { ... } | +| expressions.swift:71:7:71:7 | xx | 0 | getImmediateAccessorDecl(0) | expressions.swift:71:7:71:7 | get | +| expressions.swift:71:7:71:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:71:7:71:11 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:71:7:71:7 | xx | +| expressions.swift:71:7:71:11 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:71:11:71:11 | Int | +| expressions.swift:72:3:74:3 | init | 0 | getImmediateSelfParam() | expressions.swift:72:3:72:3 | self | +| expressions.swift:72:3:74:3 | init | 1 | getImmediateParam(0) | expressions.swift:72:8:72:11 | x | +| expressions.swift:72:3:74:3 | init | 2 | getImmediateBody() | expressions.swift:72:16:74:3 | { ... } | +| expressions.swift:72:16:74:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:73:5:73:10 | ... = ... | +| expressions.swift:72:16:74:3 | { ... } | 1 | getImmediateElement(1) | expressions.swift:74:3:74:3 | return | +| expressions.swift:73:5:73:5 | .xx | 0 | getImmediateBase() | expressions.swift:73:5:73:5 | self | +| expressions.swift:73:5:73:10 | ... = ... | 0 | getImmediateDest() | expressions.swift:73:5:73:5 | .xx | +| expressions.swift:73:5:73:10 | ... = ... | 1 | getImmediateSource() | expressions.swift:73:10:73:10 | x | +| expressions.swift:77:7:77:7 | call to _unimplementedInitializer(className:initName:file:line:column:) | 0 | getImmediateFunction() | expressions.swift:77:7:77:7 | _unimplementedInitializer(className:initName:file:line:column:) | +| expressions.swift:77:7:77:7 | deinit | 0 | getImmediateSelfParam() | expressions.swift:77:7:77:7 | self | +| expressions.swift:77:7:77:7 | deinit | 1 | getImmediateBody() | expressions.swift:77:7:77:7 | { ... } | +| expressions.swift:77:21:77:21 | init | 0 | getImmediateSelfParam() | expressions.swift:77:21:77:21 | self | +| expressions.swift:77:21:77:21 | init | 1 | getImmediateParam(0) | file://:0:0:0:0 | x | +| expressions.swift:77:21:77:21 | init | 2 | getImmediateBody() | file://:0:0:0:0 | { ... } | +| expressions.swift:78:3:80:3 | init | 0 | getImmediateSelfParam() | expressions.swift:78:3:78:3 | self | +| expressions.swift:78:3:80:3 | init | 1 | getImmediateBody() | expressions.swift:78:10:80:3 | { ... } | +| expressions.swift:78:10:80:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:79:5:79:21 | self = ... | +| expressions.swift:78:10:80:3 | { ... } | 1 | getImmediateElement(1) | expressions.swift:80:3:80:3 | return | +| expressions.swift:79:5:79:11 | call to ... | 0 | getImmediateFunction() | expressions.swift:79:11:79:11 | init | +| expressions.swift:79:5:79:11 | call to ... | 2 | getImmediateBase() | expressions.swift:79:5:79:5 | super | +| expressions.swift:79:5:79:21 | call to ... | 0 | getImmediateFunction() | expressions.swift:79:5:79:11 | call to ... | +| expressions.swift:79:5:79:21 | self = ... | 0 | getImmediateSubExpr() | expressions.swift:79:5:79:21 | call to ... | +| expressions.swift:83:1:83:23 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:83:15:83:23 | call to init | +| expressions.swift:83:1:83:23 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:83:5:83:5 | derived | +| expressions.swift:83:1:83:23 | { ... } | 0 | getImmediateBody() | expressions.swift:83:1:83:23 | { ... } | +| expressions.swift:83:1:83:23 | { ... } | 0 | getImmediateElement(0) | expressions.swift:83:1:83:23 | var ... = ... | +| expressions.swift:83:15:83:15 | Derived.Type | 0 | getImmediateTypeRepr() | expressions.swift:83:15:83:15 | Derived | +| expressions.swift:83:15:83:15 | call to init | 0 | getImmediateFunction() | expressions.swift:83:15:83:15 | init | +| expressions.swift:83:15:83:15 | call to init | 2 | getImmediateBase() | expressions.swift:83:15:83:15 | Derived.Type | +| expressions.swift:83:15:83:23 | call to init | 0 | getImmediateFunction() | expressions.swift:83:15:83:15 | call to init | +| expressions.swift:84:1:84:13 | ... = ... | 0 | getImmediateDest() | expressions.swift:84:1:84:1 | _ | +| expressions.swift:84:1:84:13 | ... = ... | 1 | getImmediateSource() | expressions.swift:84:5:84:13 | .xx | +| expressions.swift:84:1:84:13 | { ... } | 0 | getImmediateBody() | expressions.swift:84:1:84:13 | { ... } | +| expressions.swift:84:1:84:13 | { ... } | 0 | getImmediateElement(0) | expressions.swift:84:1:84:13 | ... = ... | +| expressions.swift:84:5:84:5 | (Base) ... | 0 | getImmediateSubExpr() | expressions.swift:84:5:84:5 | derived | +| expressions.swift:84:5:84:13 | .xx | 0 | getImmediateBase() | expressions.swift:84:5:84:5 | (Base) ... | +| expressions.swift:86:1:86:13 | var ... = ... | 0 | getImmediateInit(0) | file://:0:0:0:0 | nil | +| expressions.swift:86:1:86:13 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:86:5:86:13 | ... as ... | +| expressions.swift:86:1:86:13 | { ... } | 0 | getImmediateBody() | expressions.swift:86:1:86:13 | { ... } | +| expressions.swift:86:1:86:13 | { ... } | 0 | getImmediateElement(0) | expressions.swift:86:1:86:13 | var ... = ... | +| expressions.swift:86:5:86:13 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:86:5:86:5 | opt | +| expressions.swift:86:5:86:13 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:86:10:86:13 | Int? | +| expressions.swift:87:1:87:4 | ...! | 0 | getImmediateSubExpr() | expressions.swift:87:1:87:1 | opt | +| expressions.swift:87:1:87:4 | { ... } | 0 | getImmediateBody() | expressions.swift:87:1:87:4 | { ... } | +| expressions.swift:87:1:87:4 | { ... } | 0 | getImmediateElement(0) | expressions.swift:87:1:87:4 | ...! | +| expressions.swift:88:1:88:6 | ...[...] | 0 | getImmediateBase() | expressions.swift:88:1:88:1 | d | +| expressions.swift:88:1:88:7 | ...! | 0 | getImmediateSubExpr() | expressions.swift:88:1:88:6 | ...[...] | +| expressions.swift:88:1:88:7 | { ... } | 0 | getImmediateBody() | expressions.swift:88:1:88:7 | { ... } | +| expressions.swift:88:1:88:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:88:1:88:7 | ...! | +| expressions.swift:90:7:90:7 | deinit | 0 | getImmediateSelfParam() | expressions.swift:90:7:90:7 | self | +| expressions.swift:90:7:90:7 | deinit | 1 | getImmediateBody() | expressions.swift:90:7:90:7 | { ... } | +| expressions.swift:90:7:90:7 | init | 0 | getImmediateSelfParam() | expressions.swift:90:7:90:7 | self | +| expressions.swift:90:7:90:7 | init | 1 | getImmediateBody() | expressions.swift:90:7:90:7 | { ... } | +| expressions.swift:90:7:90:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:90:7:90:7 | return | +| expressions.swift:92:1:92:55 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:92:14:92:55 | call to toOpaque() | +| expressions.swift:92:1:92:55 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:92:5:92:5 | opaque | +| expressions.swift:92:1:92:55 | { ... } | 0 | getImmediateBody() | expressions.swift:92:1:92:55 | { ... } | +| expressions.swift:92:1:92:55 | { ... } | 0 | getImmediateElement(0) | expressions.swift:92:1:92:55 | var ... = ... | +| expressions.swift:92:14:92:14 | Unmanaged.Type | 0 | getImmediateTypeRepr() | expressions.swift:92:14:92:14 | Unmanaged | +| expressions.swift:92:14:92:24 | .passRetained(_:) | 0 | getImmediateBase() | expressions.swift:92:14:92:14 | Unmanaged.Type | +| expressions.swift:92:14:92:44 | call to passRetained(_:) | 0 | getImmediateFunction() | expressions.swift:92:14:92:24 | .passRetained(_:) | +| expressions.swift:92:14:92:46 | .toOpaque() | 0 | getImmediateBase() | expressions.swift:92:14:92:44 | call to passRetained(_:) | +| expressions.swift:92:14:92:55 | call to toOpaque() | 0 | getImmediateFunction() | expressions.swift:92:14:92:46 | .toOpaque() | +| expressions.swift:92:37:92:37 | ToPtr.Type | 0 | getImmediateTypeRepr() | expressions.swift:92:37:92:37 | ToPtr | +| expressions.swift:92:37:92:37 | call to init | 0 | getImmediateFunction() | expressions.swift:92:37:92:37 | init | +| expressions.swift:92:37:92:37 | call to init | 2 | getImmediateBase() | expressions.swift:92:37:92:37 | ToPtr.Type | +| expressions.swift:92:37:92:43 | call to init | 0 | getImmediateFunction() | expressions.swift:92:37:92:37 | call to init | +| expressions.swift:93:1:93:16 | Unmanaged.Type | 0 | getImmediateTypeRepr() | expressions.swift:93:1:93:16 | Unmanaged | +| expressions.swift:93:1:93:18 | .fromOpaque(_:) | 0 | getImmediateBase() | expressions.swift:93:1:93:16 | Unmanaged.Type | +| expressions.swift:93:1:93:35 | call to fromOpaque(_:) | 0 | getImmediateFunction() | expressions.swift:93:1:93:18 | .fromOpaque(_:) | +| expressions.swift:93:1:93:35 | { ... } | 0 | getImmediateBody() | expressions.swift:93:1:93:35 | { ... } | +| expressions.swift:93:1:93:35 | { ... } | 0 | getImmediateElement(0) | expressions.swift:93:1:93:35 | call to fromOpaque(_:) | +| expressions.swift:93:29:93:29 | (UnsafeRawPointer) ... | 0 | getImmediateSubExpr() | expressions.swift:93:29:93:29 | opaque | +| expressions.swift:95:8:95:8 | init | 0 | getImmediateSelfParam() | expressions.swift:95:8:95:8 | self | +| expressions.swift:95:8:95:8 | init | 1 | getImmediateParam(0) | expressions.swift:95:8:95:8 | normalField | +| expressions.swift:96:3:101:3 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:96:7:96:22 | ... as ... | +| expressions.swift:96:7:96:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:96:7:96:7 | self | +| expressions.swift:96:7:96:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:96:7:96:7 | { ... } | +| expressions.swift:96:7:96:7 | settableField | 0 | getImmediateAccessorDecl(0) | expressions.swift:97:5:97:11 | set | +| expressions.swift:96:7:96:7 | settableField | 1 | getImmediateAccessorDecl(1) | expressions.swift:98:5:100:5 | get | +| expressions.swift:96:7:96:7 | settableField | 2 | getImmediateAccessorDecl(2) | expressions.swift:96:7:96:7 | (unnamed function decl) | +| expressions.swift:96:7:96:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:96:7:96:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:96:7:96:7 | yield ... | +| expressions.swift:96:7:96:22 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:96:7:96:7 | settableField | +| expressions.swift:96:7:96:22 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:96:22:96:22 | Int | +| expressions.swift:97:5:97:11 | set | 0 | getImmediateSelfParam() | expressions.swift:97:5:97:5 | self | +| expressions.swift:97:5:97:11 | set | 1 | getImmediateParam(0) | expressions.swift:97:5:97:5 | newValue | +| expressions.swift:97:5:97:11 | set | 2 | getImmediateBody() | expressions.swift:97:9:97:11 | { ... } | +| expressions.swift:98:5:100:5 | get | 0 | getImmediateSelfParam() | expressions.swift:98:5:98:5 | self | +| expressions.swift:98:5:100:5 | get | 1 | getImmediateBody() | expressions.swift:98:9:100:5 | { ... } | +| expressions.swift:98:9:100:5 | { ... } | 0 | getImmediateElement(0) | expressions.swift:99:7:99:14 | return ... | +| expressions.swift:99:7:99:14 | return ... | 0 | getImmediateResult() | expressions.swift:99:14:99:14 | 0 | +| expressions.swift:105:3:107:3 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:105:7:105:23 | ... as ... | +| expressions.swift:105:7:105:7 | readOnlyField1 | 0 | getImmediateAccessorDecl(0) | expressions.swift:105:27:107:3 | get | +| expressions.swift:105:7:105:23 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:105:7:105:7 | readOnlyField1 | +| expressions.swift:105:7:105:23 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:105:23:105:23 | Int | +| expressions.swift:105:27:107:3 | get | 0 | getImmediateSelfParam() | expressions.swift:105:27:105:27 | self | +| expressions.swift:105:27:107:3 | get | 1 | getImmediateBody() | expressions.swift:105:27:107:3 | { ... } | +| expressions.swift:105:27:107:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:106:5:106:12 | return ... | +| expressions.swift:106:5:106:12 | return ... | 0 | getImmediateResult() | expressions.swift:106:12:106:12 | 0 | +| expressions.swift:110:3:114:3 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:110:7:110:23 | ... as ... | +| expressions.swift:110:7:110:7 | readOnlyField2 | 0 | getImmediateAccessorDecl(0) | expressions.swift:111:5:113:5 | get | +| expressions.swift:110:7:110:23 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:110:7:110:7 | readOnlyField2 | +| expressions.swift:110:7:110:23 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:110:23:110:23 | Int | +| expressions.swift:111:5:113:5 | get | 0 | getImmediateSelfParam() | expressions.swift:111:5:111:5 | self | +| expressions.swift:111:5:113:5 | get | 1 | getImmediateBody() | expressions.swift:111:9:113:5 | { ... } | +| expressions.swift:111:9:113:5 | { ... } | 0 | getImmediateElement(0) | expressions.swift:112:7:112:14 | return ... | +| expressions.swift:112:7:112:14 | return ... | 0 | getImmediateResult() | expressions.swift:112:14:112:14 | 0 | +| expressions.swift:116:3:116:21 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:116:7:116:21 | ... as ... | +| expressions.swift:116:7:116:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:116:7:116:7 | self | +| expressions.swift:116:7:116:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:116:7:116:7 | { ... } | +| expressions.swift:116:7:116:7 | get | 0 | getImmediateSelfParam() | expressions.swift:116:7:116:7 | self | +| expressions.swift:116:7:116:7 | get | 1 | getImmediateBody() | expressions.swift:116:7:116:7 | { ... } | +| expressions.swift:116:7:116:7 | normalField | 0 | getImmediateAccessorDecl(0) | expressions.swift:116:7:116:7 | get | +| expressions.swift:116:7:116:7 | normalField | 1 | getImmediateAccessorDecl(1) | expressions.swift:116:7:116:7 | set | +| expressions.swift:116:7:116:7 | normalField | 2 | getImmediateAccessorDecl(2) | expressions.swift:116:7:116:7 | (unnamed function decl) | +| expressions.swift:116:7:116:7 | set | 0 | getImmediateSelfParam() | expressions.swift:116:7:116:7 | self | +| expressions.swift:116:7:116:7 | set | 1 | getImmediateParam(0) | expressions.swift:116:7:116:7 | value | +| expressions.swift:116:7:116:7 | set | 2 | getImmediateBody() | expressions.swift:116:7:116:7 | { ... } | +| expressions.swift:116:7:116:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:116:7:116:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:116:7:116:7 | yield ... | +| expressions.swift:116:7:116:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| expressions.swift:116:7:116:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:116:7:116:21 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:116:7:116:7 | normalField | +| expressions.swift:116:7:116:21 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:116:21:116:21 | Int | +| expressions.swift:118:3:118:3 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:118:3:118:3 | self | +| expressions.swift:118:3:118:3 | (unnamed function decl) | 1 | getImmediateParam(0) | file://:0:0:0:0 | x | +| expressions.swift:118:3:118:3 | (unnamed function decl) | 2 | getImmediateBody() | expressions.swift:118:3:118:3 | { ... } | +| expressions.swift:118:3:118:3 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:118:3:118:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:118:3:118:3 | yield ... | +| expressions.swift:118:3:123:3 | subscript ... | 0 | getImmediateAccessorDecl(0) | expressions.swift:119:5:121:5 | get | +| expressions.swift:118:3:123:3 | subscript ... | 1 | getImmediateAccessorDecl(1) | expressions.swift:122:5:122:11 | set | +| expressions.swift:118:3:123:3 | subscript ... | 2 | getImmediateAccessorDecl(2) | expressions.swift:118:3:118:3 | (unnamed function decl) | +| expressions.swift:118:3:123:3 | subscript ... | 3 | getImmediateParam(0) | expressions.swift:118:13:118:16 | x | +| expressions.swift:119:5:121:5 | get | 0 | getImmediateSelfParam() | expressions.swift:119:5:119:5 | self | +| expressions.swift:119:5:121:5 | get | 1 | getImmediateParam(0) | expressions.swift:118:13:118:13 | x | +| expressions.swift:119:5:121:5 | get | 2 | getImmediateBody() | expressions.swift:119:9:121:5 | { ... } | +| expressions.swift:119:9:121:5 | { ... } | 0 | getImmediateElement(0) | expressions.swift:120:7:120:14 | return ... | +| expressions.swift:120:7:120:14 | return ... | 0 | getImmediateResult() | expressions.swift:120:14:120:14 | 0 | +| expressions.swift:122:5:122:11 | set | 0 | getImmediateSelfParam() | expressions.swift:122:5:122:5 | self | +| expressions.swift:122:5:122:11 | set | 1 | getImmediateParam(0) | expressions.swift:122:5:122:5 | newValue | +| expressions.swift:122:5:122:11 | set | 2 | getImmediateParam(1) | expressions.swift:118:13:118:13 | x | +| expressions.swift:122:5:122:11 | set | 3 | getImmediateBody() | expressions.swift:122:9:122:11 | { ... } | +| expressions.swift:125:3:127:3 | subscript ... | 0 | getImmediateAccessorDecl(0) | expressions.swift:125:37:127:3 | get | +| expressions.swift:125:3:127:3 | subscript ... | 1 | getImmediateParam(0) | expressions.swift:125:13:125:16 | x | +| expressions.swift:125:3:127:3 | subscript ... | 2 | getImmediateParam(1) | expressions.swift:125:21:125:25 | y | +| expressions.swift:125:37:127:3 | get | 0 | getImmediateSelfParam() | expressions.swift:125:37:125:37 | self | +| expressions.swift:125:37:127:3 | get | 1 | getImmediateParam(0) | expressions.swift:125:13:125:13 | x | +| expressions.swift:125:37:127:3 | get | 2 | getImmediateParam(1) | expressions.swift:125:21:125:21 | y | +| expressions.swift:125:37:127:3 | get | 3 | getImmediateBody() | expressions.swift:125:37:127:3 | { ... } | +| expressions.swift:125:37:127:3 | { ... } | 0 | getImmediateElement(0) | expressions.swift:126:5:126:12 | return ... | +| expressions.swift:126:5:126:12 | return ... | 0 | getImmediateResult() | expressions.swift:126:12:126:12 | 0 | +| expressions.swift:130:1:139:1 | testProperties(hp:) | 1 | getImmediateParam(0) | expressions.swift:130:21:130:32 | hp | +| expressions.swift:130:1:139:1 | testProperties(hp:) | 2 | getImmediateBody() | expressions.swift:130:52:139:1 | { ... } | +| expressions.swift:130:52:139:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:131:3:131:22 | ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 1 | getImmediateElement(1) | expressions.swift:132:3:132:14 | var ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 2 | getImmediateElement(2) | expressions.swift:132:7:132:7 | x | +| expressions.swift:130:52:139:1 | { ... } | 3 | getImmediateElement(3) | expressions.swift:133:3:133:14 | var ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 4 | getImmediateElement(4) | expressions.swift:133:7:133:7 | y | +| expressions.swift:130:52:139:1 | { ... } | 5 | getImmediateElement(5) | expressions.swift:134:3:134:14 | var ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 6 | getImmediateElement(6) | expressions.swift:134:7:134:7 | z | +| expressions.swift:130:52:139:1 | { ... } | 7 | getImmediateElement(7) | expressions.swift:135:3:135:20 | ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 8 | getImmediateElement(8) | expressions.swift:136:3:136:14 | var ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 9 | getImmediateElement(9) | expressions.swift:136:7:136:7 | w | +| expressions.swift:130:52:139:1 | { ... } | 10 | getImmediateElement(10) | expressions.swift:137:3:137:11 | ... = ... | +| expressions.swift:130:52:139:1 | { ... } | 11 | getImmediateElement(11) | expressions.swift:138:3:138:17 | return ... | +| expressions.swift:131:3:131:6 | .settableField | 0 | getImmediateBase() | expressions.swift:131:3:131:3 | hp | +| expressions.swift:131:3:131:22 | ... = ... | 0 | getImmediateDest() | expressions.swift:131:3:131:6 | .settableField | +| expressions.swift:131:3:131:22 | ... = ... | 1 | getImmediateSource() | expressions.swift:131:22:131:22 | 42 | +| expressions.swift:132:3:132:14 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:132:11:132:14 | (Int) ... | +| expressions.swift:132:3:132:14 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:132:7:132:7 | x | +| expressions.swift:132:11:132:14 | (Int) ... | 0 | getImmediateSubExpr() | expressions.swift:132:11:132:14 | .settableField | +| expressions.swift:132:11:132:14 | .settableField | 0 | getImmediateBase() | expressions.swift:132:11:132:11 | hp | +| expressions.swift:133:3:133:14 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:133:11:133:14 | .readOnlyField1 | +| expressions.swift:133:3:133:14 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:133:7:133:7 | y | +| expressions.swift:133:11:133:11 | (HasProperty) ... | 0 | getImmediateSubExpr() | expressions.swift:133:11:133:11 | hp | +| expressions.swift:133:11:133:14 | .readOnlyField1 | 0 | getImmediateBase() | expressions.swift:133:11:133:11 | (HasProperty) ... | +| expressions.swift:134:3:134:14 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:134:11:134:14 | .readOnlyField2 | +| expressions.swift:134:3:134:14 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:134:7:134:7 | z | +| expressions.swift:134:11:134:11 | (HasProperty) ... | 0 | getImmediateSubExpr() | expressions.swift:134:11:134:11 | hp | +| expressions.swift:134:11:134:14 | .readOnlyField2 | 0 | getImmediateBase() | expressions.swift:134:11:134:11 | (HasProperty) ... | +| expressions.swift:135:3:135:6 | .normalField | 0 | getImmediateBase() | expressions.swift:135:3:135:3 | hp | +| expressions.swift:135:3:135:20 | ... = ... | 0 | getImmediateDest() | expressions.swift:135:3:135:6 | .normalField | +| expressions.swift:135:3:135:20 | ... = ... | 1 | getImmediateSource() | expressions.swift:135:20:135:20 | 99 | +| expressions.swift:136:3:136:14 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:136:11:136:14 | (Int) ... | +| expressions.swift:136:3:136:14 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:136:7:136:7 | w | +| expressions.swift:136:11:136:14 | (Int) ... | 0 | getImmediateSubExpr() | expressions.swift:136:11:136:14 | .normalField | +| expressions.swift:136:11:136:14 | .normalField | 0 | getImmediateBase() | expressions.swift:136:11:136:11 | hp | +| expressions.swift:137:3:137:3 | &... | 0 | getImmediateSubExpr() | expressions.swift:137:3:137:3 | hp | +| expressions.swift:137:3:137:7 | ...[...] | 0 | getImmediateBase() | expressions.swift:137:3:137:3 | &... | +| expressions.swift:137:3:137:11 | ... = ... | 0 | getImmediateDest() | expressions.swift:137:3:137:7 | ...[...] | +| expressions.swift:137:3:137:11 | ... = ... | 1 | getImmediateSource() | expressions.swift:137:11:137:11 | 2 | +| expressions.swift:138:3:138:17 | return ... | 0 | getImmediateResult() | expressions.swift:138:10:138:17 | ...[...] | +| expressions.swift:138:10:138:10 | (HasProperty) ... | 0 | getImmediateSubExpr() | expressions.swift:138:10:138:10 | hp | +| expressions.swift:138:10:138:17 | ...[...] | 0 | getImmediateBase() | expressions.swift:138:10:138:10 | (HasProperty) ... | +| expressions.swift:141:8:141:8 | init | 0 | getImmediateSelfParam() | expressions.swift:141:8:141:8 | self | +| expressions.swift:141:8:141:8 | init | 1 | getImmediateParam(0) | expressions.swift:141:8:141:8 | x | +| expressions.swift:142:3:142:11 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:142:7:142:11 | ... as ... | +| expressions.swift:142:7:142:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:142:7:142:7 | self | +| expressions.swift:142:7:142:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:142:7:142:7 | { ... } | +| expressions.swift:142:7:142:7 | get | 0 | getImmediateSelfParam() | expressions.swift:142:7:142:7 | self | +| expressions.swift:142:7:142:7 | get | 1 | getImmediateBody() | expressions.swift:142:7:142:7 | { ... } | +| expressions.swift:142:7:142:7 | set | 0 | getImmediateSelfParam() | expressions.swift:142:7:142:7 | self | +| expressions.swift:142:7:142:7 | set | 1 | getImmediateParam(0) | expressions.swift:142:7:142:7 | value | +| expressions.swift:142:7:142:7 | set | 2 | getImmediateBody() | expressions.swift:142:7:142:7 | { ... } | +| expressions.swift:142:7:142:7 | x | 0 | getImmediateAccessorDecl(0) | expressions.swift:142:7:142:7 | get | +| expressions.swift:142:7:142:7 | x | 1 | getImmediateAccessorDecl(1) | expressions.swift:142:7:142:7 | set | +| expressions.swift:142:7:142:7 | x | 2 | getImmediateAccessorDecl(2) | expressions.swift:142:7:142:7 | (unnamed function decl) | +| expressions.swift:142:7:142:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:142:7:142:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:142:7:142:7 | yield ... | +| expressions.swift:142:7:142:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| expressions.swift:142:7:142:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:142:7:142:11 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:142:7:142:7 | x | +| expressions.swift:142:7:142:11 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:142:11:142:11 | Int | +| expressions.swift:145:8:145:8 | init | 0 | getImmediateSelfParam() | expressions.swift:145:8:145:8 | self | +| expressions.swift:145:8:145:8 | init | 1 | getImmediateParam(0) | expressions.swift:145:8:145:8 | b | +| expressions.swift:145:8:145:8 | init | 2 | getImmediateParam(1) | expressions.swift:145:8:145:8 | bs | +| expressions.swift:145:8:145:8 | init | 3 | getImmediateParam(2) | expressions.swift:145:8:145:8 | mayB | +| expressions.swift:146:3:146:11 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:146:7:146:11 | ... as ... | +| expressions.swift:146:7:146:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:146:7:146:7 | self | +| expressions.swift:146:7:146:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:146:7:146:7 | { ... } | +| expressions.swift:146:7:146:7 | b | 0 | getImmediateAccessorDecl(0) | expressions.swift:146:7:146:7 | get | +| expressions.swift:146:7:146:7 | b | 1 | getImmediateAccessorDecl(1) | expressions.swift:146:7:146:7 | set | +| expressions.swift:146:7:146:7 | b | 2 | getImmediateAccessorDecl(2) | expressions.swift:146:7:146:7 | (unnamed function decl) | +| expressions.swift:146:7:146:7 | get | 0 | getImmediateSelfParam() | expressions.swift:146:7:146:7 | self | +| expressions.swift:146:7:146:7 | get | 1 | getImmediateBody() | expressions.swift:146:7:146:7 | { ... } | +| expressions.swift:146:7:146:7 | set | 0 | getImmediateSelfParam() | expressions.swift:146:7:146:7 | self | +| expressions.swift:146:7:146:7 | set | 1 | getImmediateParam(0) | expressions.swift:146:7:146:7 | value | +| expressions.swift:146:7:146:7 | set | 2 | getImmediateBody() | expressions.swift:146:7:146:7 | { ... } | +| expressions.swift:146:7:146:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:146:7:146:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:146:7:146:7 | yield ... | +| expressions.swift:146:7:146:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| expressions.swift:146:7:146:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:146:7:146:11 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:146:7:146:7 | b | +| expressions.swift:146:7:146:11 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:146:11:146:11 | B | +| expressions.swift:147:3:147:14 | var ... = ... | 0 | getImmediatePattern(0) | expressions.swift:147:7:147:14 | ... as ... | +| expressions.swift:147:7:147:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:147:7:147:7 | self | +| expressions.swift:147:7:147:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:147:7:147:7 | { ... } | +| expressions.swift:147:7:147:7 | bs | 0 | getImmediateAccessorDecl(0) | expressions.swift:147:7:147:7 | get | +| expressions.swift:147:7:147:7 | bs | 1 | getImmediateAccessorDecl(1) | expressions.swift:147:7:147:7 | set | +| expressions.swift:147:7:147:7 | bs | 2 | getImmediateAccessorDecl(2) | expressions.swift:147:7:147:7 | (unnamed function decl) | +| expressions.swift:147:7:147:7 | get | 0 | getImmediateSelfParam() | expressions.swift:147:7:147:7 | self | +| expressions.swift:147:7:147:7 | get | 1 | getImmediateBody() | expressions.swift:147:7:147:7 | { ... } | +| expressions.swift:147:7:147:7 | set | 0 | getImmediateSelfParam() | expressions.swift:147:7:147:7 | self | +| expressions.swift:147:7:147:7 | set | 1 | getImmediateParam(0) | expressions.swift:147:7:147:7 | value | +| expressions.swift:147:7:147:7 | set | 2 | getImmediateBody() | expressions.swift:147:7:147:7 | { ... } | +| expressions.swift:147:7:147:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:147:7:147:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:147:7:147:7 | yield ... | +| expressions.swift:147:7:147:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| expressions.swift:147:7:147:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:147:7:147:14 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:147:7:147:7 | bs | +| expressions.swift:147:7:147:14 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:147:12:147:14 | [B] | +| expressions.swift:148:3:148:15 | var ... = ... | 0 | getImmediateInit(0) | file://:0:0:0:0 | nil | +| expressions.swift:148:3:148:15 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:148:7:148:15 | ... as ... | +| expressions.swift:148:7:148:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | expressions.swift:148:7:148:7 | self | +| expressions.swift:148:7:148:7 | (unnamed function decl) | 1 | getImmediateBody() | expressions.swift:148:7:148:7 | { ... } | +| expressions.swift:148:7:148:7 | get | 0 | getImmediateSelfParam() | expressions.swift:148:7:148:7 | self | +| expressions.swift:148:7:148:7 | get | 1 | getImmediateBody() | expressions.swift:148:7:148:7 | { ... } | +| expressions.swift:148:7:148:7 | mayB | 0 | getImmediateAccessorDecl(0) | expressions.swift:148:7:148:7 | get | +| expressions.swift:148:7:148:7 | mayB | 1 | getImmediateAccessorDecl(1) | expressions.swift:148:7:148:7 | set | +| expressions.swift:148:7:148:7 | mayB | 2 | getImmediateAccessorDecl(2) | expressions.swift:148:7:148:7 | (unnamed function decl) | +| expressions.swift:148:7:148:7 | set | 0 | getImmediateSelfParam() | expressions.swift:148:7:148:7 | self | +| expressions.swift:148:7:148:7 | set | 1 | getImmediateParam(0) | expressions.swift:148:7:148:7 | value | +| expressions.swift:148:7:148:7 | set | 2 | getImmediateBody() | expressions.swift:148:7:148:7 | { ... } | +| expressions.swift:148:7:148:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| expressions.swift:148:7:148:7 | { ... } | 0 | getImmediateElement(0) | expressions.swift:148:7:148:7 | yield ... | +| expressions.swift:148:7:148:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| expressions.swift:148:7:148:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| expressions.swift:148:7:148:15 | ... as ... | 0 | getImmediateSubPattern() | expressions.swift:148:7:148:7 | mayB | +| expressions.swift:148:7:148:15 | ... as ... | 1 | getImmediateTypeRepr() | expressions.swift:148:14:148:15 | B? | +| expressions.swift:151:1:155:1 | test(a:keyPathInt:keyPathB:) | 1 | getImmediateParam(0) | expressions.swift:151:11:151:15 | a | +| expressions.swift:151:1:155:1 | test(a:keyPathInt:keyPathB:) | 2 | getImmediateParam(1) | expressions.swift:151:18:151:53 | keyPathInt | +| expressions.swift:151:1:155:1 | test(a:keyPathInt:keyPathB:) | 3 | getImmediateParam(2) | expressions.swift:151:56:151:87 | keyPathB | +| expressions.swift:151:1:155:1 | test(a:keyPathInt:keyPathB:) | 4 | getImmediateBody() | expressions.swift:151:90:155:1 | { ... } | +| expressions.swift:151:90:155:1 | { ... } | 0 | getImmediateElement(0) | expressions.swift:152:3:152:47 | var ... = ... | +| expressions.swift:151:90:155:1 | { ... } | 1 | getImmediateElement(1) | expressions.swift:152:7:152:7 | apply_keyPathInt | +| expressions.swift:151:90:155:1 | { ... } | 2 | getImmediateElement(2) | expressions.swift:153:3:153:43 | var ... = ... | +| expressions.swift:151:90:155:1 | { ... } | 3 | getImmediateElement(3) | expressions.swift:153:7:153:7 | apply_keyPathB | +| expressions.swift:151:90:155:1 | { ... } | 4 | getImmediateElement(4) | expressions.swift:154:3:154:56 | var ... = ... | +| expressions.swift:151:90:155:1 | { ... } | 5 | getImmediateElement(5) | expressions.swift:154:7:154:7 | nested_apply | +| expressions.swift:152:3:152:47 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:152:26:152:47 | \\...[...] | +| expressions.swift:152:3:152:47 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:152:7:152:7 | apply_keyPathInt | +| expressions.swift:152:26:152:47 | \\...[...] | 0 | getImmediateBase() | expressions.swift:152:26:152:26 | a | +| expressions.swift:152:26:152:47 | \\...[...] | 1 | getImmediateKeyPath() | expressions.swift:152:37:152:37 | keyPathInt | +| expressions.swift:153:3:153:43 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:153:24:153:43 | \\...[...] | +| expressions.swift:153:3:153:43 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:153:7:153:7 | apply_keyPathB | +| expressions.swift:153:24:153:43 | \\...[...] | 0 | getImmediateBase() | expressions.swift:153:24:153:24 | a | +| expressions.swift:153:24:153:43 | \\...[...] | 1 | getImmediateKeyPath() | expressions.swift:153:35:153:35 | keyPathB | +| expressions.swift:154:3:154:56 | var ... = ... | 0 | getImmediateInit(0) | expressions.swift:154:22:154:56 | \\...[...] | +| expressions.swift:154:3:154:56 | var ... = ... | 1 | getImmediatePattern(0) | expressions.swift:154:7:154:7 | nested_apply | +| expressions.swift:154:22:154:41 | \\...[...] | 0 | getImmediateBase() | expressions.swift:154:22:154:22 | a | +| expressions.swift:154:22:154:41 | \\...[...] | 1 | getImmediateKeyPath() | expressions.swift:154:33:154:33 | keyPathB | +| expressions.swift:154:22:154:56 | \\...[...] | 0 | getImmediateBase() | expressions.swift:154:22:154:41 | \\...[...] | +| expressions.swift:154:22:154:56 | \\...[...] | 1 | getImmediateKeyPath() | expressions.swift:154:52:154:55 | #keyPath(...) | +| expressions.swift:154:52:154:55 | #keyPath(...) | 0 | getImmediateRoot() | expressions.swift:154:53:154:53 | B | +| patterns.swift:1:1:7:1 | basic_patterns() | 1 | getImmediateBody() | patterns.swift:1:23:7:1 | { ... } | +| patterns.swift:1:23:7:1 | { ... } | 0 | getImmediateElement(0) | patterns.swift:2:5:2:18 | var ... = ... | +| patterns.swift:1:23:7:1 | { ... } | 1 | getImmediateElement(1) | patterns.swift:2:9:2:9 | an_int | +| patterns.swift:1:23:7:1 | { ... } | 2 | getImmediateElement(2) | patterns.swift:3:5:3:28 | var ... = ... | +| patterns.swift:1:23:7:1 | { ... } | 3 | getImmediateElement(3) | patterns.swift:3:9:3:9 | a_string | +| patterns.swift:1:23:7:1 | { ... } | 4 | getImmediateElement(4) | patterns.swift:4:5:4:29 | var ... = ... | +| patterns.swift:1:23:7:1 | { ... } | 5 | getImmediateElement(5) | patterns.swift:4:10:4:10 | x | +| patterns.swift:1:23:7:1 | { ... } | 6 | getImmediateElement(6) | patterns.swift:4:13:4:13 | y | +| patterns.swift:1:23:7:1 | { ... } | 7 | getImmediateElement(7) | patterns.swift:4:16:4:16 | z | +| patterns.swift:1:23:7:1 | { ... } | 8 | getImmediateElement(8) | patterns.swift:5:5:5:13 | var ... = ... | +| patterns.swift:1:23:7:1 | { ... } | 9 | getImmediateElement(9) | patterns.swift:6:5:6:15 | var ... = ... | +| patterns.swift:2:5:2:18 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:2:18:2:18 | 42 | +| patterns.swift:2:5:2:18 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:2:9:2:9 | an_int | +| patterns.swift:3:5:3:28 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:3:28:3:28 | here | +| patterns.swift:3:5:3:28 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:3:9:3:19 | ... as ... | +| patterns.swift:3:9:3:19 | ... as ... | 0 | getImmediateSubPattern() | patterns.swift:3:9:3:9 | a_string | +| patterns.swift:3:9:3:19 | ... as ... | 1 | getImmediateTypeRepr() | patterns.swift:3:19:3:19 | String | +| patterns.swift:4:5:4:29 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:4:21:4:29 | (...) | +| patterns.swift:4:5:4:29 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:4:9:4:17 | (...) | +| patterns.swift:4:9:4:17 | (...) | 0 | getImmediateElement(0) | patterns.swift:4:10:4:10 | x | +| patterns.swift:4:9:4:17 | (...) | 1 | getImmediateElement(1) | patterns.swift:4:13:4:13 | y | +| patterns.swift:4:9:4:17 | (...) | 2 | getImmediateElement(2) | patterns.swift:4:16:4:16 | z | +| patterns.swift:4:21:4:29 | (...) | 0 | getImmediateElement(0) | patterns.swift:4:22:4:22 | 1 | +| patterns.swift:4:21:4:29 | (...) | 1 | getImmediateElement(1) | patterns.swift:4:25:4:25 | 2 | +| patterns.swift:4:21:4:29 | (...) | 2 | getImmediateElement(2) | patterns.swift:4:28:4:28 | 3 | +| patterns.swift:5:5:5:13 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:5:13:5:13 | any | +| patterns.swift:5:5:5:13 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:5:9:5:9 | _ | +| patterns.swift:6:5:6:15 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:6:15:6:15 | paren | +| patterns.swift:6:5:6:15 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:6:9:6:11 | (...) | +| patterns.swift:6:9:6:11 | (...) | 0 | getImmediateSubPattern() | patterns.swift:6:10:6:10 | _ | +| patterns.swift:9:1:52:1 | switch_patterns() | 1 | getImmediateBody() | patterns.swift:9:24:52:1 | { ... } | +| patterns.swift:9:24:52:1 | { ... } | 0 | getImmediateElement(0) | patterns.swift:10:5:10:22 | var ... = ... | +| patterns.swift:9:24:52:1 | { ... } | 1 | getImmediateElement(1) | patterns.swift:10:9:10:9 | point | +| patterns.swift:9:24:52:1 | { ... } | 2 | getImmediateElement(2) | patterns.swift:11:5:13:5 | switch point { ... } | +| patterns.swift:9:24:52:1 | { ... } | 3 | getImmediateElement(3) | patterns.swift:15:5:18:5 | switch 3 { ... } | +| patterns.swift:9:24:52:1 | { ... } | 4 | getImmediateElement(4) | patterns.swift:20:5:22:5 | Foo | +| patterns.swift:9:24:52:1 | { ... } | 5 | getImmediateElement(5) | patterns.swift:24:5:24:19 | var ... = ... | +| patterns.swift:9:24:52:1 | { ... } | 6 | getImmediateElement(6) | patterns.swift:24:9:24:9 | v | +| patterns.swift:9:24:52:1 | { ... } | 7 | getImmediateElement(7) | patterns.swift:26:5:29:5 | switch v { ... } | +| patterns.swift:9:24:52:1 | { ... } | 8 | getImmediateElement(8) | patterns.swift:31:5:31:19 | var ... = ... | +| patterns.swift:9:24:52:1 | { ... } | 9 | getImmediateElement(9) | patterns.swift:31:9:31:9 | w | +| patterns.swift:9:24:52:1 | { ... } | 10 | getImmediateElement(10) | patterns.swift:33:5:36:5 | switch w { ... } | +| patterns.swift:9:24:52:1 | { ... } | 11 | getImmediateElement(11) | patterns.swift:38:5:38:18 | var ... = ... | +| patterns.swift:9:24:52:1 | { ... } | 12 | getImmediateElement(12) | patterns.swift:38:9:38:9 | a | +| patterns.swift:9:24:52:1 | { ... } | 13 | getImmediateElement(13) | patterns.swift:40:5:44:5 | switch a { ... } | +| patterns.swift:9:24:52:1 | { ... } | 14 | getImmediateElement(14) | patterns.swift:46:5:46:13 | var ... = ... | +| patterns.swift:9:24:52:1 | { ... } | 15 | getImmediateElement(15) | patterns.swift:46:9:46:9 | b | +| patterns.swift:9:24:52:1 | { ... } | 16 | getImmediateElement(16) | patterns.swift:48:5:51:5 | switch b { ... } | +| patterns.swift:10:5:10:22 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:10:17:10:22 | (...) | +| patterns.swift:10:5:10:22 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:10:9:10:9 | point | +| patterns.swift:10:17:10:22 | (...) | 0 | getImmediateElement(0) | patterns.swift:10:18:10:18 | 1 | +| patterns.swift:10:17:10:22 | (...) | 1 | getImmediateElement(1) | patterns.swift:10:21:10:21 | 2 | +| patterns.swift:11:5:13:5 | switch point { ... } | 0 | getImmediateExpr() | patterns.swift:11:12:11:12 | point | +| patterns.swift:11:5:13:5 | switch point { ... } | 1 | getImmediateCase(0) | patterns.swift:12:5:12:24 | case ... | +| patterns.swift:12:5:12:24 | case ... | 0 | getImmediateBody() | patterns.swift:12:24:12:24 | { ... } | +| patterns.swift:12:5:12:24 | case ... | 1 | getImmediateLabel(0) | patterns.swift:12:10:12:21 | let ... | +| patterns.swift:12:10:12:21 | let ... | 0 | getImmediatePattern() | patterns.swift:12:10:12:21 | let ... | +| patterns.swift:12:10:12:21 | let ... | 0 | getImmediateSubPattern() | patterns.swift:12:14:12:21 | (...) | +| patterns.swift:12:14:12:21 | (...) | 0 | getImmediateElement(0) | patterns.swift:12:15:12:15 | xx | +| patterns.swift:12:14:12:21 | (...) | 1 | getImmediateElement(1) | patterns.swift:12:19:12:19 | yy | +| patterns.swift:12:24:12:24 | { ... } | 0 | getImmediateElement(0) | patterns.swift:12:24:12:24 | binding | +| patterns.swift:15:5:18:5 | switch 3 { ... } | 0 | getImmediateExpr() | patterns.swift:15:12:15:12 | 3 | +| patterns.swift:15:5:18:5 | switch 3 { ... } | 1 | getImmediateCase(0) | patterns.swift:16:5:16:17 | case ... | +| patterns.swift:15:5:18:5 | switch 3 { ... } | 2 | getImmediateCase(1) | patterns.swift:17:5:17:13 | case ... | +| patterns.swift:16:5:16:17 | case ... | 0 | getImmediateBody() | patterns.swift:16:17:16:17 | { ... } | +| patterns.swift:16:5:16:17 | case ... | 1 | getImmediateLabel(0) | patterns.swift:16:10:16:14 | =~ ... | +| patterns.swift:16:10:16:14 | =~ ... | 0 | getImmediatePattern() | patterns.swift:16:10:16:14 | =~ ... | +| patterns.swift:16:10:16:14 | =~ ... | 0 | getImmediateSubExpr() | patterns.swift:16:10:16:14 | SequenceExpr | +| patterns.swift:16:10:16:14 | SequenceExpr | 0 | getImmediateElement(0) | patterns.swift:16:10:16:10 | 1 | +| patterns.swift:16:10:16:14 | SequenceExpr | 1 | getImmediateElement(1) | patterns.swift:16:12:16:12 | OverloadedDeclRefExpr | +| patterns.swift:16:10:16:14 | SequenceExpr | 2 | getImmediateElement(2) | patterns.swift:16:14:16:14 | 2 | +| patterns.swift:16:17:16:17 | { ... } | 0 | getImmediateElement(0) | patterns.swift:16:17:16:17 | expr | +| patterns.swift:17:5:17:13 | case ... | 0 | getImmediateBody() | patterns.swift:17:13:17:13 | { ... } | +| patterns.swift:17:5:17:13 | case ... | 1 | getImmediateLabel(0) | patterns.swift:17:10:17:10 | _ | +| patterns.swift:17:10:17:10 | _ | 0 | getImmediatePattern() | patterns.swift:17:10:17:10 | _ | +| patterns.swift:17:13:17:13 | { ... } | 0 | getImmediateElement(0) | patterns.swift:17:13:17:13 | | +| patterns.swift:21:9:21:34 | case ... | 0 | getImmediateElement(0) | patterns.swift:21:14:21:14 | bar | +| patterns.swift:21:9:21:34 | case ... | 1 | getImmediateElement(1) | patterns.swift:21:19:21:34 | baz | +| patterns.swift:21:19:21:34 | baz | 0 | getImmediateParam(0) | patterns.swift:21:23:21:23 | _ | +| patterns.swift:21:19:21:34 | baz | 1 | getImmediateParam(1) | patterns.swift:21:28:21:28 | _ | +| patterns.swift:24:5:24:19 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:24:18:24:19 | .bar | +| patterns.swift:24:5:24:19 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:24:9:24:12 | ... as ... | +| patterns.swift:24:9:24:12 | ... as ... | 0 | getImmediateSubPattern() | patterns.swift:24:9:24:9 | v | +| patterns.swift:24:9:24:12 | ... as ... | 1 | getImmediateTypeRepr() | patterns.swift:24:12:24:12 | Foo | +| patterns.swift:24:18:24:18 | Foo.Type | 0 | getImmediateTypeRepr() | patterns.swift:24:18:24:18 | Foo | +| patterns.swift:24:18:24:19 | .bar | 0 | getImmediateBase() | patterns.swift:24:18:24:18 | Foo.Type | +| patterns.swift:26:5:29:5 | switch v { ... } | 0 | getImmediateExpr() | patterns.swift:26:12:26:12 | v | +| patterns.swift:26:5:29:5 | switch v { ... } | 1 | getImmediateCase(0) | patterns.swift:27:5:27:16 | case ... | +| patterns.swift:26:5:29:5 | switch v { ... } | 2 | getImmediateCase(1) | patterns.swift:28:5:28:26 | case ... | +| patterns.swift:27:5:27:16 | case ... | 0 | getImmediateBody() | patterns.swift:27:16:27:16 | { ... } | +| patterns.swift:27:5:27:16 | case ... | 1 | getImmediateLabel(0) | patterns.swift:27:10:27:11 | .bar | +| patterns.swift:27:10:27:11 | .bar | 0 | getImmediatePattern() | patterns.swift:27:10:27:11 | .bar | +| patterns.swift:27:16:27:16 | { ... } | 0 | getImmediateElement(0) | patterns.swift:27:16:27:16 | bar | +| patterns.swift:28:5:28:26 | case ... | 0 | getImmediateBody() | patterns.swift:28:26:28:26 | { ... } | +| patterns.swift:28:5:28:26 | case ... | 1 | getImmediateLabel(0) | patterns.swift:28:10:28:23 | let ... | +| patterns.swift:28:10:28:23 | let ... | 0 | getImmediatePattern() | patterns.swift:28:10:28:23 | let ... | +| patterns.swift:28:10:28:23 | let ... | 0 | getImmediateSubPattern() | patterns.swift:28:14:28:23 | .baz(...) | +| patterns.swift:28:14:28:23 | .baz(...) | 0 | getImmediateSubPattern() | patterns.swift:28:18:28:23 | (...) | +| patterns.swift:28:18:28:23 | (...) | 0 | getImmediateElement(0) | patterns.swift:28:19:28:19 | i | +| patterns.swift:28:18:28:23 | (...) | 1 | getImmediateElement(1) | patterns.swift:28:22:28:22 | s | +| patterns.swift:28:26:28:26 | { ... } | 0 | getImmediateElement(0) | patterns.swift:28:26:28:26 | i | +| patterns.swift:31:5:31:19 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:31:19:31:19 | nil | +| patterns.swift:31:5:31:19 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:31:9:31:15 | ... as ... | +| patterns.swift:31:9:31:15 | ... as ... | 0 | getImmediateSubPattern() | patterns.swift:31:9:31:9 | w | +| patterns.swift:31:9:31:15 | ... as ... | 1 | getImmediateTypeRepr() | patterns.swift:31:12:31:15 | Int? | +| patterns.swift:33:5:36:5 | switch w { ... } | 0 | getImmediateExpr() | patterns.swift:33:12:33:12 | w | +| patterns.swift:33:5:36:5 | switch w { ... } | 1 | getImmediateCase(0) | patterns.swift:34:5:34:18 | case ... | +| patterns.swift:33:5:36:5 | switch w { ... } | 2 | getImmediateCase(1) | patterns.swift:35:5:35:13 | case ... | +| patterns.swift:34:5:34:18 | case ... | 0 | getImmediateBody() | patterns.swift:34:18:34:18 | { ... } | +| patterns.swift:34:5:34:18 | case ... | 1 | getImmediateLabel(0) | patterns.swift:34:10:34:15 | let ... | +| patterns.swift:34:10:34:15 | let ... | 0 | getImmediatePattern() | patterns.swift:34:10:34:15 | let ... | +| patterns.swift:34:10:34:15 | let ... | 0 | getImmediateSubPattern() | patterns.swift:34:14:34:15 | let ...? | +| patterns.swift:34:14:34:15 | let ...? | 0 | getImmediateSubPattern() | patterns.swift:34:14:34:14 | n | +| patterns.swift:34:18:34:18 | { ... } | 0 | getImmediateElement(0) | patterns.swift:34:18:34:18 | n | +| patterns.swift:35:5:35:13 | case ... | 0 | getImmediateBody() | patterns.swift:35:13:35:13 | { ... } | +| patterns.swift:35:5:35:13 | case ... | 1 | getImmediateLabel(0) | patterns.swift:35:10:35:10 | _ | +| patterns.swift:35:10:35:10 | _ | 0 | getImmediatePattern() | patterns.swift:35:10:35:10 | _ | +| patterns.swift:35:13:35:13 | { ... } | 0 | getImmediateElement(0) | patterns.swift:35:13:35:13 | none | +| patterns.swift:38:5:38:18 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:38:18:38:18 | (Any) ... | +| patterns.swift:38:5:38:18 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:38:9:38:12 | ... as ... | +| patterns.swift:38:9:38:12 | ... as ... | 0 | getImmediateSubPattern() | patterns.swift:38:9:38:9 | a | +| patterns.swift:38:9:38:12 | ... as ... | 1 | getImmediateTypeRepr() | patterns.swift:38:12:38:12 | Any | +| patterns.swift:38:18:38:18 | (Any) ... | 0 | getImmediateSubExpr() | patterns.swift:38:18:38:18 | any | +| patterns.swift:40:5:44:5 | switch a { ... } | 0 | getImmediateExpr() | patterns.swift:40:12:40:12 | a | +| patterns.swift:40:5:44:5 | switch a { ... } | 1 | getImmediateCase(0) | patterns.swift:41:5:41:18 | case ... | +| patterns.swift:40:5:44:5 | switch a { ... } | 2 | getImmediateCase(1) | patterns.swift:42:5:42:27 | case ... | +| patterns.swift:40:5:44:5 | switch a { ... } | 3 | getImmediateCase(2) | patterns.swift:43:5:43:13 | case ... | +| patterns.swift:41:5:41:18 | case ... | 0 | getImmediateBody() | patterns.swift:41:18:41:18 | { ... } | +| patterns.swift:41:5:41:18 | case ... | 1 | getImmediateLabel(0) | patterns.swift:41:10:41:13 | ... is ... | +| patterns.swift:41:10:41:13 | ... is ... | 0 | getImmediateCastTypeRepr() | patterns.swift:41:13:41:13 | Int | +| patterns.swift:41:10:41:13 | ... is ... | 0 | getImmediatePattern() | patterns.swift:41:10:41:13 | ... is ... | +| patterns.swift:41:18:41:18 | { ... } | 0 | getImmediateElement(0) | patterns.swift:41:18:41:18 | is pattern | +| patterns.swift:42:5:42:27 | case ... | 0 | getImmediateBody() | patterns.swift:42:27:42:27 | { ... } | +| patterns.swift:42:5:42:27 | case ... | 1 | getImmediateLabel(0) | patterns.swift:42:10:42:19 | let ... | +| patterns.swift:42:10:42:19 | let ... | 0 | getImmediatePattern() | patterns.swift:42:10:42:19 | let ... | +| patterns.swift:42:10:42:19 | let ... | 0 | getImmediateSubPattern() | patterns.swift:42:14:42:19 | ... is ... | +| patterns.swift:42:14:42:19 | ... is ... | 0 | getImmediateCastTypeRepr() | patterns.swift:42:19:42:19 | String | +| patterns.swift:42:14:42:19 | ... is ... | 1 | getImmediateSubPattern() | patterns.swift:42:14:42:14 | x | +| patterns.swift:42:27:42:27 | { ... } | 0 | getImmediateElement(0) | patterns.swift:42:27:42:27 | as pattern | +| patterns.swift:43:5:43:13 | case ... | 0 | getImmediateBody() | patterns.swift:43:13:43:13 | { ... } | +| patterns.swift:43:5:43:13 | case ... | 1 | getImmediateLabel(0) | patterns.swift:43:10:43:10 | _ | +| patterns.swift:43:10:43:10 | _ | 0 | getImmediatePattern() | patterns.swift:43:10:43:10 | _ | +| patterns.swift:43:13:43:13 | { ... } | 0 | getImmediateElement(0) | patterns.swift:43:13:43:13 | other | +| patterns.swift:46:5:46:13 | var ... = ... | 0 | getImmediateInit(0) | patterns.swift:46:13:46:13 | true | +| patterns.swift:46:5:46:13 | var ... = ... | 1 | getImmediatePattern(0) | patterns.swift:46:9:46:9 | b | +| patterns.swift:48:5:51:5 | switch b { ... } | 0 | getImmediateExpr() | patterns.swift:48:12:48:12 | b | +| patterns.swift:48:5:51:5 | switch b { ... } | 1 | getImmediateCase(0) | patterns.swift:49:5:49:16 | case ... | +| patterns.swift:48:5:51:5 | switch b { ... } | 2 | getImmediateCase(1) | patterns.swift:50:5:50:17 | case ... | +| patterns.swift:49:5:49:16 | case ... | 0 | getImmediateBody() | patterns.swift:49:16:49:16 | { ... } | +| patterns.swift:49:5:49:16 | case ... | 1 | getImmediateLabel(0) | patterns.swift:49:10:49:10 | true | +| patterns.swift:49:10:49:10 | true | 0 | getImmediatePattern() | patterns.swift:49:10:49:10 | true | +| patterns.swift:49:16:49:16 | { ... } | 0 | getImmediateElement(0) | patterns.swift:49:16:49:16 | true | +| patterns.swift:50:5:50:17 | case ... | 0 | getImmediateBody() | patterns.swift:50:17:50:17 | { ... } | +| patterns.swift:50:5:50:17 | case ... | 1 | getImmediateLabel(0) | patterns.swift:50:10:50:10 | false | +| patterns.swift:50:10:50:10 | false | 0 | getImmediatePattern() | patterns.swift:50:10:50:10 | false | +| patterns.swift:50:17:50:17 | { ... } | 0 | getImmediateElement(0) | patterns.swift:50:17:50:17 | false | +| statements.swift:1:1:32:1 | loop() | 1 | getImmediateBody() | statements.swift:1:13:32:1 | { ... } | +| statements.swift:1:13:32:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:2:3:8:3 | for ... in ... { ... } | +| statements.swift:1:13:32:1 | { ... } | 1 | getImmediateElement(1) | statements.swift:9:3:9:11 | var ... = ... | +| statements.swift:1:13:32:1 | { ... } | 2 | getImmediateElement(2) | statements.swift:9:7:9:7 | i | +| statements.swift:1:13:32:1 | { ... } | 3 | getImmediateElement(3) | statements.swift:10:3:12:3 | while ... { ... } | +| statements.swift:1:13:32:1 | { ... } | 4 | getImmediateElement(4) | statements.swift:14:3:14:7 | ... = ... | +| statements.swift:1:13:32:1 | { ... } | 5 | getImmediateElement(5) | statements.swift:15:3:17:18 | repeat { ... } while ... | +| statements.swift:1:13:32:1 | { ... } | 6 | getImmediateElement(6) | statements.swift:19:3:23:3 | do { ... } catch { ... } | +| statements.swift:1:13:32:1 | { ... } | 7 | getImmediateElement(7) | statements.swift:25:3:31:3 | do { ... } catch { ... } | +| statements.swift:2:3:8:3 | for ... in ... { ... } | 0 | getImmediatePattern() | statements.swift:2:15:2:15 | i | +| statements.swift:2:3:8:3 | for ... in ... { ... } | 1 | getImmediateSequence() | statements.swift:2:20:2:24 | ... ....(_:_:) ... | +| statements.swift:2:3:8:3 | for ... in ... { ... } | 3 | getImmediateBody() | statements.swift:2:26:8:3 | { ... } | +| statements.swift:2:20:2:24 | ... ....(_:_:) ... | 0 | getImmediateFunction() | statements.swift:2:21:2:21 | ....(_:_:) | +| statements.swift:2:21:2:21 | ....(_:_:) | 0 | getImmediateBase() | statements.swift:2:21:2:21 | Int.Type | +| statements.swift:2:21:2:21 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:2:21:2:21 | Int | +| statements.swift:2:26:8:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:3:5:7:5 | if ... then { ... } else { ... } | +| statements.swift:3:5:7:5 | if ... then { ... } else { ... } | 0 | getImmediateCondition() | statements.swift:3:8:3:13 | StmtCondition | +| statements.swift:3:5:7:5 | if ... then { ... } else { ... } | 1 | getImmediateThen() | statements.swift:3:15:5:5 | { ... } | +| statements.swift:3:5:7:5 | if ... then { ... } else { ... } | 2 | getImmediateElse() | statements.swift:5:12:7:5 | { ... } | +| statements.swift:3:8:3:13 | ... .==(_:_:) ... | 0 | getImmediateFunction() | statements.swift:3:10:3:10 | .==(_:_:) | +| statements.swift:3:10:3:10 | .==(_:_:) | 0 | getImmediateBase() | statements.swift:3:10:3:10 | Int.Type | +| statements.swift:3:10:3:10 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:3:10:3:10 | Int | +| statements.swift:3:15:5:5 | { ... } | 0 | getImmediateElement(0) | statements.swift:4:9:4:9 | break | +| statements.swift:5:12:7:5 | { ... } | 0 | getImmediateElement(0) | statements.swift:6:9:6:9 | continue | +| statements.swift:9:3:9:11 | var ... = ... | 0 | getImmediateInit(0) | statements.swift:9:11:9:11 | 0 | +| statements.swift:9:3:9:11 | var ... = ... | 1 | getImmediatePattern(0) | statements.swift:9:7:9:7 | i | +| statements.swift:10:3:12:3 | while ... { ... } | 0 | getImmediateCondition() | statements.swift:10:17:10:24 | StmtCondition | +| statements.swift:10:3:12:3 | while ... { ... } | 1 | getImmediateBody() | statements.swift:10:26:12:3 | { ... } | +| statements.swift:10:17:10:24 | (...) | 0 | getImmediateSubExpr() | statements.swift:10:18:10:22 | ... .<(_:_:) ... | +| statements.swift:10:18:10:18 | (Int) ... | 0 | getImmediateSubExpr() | statements.swift:10:18:10:18 | i | +| statements.swift:10:18:10:22 | ... .<(_:_:) ... | 0 | getImmediateFunction() | statements.swift:10:20:10:20 | .<(_:_:) | +| statements.swift:10:20:10:20 | .<(_:_:) | 0 | getImmediateBase() | statements.swift:10:20:10:20 | Int.Type | +| statements.swift:10:20:10:20 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:10:20:10:20 | Int | +| statements.swift:10:26:12:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:11:5:11:13 | ... = ... | +| statements.swift:11:5:11:13 | ... = ... | 0 | getImmediateDest() | statements.swift:11:5:11:5 | i | +| statements.swift:11:5:11:13 | ... = ... | 1 | getImmediateSource() | statements.swift:11:9:11:13 | ... .+(_:_:) ... | +| statements.swift:11:9:11:9 | (Int) ... | 0 | getImmediateSubExpr() | statements.swift:11:9:11:9 | i | +| statements.swift:11:9:11:13 | ... .+(_:_:) ... | 0 | getImmediateFunction() | statements.swift:11:11:11:11 | .+(_:_:) | +| statements.swift:11:11:11:11 | .+(_:_:) | 0 | getImmediateBase() | statements.swift:11:11:11:11 | Int.Type | +| statements.swift:11:11:11:11 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:11:11:11:11 | Int | +| statements.swift:14:3:14:7 | ... = ... | 0 | getImmediateDest() | statements.swift:14:3:14:3 | i | +| statements.swift:14:3:14:7 | ... = ... | 1 | getImmediateSource() | statements.swift:14:7:14:7 | 0 | +| statements.swift:15:3:17:18 | repeat { ... } while ... | 0 | getImmediateCondition() | statements.swift:17:11:17:18 | (...) | +| statements.swift:15:3:17:18 | repeat { ... } while ... | 1 | getImmediateBody() | statements.swift:15:18:17:3 | { ... } | +| statements.swift:15:18:17:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:16:5:16:13 | ... = ... | +| statements.swift:16:5:16:13 | ... = ... | 0 | getImmediateDest() | statements.swift:16:5:16:5 | i | +| statements.swift:16:5:16:13 | ... = ... | 1 | getImmediateSource() | statements.swift:16:9:16:13 | ... .+(_:_:) ... | +| statements.swift:16:9:16:9 | (Int) ... | 0 | getImmediateSubExpr() | statements.swift:16:9:16:9 | i | +| statements.swift:16:9:16:13 | ... .+(_:_:) ... | 0 | getImmediateFunction() | statements.swift:16:11:16:11 | .+(_:_:) | +| statements.swift:16:11:16:11 | .+(_:_:) | 0 | getImmediateBase() | statements.swift:16:11:16:11 | Int.Type | +| statements.swift:16:11:16:11 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:16:11:16:11 | Int | +| statements.swift:17:11:17:18 | (...) | 0 | getImmediateSubExpr() | statements.swift:17:12:17:16 | ... .<(_:_:) ... | +| statements.swift:17:12:17:12 | (Int) ... | 0 | getImmediateSubExpr() | statements.swift:17:12:17:12 | i | +| statements.swift:17:12:17:16 | ... .<(_:_:) ... | 0 | getImmediateFunction() | statements.swift:17:14:17:14 | .<(_:_:) | +| statements.swift:17:14:17:14 | .<(_:_:) | 0 | getImmediateBase() | statements.swift:17:14:17:14 | Int.Type | +| statements.swift:17:14:17:14 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:17:14:17:14 | Int | +| statements.swift:19:3:23:3 | do { ... } catch { ... } | 0 | getImmediateBody() | statements.swift:19:6:21:3 | { ... } | +| statements.swift:19:3:23:3 | do { ... } catch { ... } | 1 | getImmediateCatch(0) | statements.swift:21:5:23:3 | case ... | +| statements.swift:19:6:21:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:20:5:20:19 | try ... | +| statements.swift:20:5:20:19 | try ... | 0 | getImmediateSubExpr() | statements.swift:20:9:20:19 | call to failure(_:) | +| statements.swift:20:9:20:19 | call to failure(_:) | 0 | getImmediateFunction() | statements.swift:20:9:20:9 | failure(_:) | +| statements.swift:21:5:23:3 | case ... | 0 | getImmediateBody() | statements.swift:21:11:23:3 | { ... } | +| statements.swift:21:5:23:3 | case ... | 1 | getImmediateLabel(0) | statements.swift:21:11:21:11 | let ... | +| statements.swift:21:11:21:11 | let ... | 0 | getImmediatePattern() | statements.swift:21:11:21:11 | let ... | +| statements.swift:21:11:21:11 | let ... | 0 | getImmediateSubPattern() | statements.swift:21:11:21:11 | error | +| statements.swift:21:11:23:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:22:5:22:18 | call to print(_:separator:terminator:) | +| statements.swift:22:5:22:18 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:22:5:22:5 | print(_:separator:terminator:) | +| statements.swift:22:11:22:11 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:22:11:22:11 | error | +| statements.swift:22:11:22:11 | [...] | 0 | getImmediateElement(0) | statements.swift:22:11:22:11 | (Any) ... | +| statements.swift:22:11:22:11 | [...] | 0 | getImmediateSubExpr() | statements.swift:22:11:22:11 | [...] | +| statements.swift:25:3:31:3 | do { ... } catch { ... } | 0 | getImmediateBody() | statements.swift:25:6:27:3 | { ... } | +| statements.swift:25:3:31:3 | do { ... } catch { ... } | 1 | getImmediateCatch(0) | statements.swift:27:5:29:3 | case ... | +| statements.swift:25:3:31:3 | do { ... } catch { ... } | 2 | getImmediateCatch(1) | statements.swift:29:5:31:3 | case ... | +| statements.swift:25:6:27:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:26:5:26:19 | try ... | +| statements.swift:26:5:26:19 | try ... | 0 | getImmediateSubExpr() | statements.swift:26:9:26:19 | call to failure(_:) | +| statements.swift:26:9:26:19 | call to failure(_:) | 0 | getImmediateFunction() | statements.swift:26:9:26:9 | failure(_:) | +| statements.swift:27:5:29:3 | case ... | 0 | getImmediateBody() | statements.swift:27:26:29:3 | { ... } | +| statements.swift:27:5:29:3 | case ... | 1 | getImmediateLabel(0) | statements.swift:27:11:27:11 | ... is ... | +| statements.swift:27:11:27:11 | ... is ... | 0 | getImmediatePattern() | statements.swift:27:11:27:11 | ... is ... | +| statements.swift:27:11:27:11 | ... is ... | 1 | getImmediateSubPattern() | statements.swift:27:11:27:19 | .failed | +| statements.swift:27:26:29:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:28:5:28:27 | call to print(_:separator:terminator:) | +| statements.swift:28:5:28:27 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:28:5:28:5 | print(_:separator:terminator:) | +| statements.swift:28:11:28:11 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:28:11:28:11 | AnError.failed | +| statements.swift:28:11:28:11 | [...] | 0 | getImmediateElement(0) | statements.swift:28:11:28:11 | (Any) ... | +| statements.swift:28:11:28:11 | [...] | 0 | getImmediateSubExpr() | statements.swift:28:11:28:11 | [...] | +| statements.swift:29:5:31:3 | case ... | 0 | getImmediateBody() | statements.swift:29:11:31:3 | { ... } | +| statements.swift:29:5:31:3 | case ... | 1 | getImmediateLabel(0) | statements.swift:29:11:29:11 | let ... | +| statements.swift:29:11:29:11 | let ... | 0 | getImmediatePattern() | statements.swift:29:11:29:11 | let ... | +| statements.swift:29:11:29:11 | let ... | 0 | getImmediateSubPattern() | statements.swift:29:11:29:11 | error | +| statements.swift:29:11:31:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:30:5:30:18 | call to print(_:separator:terminator:) | +| statements.swift:30:5:30:18 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:30:5:30:5 | print(_:separator:terminator:) | +| statements.swift:30:11:30:11 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:30:11:30:11 | error | +| statements.swift:30:11:30:11 | [...] | 0 | getImmediateElement(0) | statements.swift:30:11:30:11 | (Any) ... | +| statements.swift:30:11:30:11 | [...] | 0 | getImmediateSubExpr() | statements.swift:30:11:30:11 | [...] | +| statements.swift:35:3:35:8 | case ... | 0 | getImmediateElement(0) | statements.swift:35:8:35:8 | failed | +| statements.swift:38:1:42:1 | failure(_:) | 1 | getImmediateParam(0) | statements.swift:38:14:38:19 | x | +| statements.swift:38:1:42:1 | failure(_:) | 2 | getImmediateBody() | statements.swift:38:31:42:1 | { ... } | +| statements.swift:38:31:42:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:39:3:41:3 | guard ... else { ... } | +| statements.swift:39:3:41:3 | guard ... else { ... } | 0 | getImmediateCondition() | statements.swift:39:9:39:14 | StmtCondition | +| statements.swift:39:3:41:3 | guard ... else { ... } | 1 | getImmediateBody() | statements.swift:39:21:41:3 | { ... } | +| statements.swift:39:9:39:14 | ... .!=(_:_:) ... | 0 | getImmediateFunction() | statements.swift:39:11:39:11 | .!=(_:_:) | +| statements.swift:39:11:39:11 | .!=(_:_:) | 0 | getImmediateBase() | statements.swift:39:11:39:11 | Int.Type | +| statements.swift:39:11:39:11 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:39:11:39:11 | Int | +| statements.swift:39:21:41:3 | { ... } | 0 | getImmediateElement(0) | statements.swift:40:5:40:19 | throw ... | +| statements.swift:40:5:40:19 | throw ... | 0 | getImmediateSubExpr() | statements.swift:40:11:40:19 | (Error) ... | +| statements.swift:40:11:40:11 | AnError.Type | 0 | getImmediateTypeRepr() | statements.swift:40:11:40:11 | AnError | +| statements.swift:40:11:40:19 | (Error) ... | 0 | getImmediateSubExpr() | statements.swift:40:11:40:19 | .failed | +| statements.swift:40:11:40:19 | .failed | 0 | getImmediateBase() | statements.swift:40:11:40:11 | AnError.Type | +| statements.swift:44:1:46:1 | defer { ... } | 0 | getImmediateBody() | statements.swift:44:7:46:1 | { ... } | +| statements.swift:44:1:46:1 | { ... } | 0 | getImmediateBody() | statements.swift:44:1:46:1 | { ... } | +| statements.swift:44:1:46:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:44:1:46:1 | defer { ... } | +| statements.swift:44:7:46:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:45:3:45:15 | call to print(_:separator:terminator:) | +| statements.swift:45:3:45:15 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:45:3:45:3 | print(_:separator:terminator:) | +| statements.swift:45:9:45:9 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:45:9:45:9 | done | +| statements.swift:45:9:45:9 | [...] | 0 | getImmediateElement(0) | statements.swift:45:9:45:9 | (Any) ... | +| statements.swift:45:9:45:9 | [...] | 0 | getImmediateSubExpr() | statements.swift:45:9:45:9 | [...] | +| statements.swift:48:1:50:1 | do { ... } | 0 | getImmediateBody() | statements.swift:48:4:50:1 | { ... } | +| statements.swift:48:1:50:1 | { ... } | 0 | getImmediateBody() | statements.swift:48:1:50:1 | { ... } | +| statements.swift:48:1:50:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:48:1:50:1 | do { ... } | +| statements.swift:48:4:50:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:49:3:49:16 | call to print(_:separator:terminator:) | +| statements.swift:49:3:49:16 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:49:3:49:3 | print(_:separator:terminator:) | +| statements.swift:49:9:49:9 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:49:9:49:9 | doing | +| statements.swift:49:9:49:9 | [...] | 0 | getImmediateElement(0) | statements.swift:49:9:49:9 | (Any) ... | +| statements.swift:49:9:49:9 | [...] | 0 | getImmediateSubExpr() | statements.swift:49:9:49:9 | [...] | +| statements.swift:52:1:52:13 | var ... = ... | 0 | getImmediateInit(0) | statements.swift:52:13:52:13 | 42 | +| statements.swift:52:1:52:13 | var ... = ... | 1 | getImmediatePattern(0) | statements.swift:52:5:52:5 | index | +| statements.swift:52:1:52:13 | { ... } | 0 | getImmediateBody() | statements.swift:52:1:52:13 | { ... } | +| statements.swift:52:1:52:13 | { ... } | 0 | getImmediateElement(0) | statements.swift:52:1:52:13 | var ... = ... | +| statements.swift:53:1:62:1 | switch index { ... } | 0 | getImmediateExpr() | statements.swift:53:8:53:8 | index | +| statements.swift:53:1:62:1 | switch index { ... } | 1 | getImmediateCase(0) | statements.swift:54:4:56:7 | case ... | +| statements.swift:53:1:62:1 | switch index { ... } | 2 | getImmediateCase(1) | statements.swift:57:4:59:7 | case ... | +| statements.swift:53:1:62:1 | switch index { ... } | 3 | getImmediateCase(2) | statements.swift:60:4:61:22 | case ... | +| statements.swift:53:1:62:1 | { ... } | 0 | getImmediateBody() | statements.swift:53:1:62:1 | { ... } | +| statements.swift:53:1:62:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:53:1:62:1 | switch index { ... } | +| statements.swift:54:4:56:7 | case ... | 0 | getImmediateBody() | statements.swift:55:7:56:7 | { ... } | +| statements.swift:54:4:56:7 | case ... | 1 | getImmediateLabel(0) | statements.swift:54:9:54:9 | =~ ... | +| statements.swift:54:9:54:9 | =~ ... | 0 | getImmediatePattern() | statements.swift:54:9:54:9 | =~ ... | +| statements.swift:54:9:54:9 | =~ ... | 0 | getImmediateSubExpr() | statements.swift:54:9:54:9 | 1 | +| statements.swift:55:7:55:16 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:55:7:55:7 | print(_:separator:terminator:) | +| statements.swift:55:7:56:7 | { ... } | 0 | getImmediateElement(0) | statements.swift:55:7:55:16 | call to print(_:separator:terminator:) | +| statements.swift:55:7:56:7 | { ... } | 1 | getImmediateElement(1) | statements.swift:56:7:56:7 | fallthrough | +| statements.swift:55:13:55:13 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:55:13:55:13 | 1 | +| statements.swift:55:13:55:13 | [...] | 0 | getImmediateElement(0) | statements.swift:55:13:55:13 | (Any) ... | +| statements.swift:55:13:55:13 | [...] | 0 | getImmediateSubExpr() | statements.swift:55:13:55:13 | [...] | +| statements.swift:57:4:59:7 | case ... | 0 | getImmediateBody() | statements.swift:58:7:59:7 | { ... } | +| statements.swift:57:4:59:7 | case ... | 1 | getImmediateLabel(0) | statements.swift:57:9:57:9 | =~ ... | +| statements.swift:57:4:59:7 | case ... | 2 | getImmediateLabel(1) | statements.swift:57:12:57:12 | =~ ... | +| statements.swift:57:9:57:9 | =~ ... | 0 | getImmediatePattern() | statements.swift:57:9:57:9 | =~ ... | +| statements.swift:57:9:57:9 | =~ ... | 0 | getImmediateSubExpr() | statements.swift:57:9:57:9 | 5 | +| statements.swift:57:12:57:12 | =~ ... | 0 | getImmediatePattern() | statements.swift:57:12:57:12 | =~ ... | +| statements.swift:57:12:57:12 | =~ ... | 0 | getImmediateSubExpr() | statements.swift:57:12:57:12 | 10 | +| statements.swift:58:7:58:20 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:58:7:58:7 | print(_:separator:terminator:) | +| statements.swift:58:7:59:7 | { ... } | 0 | getImmediateElement(0) | statements.swift:58:7:58:20 | call to print(_:separator:terminator:) | +| statements.swift:58:7:59:7 | { ... } | 1 | getImmediateElement(1) | statements.swift:59:7:59:7 | break | +| statements.swift:58:13:58:13 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:58:13:58:13 | 5, 10 | +| statements.swift:58:13:58:13 | [...] | 0 | getImmediateElement(0) | statements.swift:58:13:58:13 | (Any) ... | +| statements.swift:58:13:58:13 | [...] | 0 | getImmediateSubExpr() | statements.swift:58:13:58:13 | [...] | +| statements.swift:60:4:60:4 | _ | 0 | getImmediatePattern() | statements.swift:60:4:60:4 | _ | +| statements.swift:60:4:61:22 | case ... | 0 | getImmediateBody() | statements.swift:61:7:61:22 | { ... } | +| statements.swift:60:4:61:22 | case ... | 1 | getImmediateLabel(0) | statements.swift:60:4:60:4 | _ | +| statements.swift:61:7:61:22 | call to print(_:separator:terminator:) | 0 | getImmediateFunction() | statements.swift:61:7:61:7 | print(_:separator:terminator:) | +| statements.swift:61:7:61:22 | { ... } | 0 | getImmediateElement(0) | statements.swift:61:7:61:22 | call to print(_:separator:terminator:) | +| statements.swift:61:13:61:13 | (Any) ... | 0 | getImmediateSubExpr() | statements.swift:61:13:61:13 | default | +| statements.swift:61:13:61:13 | [...] | 0 | getImmediateElement(0) | statements.swift:61:13:61:13 | (Any) ... | +| statements.swift:61:13:61:13 | [...] | 0 | getImmediateSubExpr() | statements.swift:61:13:61:13 | [...] | +| statements.swift:64:1:64:15 | var ... = ... | 0 | getImmediateInit(0) | statements.swift:64:15:64:15 | (Int?) ... | +| statements.swift:64:1:64:15 | var ... = ... | 1 | getImmediatePattern(0) | statements.swift:64:5:64:11 | ... as ... | +| statements.swift:64:1:64:15 | { ... } | 0 | getImmediateBody() | statements.swift:64:1:64:15 | { ... } | +| statements.swift:64:1:64:15 | { ... } | 0 | getImmediateElement(0) | statements.swift:64:1:64:15 | var ... = ... | +| statements.swift:64:5:64:11 | ... as ... | 0 | getImmediateSubPattern() | statements.swift:64:5:64:5 | x | +| statements.swift:64:5:64:11 | ... as ... | 1 | getImmediateTypeRepr() | statements.swift:64:8:64:11 | Int? | +| statements.swift:64:15:64:15 | (Int?) ... | 0 | getImmediateSubExpr() | statements.swift:64:15:64:15 | 4 | +| statements.swift:65:1:66:1 | if ... then { ... } | 0 | getImmediateCondition() | statements.swift:65:4:65:19 | StmtCondition | +| statements.swift:65:1:66:1 | if ... then { ... } | 1 | getImmediateThen() | statements.swift:65:21:66:1 | { ... } | +| statements.swift:65:1:66:1 | { ... } | 0 | getImmediateBody() | statements.swift:65:1:66:1 | { ... } | +| statements.swift:65:1:66:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:65:1:66:1 | if ... then { ... } | +| statements.swift:65:9:65:15 | let ... | 0 | getImmediateSubPattern() | statements.swift:65:13:65:15 | let ...? | +| statements.swift:65:13:65:15 | let ...? | 0 | getImmediateSubPattern() | statements.swift:65:13:65:13 | xx | +| statements.swift:67:1:68:1 | if ... then { ... } | 0 | getImmediateCondition() | statements.swift:67:4:67:20 | StmtCondition | +| statements.swift:67:1:68:1 | if ... then { ... } | 1 | getImmediateThen() | statements.swift:67:22:68:1 | { ... } | +| statements.swift:67:1:68:1 | { ... } | 0 | getImmediateBody() | statements.swift:67:1:68:1 | { ... } | +| statements.swift:67:1:68:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:67:1:68:1 | if ... then { ... } | +| statements.swift:67:9:67:16 | .some(...) | 0 | getImmediateSubPattern() | statements.swift:67:14:67:16 | (...) | +| statements.swift:67:14:67:16 | (...) | 0 | getImmediateSubPattern() | statements.swift:67:15:67:15 | _ | +| statements.swift:70:1:70:23 | var ... = ... | 0 | getImmediateInit(0) | statements.swift:70:15:70:23 | [...] | +| statements.swift:70:1:70:23 | var ... = ... | 1 | getImmediatePattern(0) | statements.swift:70:5:70:5 | numbers | +| statements.swift:70:1:70:23 | { ... } | 0 | getImmediateBody() | statements.swift:70:1:70:23 | { ... } | +| statements.swift:70:1:70:23 | { ... } | 0 | getImmediateElement(0) | statements.swift:70:1:70:23 | var ... = ... | +| statements.swift:70:15:70:23 | [...] | 0 | getImmediateElement(0) | statements.swift:70:16:70:16 | 1 | +| statements.swift:70:15:70:23 | [...] | 1 | getImmediateElement(1) | statements.swift:70:19:70:19 | 2 | +| statements.swift:70:15:70:23 | [...] | 2 | getImmediateElement(2) | statements.swift:70:22:70:22 | 3 | +| statements.swift:71:1:72:1 | for ... in ... where ... { ... } | 0 | getImmediatePattern() | statements.swift:71:5:71:5 | number | +| statements.swift:71:1:72:1 | for ... in ... where ... { ... } | 1 | getImmediateSequence() | statements.swift:71:15:71:15 | numbers | +| statements.swift:71:1:72:1 | for ... in ... where ... { ... } | 2 | getImmediateWhere() | statements.swift:71:29:71:43 | ... .==(_:_:) ... | +| statements.swift:71:1:72:1 | for ... in ... where ... { ... } | 3 | getImmediateBody() | statements.swift:71:45:72:1 | { ... } | +| statements.swift:71:1:72:1 | { ... } | 0 | getImmediateBody() | statements.swift:71:1:72:1 | { ... } | +| statements.swift:71:1:72:1 | { ... } | 0 | getImmediateElement(0) | statements.swift:71:1:72:1 | for ... in ... where ... { ... } | +| statements.swift:71:29:71:38 | ... .%(_:_:) ... | 0 | getImmediateFunction() | statements.swift:71:36:71:36 | .%(_:_:) | +| statements.swift:71:29:71:43 | ... .==(_:_:) ... | 0 | getImmediateFunction() | statements.swift:71:40:71:40 | .==(_:_:) | +| statements.swift:71:36:71:36 | .%(_:_:) | 0 | getImmediateBase() | statements.swift:71:36:71:36 | Int.Type | +| statements.swift:71:36:71:36 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:71:36:71:36 | Int | +| statements.swift:71:40:71:40 | .==(_:_:) | 0 | getImmediateBase() | statements.swift:71:40:71:40 | Int.Type | +| statements.swift:71:40:71:40 | Int.Type | 0 | getImmediateTypeRepr() | statements.swift:71:40:71:40 | Int | +| statements.swift:74:8:74:8 | init | 0 | getImmediateSelfParam() | statements.swift:74:8:74:8 | self | +| statements.swift:74:8:74:8 | init | 1 | getImmediateParam(0) | statements.swift:74:8:74:8 | x | +| statements.swift:75:3:75:11 | var ... = ... | 0 | getImmediatePattern(0) | statements.swift:75:7:75:11 | ... as ... | +| statements.swift:75:7:75:7 | (unnamed function decl) | 0 | getImmediateSelfParam() | statements.swift:75:7:75:7 | self | +| statements.swift:75:7:75:7 | (unnamed function decl) | 1 | getImmediateBody() | statements.swift:75:7:75:7 | { ... } | +| statements.swift:75:7:75:7 | get | 0 | getImmediateSelfParam() | statements.swift:75:7:75:7 | self | +| statements.swift:75:7:75:7 | get | 1 | getImmediateBody() | statements.swift:75:7:75:7 | { ... } | +| statements.swift:75:7:75:7 | set | 0 | getImmediateSelfParam() | statements.swift:75:7:75:7 | self | +| statements.swift:75:7:75:7 | set | 1 | getImmediateParam(0) | statements.swift:75:7:75:7 | value | +| statements.swift:75:7:75:7 | set | 2 | getImmediateBody() | statements.swift:75:7:75:7 | { ... } | +| statements.swift:75:7:75:7 | x | 0 | getImmediateAccessorDecl(0) | statements.swift:75:7:75:7 | get | +| statements.swift:75:7:75:7 | x | 1 | getImmediateAccessorDecl(1) | statements.swift:75:7:75:7 | set | +| statements.swift:75:7:75:7 | x | 2 | getImmediateAccessorDecl(2) | statements.swift:75:7:75:7 | (unnamed function decl) | +| statements.swift:75:7:75:7 | yield ... | 0 | getImmediateResult(0) | file://:0:0:0:0 | &... | +| statements.swift:75:7:75:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| statements.swift:75:7:75:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | return ... | +| statements.swift:75:7:75:7 | { ... } | 0 | getImmediateElement(0) | statements.swift:75:7:75:7 | yield ... | +| statements.swift:75:7:75:11 | ... as ... | 0 | getImmediateSubPattern() | statements.swift:75:7:75:7 | x | +| statements.swift:75:7:75:11 | ... as ... | 1 | getImmediateTypeRepr() | statements.swift:75:11:75:11 | Int | +| statements.swift:76:3:84:3 | var ... = ... | 0 | getImmediatePattern(0) | statements.swift:76:7:76:19 | ... as ... | +| statements.swift:76:7:76:7 | hasModify | 0 | getImmediateAccessorDecl(0) | statements.swift:77:5:79:5 | (unnamed function decl) | +| statements.swift:76:7:76:7 | hasModify | 1 | getImmediateAccessorDecl(1) | statements.swift:81:5:83:5 | get | +| statements.swift:76:7:76:7 | hasModify | 2 | getImmediateAccessorDecl(2) | statements.swift:76:7:76:7 | set | +| statements.swift:76:7:76:7 | set | 0 | getImmediateSelfParam() | statements.swift:76:7:76:7 | self | +| statements.swift:76:7:76:7 | set | 1 | getImmediateParam(0) | statements.swift:76:7:76:7 | value | +| statements.swift:76:7:76:7 | set | 2 | getImmediateBody() | statements.swift:76:7:76:7 | { ... } | +| statements.swift:76:7:76:7 | { ... } | 0 | getImmediateElement(0) | file://:0:0:0:0 | ... = ... | +| statements.swift:76:7:76:19 | ... as ... | 0 | getImmediateSubPattern() | statements.swift:76:7:76:7 | hasModify | +| statements.swift:76:7:76:19 | ... as ... | 1 | getImmediateTypeRepr() | statements.swift:76:19:76:19 | Int | +| statements.swift:77:5:79:5 | (unnamed function decl) | 0 | getImmediateSelfParam() | statements.swift:77:5:77:5 | self | +| statements.swift:77:5:79:5 | (unnamed function decl) | 1 | getImmediateBody() | statements.swift:77:13:79:5 | { ... } | +| statements.swift:77:13:79:5 | { ... } | 0 | getImmediateElement(0) | statements.swift:78:7:78:14 | yield ... | +| statements.swift:78:7:78:14 | yield ... | 0 | getImmediateResult(0) | statements.swift:78:13:78:14 | &... | +| statements.swift:78:13:78:14 | &... | 0 | getImmediateSubExpr() | statements.swift:78:14:78:14 | .x | +| statements.swift:78:14:78:14 | .x | 0 | getImmediateBase() | statements.swift:78:14:78:14 | self | +| statements.swift:81:5:83:5 | get | 0 | getImmediateSelfParam() | statements.swift:81:5:81:5 | self | +| statements.swift:81:5:83:5 | get | 1 | getImmediateBody() | statements.swift:81:9:83:5 | { ... } | +| statements.swift:81:9:83:5 | { ... } | 0 | getImmediateElement(0) | statements.swift:82:7:82:14 | return ... | +| statements.swift:82:7:82:14 | return ... | 0 | getImmediateResult() | statements.swift:82:14:82:14 | 0 | diff --git a/swift/ql/test/library-tests/parent/child.ql b/swift/ql/test/library-tests/parent/child.ql new file mode 100644 index 00000000000..51ee320b56b --- /dev/null +++ b/swift/ql/test/library-tests/parent/child.ql @@ -0,0 +1,9 @@ +import swift +import codeql.swift.generated.ParentChild +import TestUtils + +from AstNode parent, AstNode child, int index, string accessor +where + toBeTested(parent) and + child = getImmediateChildAndAccessor(parent, index, accessor) +select parent, index, accessor, child diff --git a/swift/ql/test/library-tests/parent/no_double_children.expected b/swift/ql/test/library-tests/parent/no_double_children.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/ql/test/library-tests/parent/no_double_children.ql b/swift/ql/test/library-tests/parent/no_double_children.ql new file mode 100644 index 00000000000..d3ea85a875b --- /dev/null +++ b/swift/ql/test/library-tests/parent/no_double_children.ql @@ -0,0 +1,10 @@ +import swift +private import codeql.swift.generated.ParentChild + +from AstNode parent, int index, AstNode child1, AstNode child2 +where + child1 != child2 and + child1 = getImmediateChildAndAccessor(parent, index, _) and + child2 = getImmediateChildAndAccessor(parent, index, _) +select parent, parent.getPrimaryQlClasses(), index, child1, child1.getPrimaryQlClasses(), child2, + child2.getPrimaryQlClasses() diff --git a/swift/ql/test/library-tests/parent/no_double_indexes.expected b/swift/ql/test/library-tests/parent/no_double_indexes.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/swift/ql/test/library-tests/parent/no_double_indexes.ql b/swift/ql/test/library-tests/parent/no_double_indexes.ql new file mode 100644 index 00000000000..b05a432f89c --- /dev/null +++ b/swift/ql/test/library-tests/parent/no_double_indexes.ql @@ -0,0 +1,9 @@ +import swift +private import codeql.swift.generated.ParentChild + +from AstNode parent, int index1, int index2, AstNode child +where + index1 != index2 and + child = getImmediateChildAndAccessor(parent, index1, _) and + child = getImmediateChildAndAccessor(parent, index2, _) +select parent, parent.getPrimaryQlClasses(), child, child.getPrimaryQlClasses(), index1, index2 diff --git a/swift/ql/test/library-tests/parent/no_double_parents.expected b/swift/ql/test/library-tests/parent/no_double_parents.expected index 015ff37dc4b..e69de29bb2d 100644 --- a/swift/ql/test/library-tests/parent/no_double_parents.expected +++ b/swift/ql/test/library-tests/parent/no_double_parents.expected @@ -1,2 +0,0 @@ -| ConstructorDecl | RebindSelfInConstructorExpr | ParamDecl | -| RebindSelfInConstructorExpr | ConstructorDecl | ParamDecl | diff --git a/swift/ql/test/library-tests/parent/no_double_parents.ql b/swift/ql/test/library-tests/parent/no_double_parents.ql index 5377ca7ebc2..1c680420503 100644 --- a/swift/ql/test/library-tests/parent/no_double_parents.ql +++ b/swift/ql/test/library-tests/parent/no_double_parents.ql @@ -1,9 +1,10 @@ import swift -import codeql.swift.generated.GetImmediateParent +private import codeql.swift.generated.ParentChild from AstNode parent1, AstNode parent2, AstNode child where parent1 != parent2 and - child = getAnImmediateChild(parent1) and - child = getAnImmediateChild(parent2) -select parent1.getPrimaryQlClasses(), parent2.getPrimaryQlClasses(), child.getPrimaryQlClasses() + child = getImmediateChildAndAccessor(parent1, _, _) and + child = getImmediateChildAndAccessor(parent2, _, _) +select parent1, parent1.getPrimaryQlClasses(), parent2, parent2.getPrimaryQlClasses(), child, + child.getPrimaryQlClasses() diff --git a/swift/ql/test/library-tests/parent/parent.expected b/swift/ql/test/library-tests/parent/parent.expected index e94ce274c7b..026b791db21 100644 --- a/swift/ql/test/library-tests/parent/parent.expected +++ b/swift/ql/test/library-tests/parent/parent.expected @@ -623,6 +623,7 @@ | expressions.swift:77:21:77:21 | init | ConstructorDecl | expressions.swift:77:21:77:21 | self | ParamDecl | | expressions.swift:77:21:77:21 | init | ConstructorDecl | file://:0:0:0:0 | x | ParamDecl | | expressions.swift:77:21:77:21 | init | ConstructorDecl | file://:0:0:0:0 | { ... } | BraceStmt | +| expressions.swift:78:3:80:3 | init | ConstructorDecl | expressions.swift:78:3:78:3 | self | ParamDecl | | expressions.swift:78:3:80:3 | init | ConstructorDecl | expressions.swift:78:10:80:3 | { ... } | BraceStmt | | expressions.swift:78:10:80:3 | { ... } | BraceStmt | expressions.swift:79:5:79:21 | self = ... | RebindSelfInConstructorExpr | | expressions.swift:78:10:80:3 | { ... } | BraceStmt | expressions.swift:80:3:80:3 | return | ReturnStmt | diff --git a/swift/ql/test/library-tests/parent/parent.ql b/swift/ql/test/library-tests/parent/parent.ql index 56a40e53f43..d0af45dd345 100644 --- a/swift/ql/test/library-tests/parent/parent.ql +++ b/swift/ql/test/library-tests/parent/parent.ql @@ -1,8 +1,9 @@ import swift -import codeql.swift.generated.GetImmediateParent +import codeql.swift.generated.ParentChild +import TestUtils from AstNode parent, AstNode child where - parent = getImmediateParent(child) and - parent.getLocation().getFile().getName().matches("%swift/ql/test%") + toBeTested(parent) and + parent = getImmediateParent(child) select parent, parent.getPrimaryQlClasses(), child, child.getPrimaryQlClasses()