From 06b391ef9ba35fdcee626e40a42d229884243f52 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 20 Sep 2019 11:14:16 +0100 Subject: [PATCH 001/232] docs: fix links --- docs/language/learn-ql/java/introduce-libraries-java.rst | 2 +- docs/language/learn-ql/javascript/introduce-libraries-ts.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index 4757085cfe1..32863b099e0 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -369,7 +369,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So where not exists(c.getAReference()) select c -➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see `Navigating the call graph `__. +➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. For more information about callables and calls, see the :doc:`call graph tutorial `. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index a31bf9ffad6..539d81fb016 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -134,7 +134,7 @@ The QL class `ClassOrInterface `__. -Also see the documentation for classes in the `Introduction to the QL libraries for JavaScript `__. +Also see the documentation for classes in the `Introduction to the QL libraries for JavaScript `__. To select the type references to a class or an interface, use ``getTypeName()``. @@ -443,6 +443,6 @@ A `LocalNamespaceName `. +- Learn about the QL standard libraries used to write queries for JavaScript in :doc:`Introducing the JavaScript libraries `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. \ No newline at end of file From cd5f3b84a8a9b62100ef4f697fa9740b911083ab Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 23 Sep 2019 14:51:59 +0200 Subject: [PATCH 002/232] C++: Make sure there's a Instruction for each Expr This change ensures that all `Expr`s (except parentheses) have a `TranslatedExpr` with a `getResult` that's one of its own instructions, not an instruction from one of its operands. This means that when we translate back and forth between `Expr` and `Instruction`, like in `DataFlow::exprNode`, we will not conflate `e` with `&e` or `... = e`. --- .../raw/internal/InstructionTag.qll | 1 + .../raw/internal/TranslatedElement.qll | 10 + .../raw/internal/TranslatedExpr.qll | 94 +- .../ir/escape/points_to.expected | 58 + .../test/library-tests/ir/ir/raw_ir.expected | 3207 +++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 141 +- .../ir/ssa/unaliased_ssa_ir.expected | 131 +- 7 files changed, 2072 insertions(+), 1570 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index ddac5692cdf..c18ff827992 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -44,6 +44,7 @@ newtype TInstructionTag = ConditionValueResultLoadTag() or BoolConversionConstantTag() or BoolConversionCompareTag() or + ResultCopyTag() or LoadTag() or // Implicit load due to lvalue-to-rvalue conversion CatchTag() or ThrowTag() or diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 23d3036ca15..b9a6d4c737d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -8,6 +8,7 @@ private import InstructionTag private import TranslatedCondition private import TranslatedFunction private import TranslatedStmt +private import TranslatedExpr private import IRConstruction /** @@ -235,6 +236,15 @@ newtype TTranslatedElement = expr.hasLValueToRValueConversion() and not ignoreLoad(expr) } or + TTranslatedResultCopy(Expr expr) { + not ignoreExpr(expr) and + exprNeedsCopyIfNotLoaded(expr) and + // Doesn't have a TTranslatedLoad + not ( + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) + ) + } or // An expression most naturally translated as control flow. TTranslatedNativeCondition(Expr expr) { not ignoreExpr(expr) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index fa8eeb36adb..e9e7cf59cb0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -85,11 +85,14 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { final override predicate producesExprResult() { // If there's no load, then this is the only TranslatedExpr for this // expression. - not expr.hasLValueToRValueConversion() - or - // If we're supposed to ignore the load on this expression, then this - // is the only TranslatedExpr. - ignoreLoad(expr) + not hasLoad() and + // If there's a result copy, then this expression's result is the copy. + not exprNeedsCopyIfNotLoaded(expr) + } + + private predicate hasLoad() { + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) } /** @@ -106,7 +109,7 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { or // If this TranslatedExpr doesn't produce the result, then it must represent // a glvalue that is then loaded by a TranslatedLoad. - not producesExprResult() + hasLoad() then result = true else result = false } @@ -302,6 +305,51 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { private TranslatedCoreExpr getOperand() { result.getExpr() = expr } } +/** + * IR translation of an implicit lvalue-to-rvalue conversion on the result of + * an expression. + */ +class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { + TranslatedResultCopy() { this = TTranslatedResultCopy(expr) } + + override string toString() { result = "Result of " + expr.toString() } + + override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + + override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = ResultCopyTag() and + opcode instanceof Opcode::CopyValue and + resultType = getOperand().getResultType() and + isGLValue = getOperand().isResultGLValue() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = ResultCopyTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getOperand() and result = getInstruction(ResultCopyTag()) + } + + override Instruction getResult() { result = getInstruction(ResultCopyTag()) } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = ResultCopyTag() and + operandTag instanceof UnaryOperandTag and + result = getOperand().getResult() + } + + final override predicate producesExprResult() { any() } + + private TranslatedCoreExpr getOperand() { result.getExpr() = expr } +} + class TranslatedCommaExpr extends TranslatedNonConstantExpr { override CommaExpr expr; @@ -2485,3 +2533,37 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { final override Opcode getOpcode() { result instanceof Opcode::Error } } + +/** + * Holds if the translation of `expr` will not directly generate any + * `Instruction` for use as result. For such instructions we can synthesize a + * `CopyValue` instruction to ensure that there is a 1-to-1 mapping between + * expressions and result-bearing instructions. + */ +// This should ideally be a dispatch predicate on TranslatedNonConstantExpr, +// but it doesn't look monotonic to QL. +predicate exprNeedsCopyIfNotLoaded(Expr expr) { + expr instanceof AssignExpr + or + expr instanceof AssignOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PrefixCrementOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PointerDereferenceExpr + or + expr instanceof AddressOfExpr + or + expr instanceof BuiltInOperationBuiltInAddressOf + // No case for ParenthesisExpr to avoid getting too many instructions + or + expr instanceof ReferenceDereferenceExpr + or + expr instanceof ReferenceToExpr + or + expr instanceof CommaExpr + or + expr instanceof ConditionDeclExpr + // TODO: simplify TranslatedStmtExpr too +} diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index f40460f4d91..e6fefda7bb5 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,47 +1,105 @@ +| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 | +| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 | +| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | | escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | | escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 | | escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 | +| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 | | escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | +| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 | +| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | +| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | | escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | +| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 | +| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | | escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 | +| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | +| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 20f15e4f772..788e4a72663 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -40,13 +40,14 @@ bad_asts.cpp: # 27| r0_5(glval) = VariableAddress[b] : # 27| r0_6(glval) = VariableAddress[a] : # 27| r0_7(Point &) = Load : &:r0_6, ~mu0_2 -# 27| r0_8(glval) = Convert : r0_7 -# 27| r0_9(Point) = Load : &:r0_8, ~mu0_2 -# 27| mu0_10(Point) = Store : &:r0_5, r0_9 -# 28| v0_11(void) = NoOp : -# 26| v0_12(void) = ReturnVoid : -# 26| v0_13(void) = UnmodeledUse : mu* -# 26| v0_14(void) = ExitFunction : +# 27| r0_8(glval) = CopyValue : r0_7 +# 27| r0_9(glval) = Convert : r0_8 +# 27| r0_10(Point) = Load : &:r0_9, ~mu0_2 +# 27| mu0_11(Point) = Store : &:r0_5, r0_10 +# 28| v0_12(void) = NoOp : +# 26| v0_13(void) = ReturnVoid : +# 26| v0_14(void) = UnmodeledUse : mu* +# 26| v0_15(void) = ExitFunction : # 30| void Bad::errorExpr() # 30| Block 0 @@ -63,10 +64,11 @@ bad_asts.cpp: #-----| r0_10(error) = Load : &:r0_9, ~mu0_2 # 33| r0_11(glval) = VariableAddress[x] : # 33| mu0_12(int) = Store : &:r0_11, r0_10 -# 34| v0_13(void) = NoOp : -# 30| v0_14(void) = ReturnVoid : -# 30| v0_15(void) = UnmodeledUse : mu* -# 30| v0_16(void) = ExitFunction : +# 33| r0_13(glval) = CopyValue : r0_11 +# 34| v0_14(void) = NoOp : +# 30| v0_15(void) = ReturnVoid : +# 30| v0_16(void) = UnmodeledUse : mu* +# 30| v0_17(void) = ExitFunction : clang.cpp: # 5| int* globalIntAddress() @@ -76,11 +78,12 @@ clang.cpp: # 5| mu0_2(unknown) = UnmodeledDefinition : # 6| r0_3(glval) = VariableAddress[#return] : # 6| r0_4(glval) = VariableAddress[globalInt] : -# 6| mu0_5(int *) = Store : &:r0_3, r0_4 -# 5| r0_6(glval) = VariableAddress[#return] : -# 5| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 5| v0_8(void) = UnmodeledUse : mu* -# 5| v0_9(void) = ExitFunction : +# 6| r0_5(int *) = CopyValue : r0_4 +# 6| mu0_6(int *) = Store : &:r0_3, r0_5 +# 5| r0_7(glval) = VariableAddress[#return] : +# 5| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 5| v0_9(void) = UnmodeledUse : mu* +# 5| v0_10(void) = ExitFunction : ir.cpp: # 1| void Constants() @@ -197,18 +200,20 @@ ir.cpp: # 46| r0_15(short) = Convert : r0_14 # 46| r0_16(glval) = VariableAddress[y] : # 46| mu0_17(short) = Store : &:r0_16, r0_15 -# 47| r0_18(glval) = VariableAddress[x] : -# 47| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 47| r0_20(glval) = VariableAddress[y] : -# 47| r0_21(short) = Load : &:r0_20, ~mu0_2 -# 47| r0_22(int) = Convert : r0_21 -# 47| r0_23(int) = Mul : r0_19, r0_22 -# 47| r0_24(glval) = VariableAddress[x] : -# 47| mu0_25(int) = Store : &:r0_24, r0_23 -# 48| v0_26(void) = NoOp : -# 43| v0_27(void) = ReturnVoid : -# 43| v0_28(void) = UnmodeledUse : mu* -# 43| v0_29(void) = ExitFunction : +# 46| r0_18(glval) = CopyValue : r0_16 +# 47| r0_19(glval) = VariableAddress[x] : +# 47| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 47| r0_21(glval) = VariableAddress[y] : +# 47| r0_22(short) = Load : &:r0_21, ~mu0_2 +# 47| r0_23(int) = Convert : r0_22 +# 47| r0_24(int) = Mul : r0_20, r0_23 +# 47| r0_25(glval) = VariableAddress[x] : +# 47| mu0_26(int) = Store : &:r0_25, r0_24 +# 47| r0_27(glval) = CopyValue : r0_25 +# 48| v0_28(void) = NoOp : +# 43| v0_29(void) = ReturnVoid : +# 43| v0_30(void) = UnmodeledUse : mu* +# 43| v0_31(void) = ExitFunction : # 50| void IntegerOps(int, int) # 50| Block 0 @@ -228,160 +233,185 @@ ir.cpp: # 53| r0_13(int) = Add : r0_10, r0_12 # 53| r0_14(glval) = VariableAddress[z] : # 53| mu0_15(int) = Store : &:r0_14, r0_13 -# 54| r0_16(glval) = VariableAddress[x] : -# 54| r0_17(int) = Load : &:r0_16, ~mu0_2 -# 54| r0_18(glval) = VariableAddress[y] : -# 54| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 54| r0_20(int) = Sub : r0_17, r0_19 -# 54| r0_21(glval) = VariableAddress[z] : -# 54| mu0_22(int) = Store : &:r0_21, r0_20 -# 55| r0_23(glval) = VariableAddress[x] : -# 55| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 55| r0_25(glval) = VariableAddress[y] : +# 53| r0_16(glval) = CopyValue : r0_14 +# 54| r0_17(glval) = VariableAddress[x] : +# 54| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 54| r0_19(glval) = VariableAddress[y] : +# 54| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 54| r0_21(int) = Sub : r0_18, r0_20 +# 54| r0_22(glval) = VariableAddress[z] : +# 54| mu0_23(int) = Store : &:r0_22, r0_21 +# 54| r0_24(glval) = CopyValue : r0_22 +# 55| r0_25(glval) = VariableAddress[x] : # 55| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 55| r0_27(int) = Mul : r0_24, r0_26 -# 55| r0_28(glval) = VariableAddress[z] : -# 55| mu0_29(int) = Store : &:r0_28, r0_27 -# 56| r0_30(glval) = VariableAddress[x] : -# 56| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 56| r0_32(glval) = VariableAddress[y] : -# 56| r0_33(int) = Load : &:r0_32, ~mu0_2 -# 56| r0_34(int) = Div : r0_31, r0_33 -# 56| r0_35(glval) = VariableAddress[z] : -# 56| mu0_36(int) = Store : &:r0_35, r0_34 -# 57| r0_37(glval) = VariableAddress[x] : -# 57| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 57| r0_39(glval) = VariableAddress[y] : -# 57| r0_40(int) = Load : &:r0_39, ~mu0_2 -# 57| r0_41(int) = Rem : r0_38, r0_40 -# 57| r0_42(glval) = VariableAddress[z] : -# 57| mu0_43(int) = Store : &:r0_42, r0_41 -# 59| r0_44(glval) = VariableAddress[x] : -# 59| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 59| r0_46(glval) = VariableAddress[y] : -# 59| r0_47(int) = Load : &:r0_46, ~mu0_2 -# 59| r0_48(int) = BitAnd : r0_45, r0_47 -# 59| r0_49(glval) = VariableAddress[z] : -# 59| mu0_50(int) = Store : &:r0_49, r0_48 -# 60| r0_51(glval) = VariableAddress[x] : -# 60| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 60| r0_53(glval) = VariableAddress[y] : -# 60| r0_54(int) = Load : &:r0_53, ~mu0_2 -# 60| r0_55(int) = BitOr : r0_52, r0_54 -# 60| r0_56(glval) = VariableAddress[z] : -# 60| mu0_57(int) = Store : &:r0_56, r0_55 -# 61| r0_58(glval) = VariableAddress[x] : -# 61| r0_59(int) = Load : &:r0_58, ~mu0_2 -# 61| r0_60(glval) = VariableAddress[y] : -# 61| r0_61(int) = Load : &:r0_60, ~mu0_2 -# 61| r0_62(int) = BitXor : r0_59, r0_61 -# 61| r0_63(glval) = VariableAddress[z] : -# 61| mu0_64(int) = Store : &:r0_63, r0_62 -# 63| r0_65(glval) = VariableAddress[x] : -# 63| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 63| r0_67(glval) = VariableAddress[y] : -# 63| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 63| r0_69(int) = ShiftLeft : r0_66, r0_68 -# 63| r0_70(glval) = VariableAddress[z] : -# 63| mu0_71(int) = Store : &:r0_70, r0_69 -# 64| r0_72(glval) = VariableAddress[x] : -# 64| r0_73(int) = Load : &:r0_72, ~mu0_2 -# 64| r0_74(glval) = VariableAddress[y] : -# 64| r0_75(int) = Load : &:r0_74, ~mu0_2 -# 64| r0_76(int) = ShiftRight : r0_73, r0_75 -# 64| r0_77(glval) = VariableAddress[z] : -# 64| mu0_78(int) = Store : &:r0_77, r0_76 -# 66| r0_79(glval) = VariableAddress[x] : -# 66| r0_80(int) = Load : &:r0_79, ~mu0_2 -# 66| r0_81(glval) = VariableAddress[z] : -# 66| mu0_82(int) = Store : &:r0_81, r0_80 -# 68| r0_83(glval) = VariableAddress[x] : -# 68| r0_84(int) = Load : &:r0_83, ~mu0_2 -# 68| r0_85(glval) = VariableAddress[z] : -# 68| r0_86(int) = Load : &:r0_85, ~mu0_2 -# 68| r0_87(int) = Add : r0_86, r0_84 -# 68| mu0_88(int) = Store : &:r0_85, r0_87 -# 69| r0_89(glval) = VariableAddress[x] : -# 69| r0_90(int) = Load : &:r0_89, ~mu0_2 -# 69| r0_91(glval) = VariableAddress[z] : -# 69| r0_92(int) = Load : &:r0_91, ~mu0_2 -# 69| r0_93(int) = Sub : r0_92, r0_90 -# 69| mu0_94(int) = Store : &:r0_91, r0_93 -# 70| r0_95(glval) = VariableAddress[x] : -# 70| r0_96(int) = Load : &:r0_95, ~mu0_2 -# 70| r0_97(glval) = VariableAddress[z] : -# 70| r0_98(int) = Load : &:r0_97, ~mu0_2 -# 70| r0_99(int) = Mul : r0_98, r0_96 -# 70| mu0_100(int) = Store : &:r0_97, r0_99 -# 71| r0_101(glval) = VariableAddress[x] : -# 71| r0_102(int) = Load : &:r0_101, ~mu0_2 -# 71| r0_103(glval) = VariableAddress[z] : -# 71| r0_104(int) = Load : &:r0_103, ~mu0_2 -# 71| r0_105(int) = Div : r0_104, r0_102 -# 71| mu0_106(int) = Store : &:r0_103, r0_105 -# 72| r0_107(glval) = VariableAddress[x] : -# 72| r0_108(int) = Load : &:r0_107, ~mu0_2 -# 72| r0_109(glval) = VariableAddress[z] : -# 72| r0_110(int) = Load : &:r0_109, ~mu0_2 -# 72| r0_111(int) = Rem : r0_110, r0_108 -# 72| mu0_112(int) = Store : &:r0_109, r0_111 -# 74| r0_113(glval) = VariableAddress[x] : -# 74| r0_114(int) = Load : &:r0_113, ~mu0_2 -# 74| r0_115(glval) = VariableAddress[z] : -# 74| r0_116(int) = Load : &:r0_115, ~mu0_2 -# 74| r0_117(int) = BitAnd : r0_116, r0_114 -# 74| mu0_118(int) = Store : &:r0_115, r0_117 -# 75| r0_119(glval) = VariableAddress[x] : -# 75| r0_120(int) = Load : &:r0_119, ~mu0_2 -# 75| r0_121(glval) = VariableAddress[z] : -# 75| r0_122(int) = Load : &:r0_121, ~mu0_2 -# 75| r0_123(int) = BitOr : r0_122, r0_120 -# 75| mu0_124(int) = Store : &:r0_121, r0_123 -# 76| r0_125(glval) = VariableAddress[x] : -# 76| r0_126(int) = Load : &:r0_125, ~mu0_2 -# 76| r0_127(glval) = VariableAddress[z] : -# 76| r0_128(int) = Load : &:r0_127, ~mu0_2 -# 76| r0_129(int) = BitXor : r0_128, r0_126 -# 76| mu0_130(int) = Store : &:r0_127, r0_129 -# 78| r0_131(glval) = VariableAddress[x] : -# 78| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 78| r0_133(glval) = VariableAddress[z] : -# 78| r0_134(int) = Load : &:r0_133, ~mu0_2 -# 78| r0_135(int) = ShiftLeft : r0_134, r0_132 -# 78| mu0_136(int) = Store : &:r0_133, r0_135 -# 79| r0_137(glval) = VariableAddress[x] : -# 79| r0_138(int) = Load : &:r0_137, ~mu0_2 -# 79| r0_139(glval) = VariableAddress[z] : -# 79| r0_140(int) = Load : &:r0_139, ~mu0_2 -# 79| r0_141(int) = ShiftRight : r0_140, r0_138 -# 79| mu0_142(int) = Store : &:r0_139, r0_141 -# 81| r0_143(glval) = VariableAddress[x] : -# 81| r0_144(int) = Load : &:r0_143, ~mu0_2 -# 81| r0_145(int) = CopyValue : r0_144 -# 81| r0_146(glval) = VariableAddress[z] : -# 81| mu0_147(int) = Store : &:r0_146, r0_145 -# 82| r0_148(glval) = VariableAddress[x] : -# 82| r0_149(int) = Load : &:r0_148, ~mu0_2 -# 82| r0_150(int) = Negate : r0_149 -# 82| r0_151(glval) = VariableAddress[z] : -# 82| mu0_152(int) = Store : &:r0_151, r0_150 -# 83| r0_153(glval) = VariableAddress[x] : -# 83| r0_154(int) = Load : &:r0_153, ~mu0_2 -# 83| r0_155(int) = BitComplement : r0_154 -# 83| r0_156(glval) = VariableAddress[z] : -# 83| mu0_157(int) = Store : &:r0_156, r0_155 -# 84| r0_158(glval) = VariableAddress[x] : -# 84| r0_159(int) = Load : &:r0_158, ~mu0_2 -# 84| r0_160(int) = Constant[0] : -# 84| r0_161(bool) = CompareNE : r0_159, r0_160 -# 84| r0_162(bool) = LogicalNot : r0_161 -# 84| r0_163(int) = Convert : r0_162 -# 84| r0_164(glval) = VariableAddress[z] : -# 84| mu0_165(int) = Store : &:r0_164, r0_163 -# 85| v0_166(void) = NoOp : -# 50| v0_167(void) = ReturnVoid : -# 50| v0_168(void) = UnmodeledUse : mu* -# 50| v0_169(void) = ExitFunction : +# 55| r0_27(glval) = VariableAddress[y] : +# 55| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 55| r0_29(int) = Mul : r0_26, r0_28 +# 55| r0_30(glval) = VariableAddress[z] : +# 55| mu0_31(int) = Store : &:r0_30, r0_29 +# 55| r0_32(glval) = CopyValue : r0_30 +# 56| r0_33(glval) = VariableAddress[x] : +# 56| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 56| r0_35(glval) = VariableAddress[y] : +# 56| r0_36(int) = Load : &:r0_35, ~mu0_2 +# 56| r0_37(int) = Div : r0_34, r0_36 +# 56| r0_38(glval) = VariableAddress[z] : +# 56| mu0_39(int) = Store : &:r0_38, r0_37 +# 56| r0_40(glval) = CopyValue : r0_38 +# 57| r0_41(glval) = VariableAddress[x] : +# 57| r0_42(int) = Load : &:r0_41, ~mu0_2 +# 57| r0_43(glval) = VariableAddress[y] : +# 57| r0_44(int) = Load : &:r0_43, ~mu0_2 +# 57| r0_45(int) = Rem : r0_42, r0_44 +# 57| r0_46(glval) = VariableAddress[z] : +# 57| mu0_47(int) = Store : &:r0_46, r0_45 +# 57| r0_48(glval) = CopyValue : r0_46 +# 59| r0_49(glval) = VariableAddress[x] : +# 59| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 59| r0_51(glval) = VariableAddress[y] : +# 59| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 59| r0_53(int) = BitAnd : r0_50, r0_52 +# 59| r0_54(glval) = VariableAddress[z] : +# 59| mu0_55(int) = Store : &:r0_54, r0_53 +# 59| r0_56(glval) = CopyValue : r0_54 +# 60| r0_57(glval) = VariableAddress[x] : +# 60| r0_58(int) = Load : &:r0_57, ~mu0_2 +# 60| r0_59(glval) = VariableAddress[y] : +# 60| r0_60(int) = Load : &:r0_59, ~mu0_2 +# 60| r0_61(int) = BitOr : r0_58, r0_60 +# 60| r0_62(glval) = VariableAddress[z] : +# 60| mu0_63(int) = Store : &:r0_62, r0_61 +# 60| r0_64(glval) = CopyValue : r0_62 +# 61| r0_65(glval) = VariableAddress[x] : +# 61| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 61| r0_67(glval) = VariableAddress[y] : +# 61| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 61| r0_69(int) = BitXor : r0_66, r0_68 +# 61| r0_70(glval) = VariableAddress[z] : +# 61| mu0_71(int) = Store : &:r0_70, r0_69 +# 61| r0_72(glval) = CopyValue : r0_70 +# 63| r0_73(glval) = VariableAddress[x] : +# 63| r0_74(int) = Load : &:r0_73, ~mu0_2 +# 63| r0_75(glval) = VariableAddress[y] : +# 63| r0_76(int) = Load : &:r0_75, ~mu0_2 +# 63| r0_77(int) = ShiftLeft : r0_74, r0_76 +# 63| r0_78(glval) = VariableAddress[z] : +# 63| mu0_79(int) = Store : &:r0_78, r0_77 +# 63| r0_80(glval) = CopyValue : r0_78 +# 64| r0_81(glval) = VariableAddress[x] : +# 64| r0_82(int) = Load : &:r0_81, ~mu0_2 +# 64| r0_83(glval) = VariableAddress[y] : +# 64| r0_84(int) = Load : &:r0_83, ~mu0_2 +# 64| r0_85(int) = ShiftRight : r0_82, r0_84 +# 64| r0_86(glval) = VariableAddress[z] : +# 64| mu0_87(int) = Store : &:r0_86, r0_85 +# 64| r0_88(glval) = CopyValue : r0_86 +# 66| r0_89(glval) = VariableAddress[x] : +# 66| r0_90(int) = Load : &:r0_89, ~mu0_2 +# 66| r0_91(glval) = VariableAddress[z] : +# 66| mu0_92(int) = Store : &:r0_91, r0_90 +# 66| r0_93(glval) = CopyValue : r0_91 +# 68| r0_94(glval) = VariableAddress[x] : +# 68| r0_95(int) = Load : &:r0_94, ~mu0_2 +# 68| r0_96(glval) = VariableAddress[z] : +# 68| r0_97(int) = Load : &:r0_96, ~mu0_2 +# 68| r0_98(int) = Add : r0_97, r0_95 +# 68| mu0_99(int) = Store : &:r0_96, r0_98 +# 68| r0_100(glval) = CopyValue : r0_96 +# 69| r0_101(glval) = VariableAddress[x] : +# 69| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 69| r0_103(glval) = VariableAddress[z] : +# 69| r0_104(int) = Load : &:r0_103, ~mu0_2 +# 69| r0_105(int) = Sub : r0_104, r0_102 +# 69| mu0_106(int) = Store : &:r0_103, r0_105 +# 69| r0_107(glval) = CopyValue : r0_103 +# 70| r0_108(glval) = VariableAddress[x] : +# 70| r0_109(int) = Load : &:r0_108, ~mu0_2 +# 70| r0_110(glval) = VariableAddress[z] : +# 70| r0_111(int) = Load : &:r0_110, ~mu0_2 +# 70| r0_112(int) = Mul : r0_111, r0_109 +# 70| mu0_113(int) = Store : &:r0_110, r0_112 +# 70| r0_114(glval) = CopyValue : r0_110 +# 71| r0_115(glval) = VariableAddress[x] : +# 71| r0_116(int) = Load : &:r0_115, ~mu0_2 +# 71| r0_117(glval) = VariableAddress[z] : +# 71| r0_118(int) = Load : &:r0_117, ~mu0_2 +# 71| r0_119(int) = Div : r0_118, r0_116 +# 71| mu0_120(int) = Store : &:r0_117, r0_119 +# 71| r0_121(glval) = CopyValue : r0_117 +# 72| r0_122(glval) = VariableAddress[x] : +# 72| r0_123(int) = Load : &:r0_122, ~mu0_2 +# 72| r0_124(glval) = VariableAddress[z] : +# 72| r0_125(int) = Load : &:r0_124, ~mu0_2 +# 72| r0_126(int) = Rem : r0_125, r0_123 +# 72| mu0_127(int) = Store : &:r0_124, r0_126 +# 72| r0_128(glval) = CopyValue : r0_124 +# 74| r0_129(glval) = VariableAddress[x] : +# 74| r0_130(int) = Load : &:r0_129, ~mu0_2 +# 74| r0_131(glval) = VariableAddress[z] : +# 74| r0_132(int) = Load : &:r0_131, ~mu0_2 +# 74| r0_133(int) = BitAnd : r0_132, r0_130 +# 74| mu0_134(int) = Store : &:r0_131, r0_133 +# 74| r0_135(glval) = CopyValue : r0_131 +# 75| r0_136(glval) = VariableAddress[x] : +# 75| r0_137(int) = Load : &:r0_136, ~mu0_2 +# 75| r0_138(glval) = VariableAddress[z] : +# 75| r0_139(int) = Load : &:r0_138, ~mu0_2 +# 75| r0_140(int) = BitOr : r0_139, r0_137 +# 75| mu0_141(int) = Store : &:r0_138, r0_140 +# 75| r0_142(glval) = CopyValue : r0_138 +# 76| r0_143(glval) = VariableAddress[x] : +# 76| r0_144(int) = Load : &:r0_143, ~mu0_2 +# 76| r0_145(glval) = VariableAddress[z] : +# 76| r0_146(int) = Load : &:r0_145, ~mu0_2 +# 76| r0_147(int) = BitXor : r0_146, r0_144 +# 76| mu0_148(int) = Store : &:r0_145, r0_147 +# 76| r0_149(glval) = CopyValue : r0_145 +# 78| r0_150(glval) = VariableAddress[x] : +# 78| r0_151(int) = Load : &:r0_150, ~mu0_2 +# 78| r0_152(glval) = VariableAddress[z] : +# 78| r0_153(int) = Load : &:r0_152, ~mu0_2 +# 78| r0_154(int) = ShiftLeft : r0_153, r0_151 +# 78| mu0_155(int) = Store : &:r0_152, r0_154 +# 78| r0_156(glval) = CopyValue : r0_152 +# 79| r0_157(glval) = VariableAddress[x] : +# 79| r0_158(int) = Load : &:r0_157, ~mu0_2 +# 79| r0_159(glval) = VariableAddress[z] : +# 79| r0_160(int) = Load : &:r0_159, ~mu0_2 +# 79| r0_161(int) = ShiftRight : r0_160, r0_158 +# 79| mu0_162(int) = Store : &:r0_159, r0_161 +# 79| r0_163(glval) = CopyValue : r0_159 +# 81| r0_164(glval) = VariableAddress[x] : +# 81| r0_165(int) = Load : &:r0_164, ~mu0_2 +# 81| r0_166(int) = CopyValue : r0_165 +# 81| r0_167(glval) = VariableAddress[z] : +# 81| mu0_168(int) = Store : &:r0_167, r0_166 +# 81| r0_169(glval) = CopyValue : r0_167 +# 82| r0_170(glval) = VariableAddress[x] : +# 82| r0_171(int) = Load : &:r0_170, ~mu0_2 +# 82| r0_172(int) = Negate : r0_171 +# 82| r0_173(glval) = VariableAddress[z] : +# 82| mu0_174(int) = Store : &:r0_173, r0_172 +# 82| r0_175(glval) = CopyValue : r0_173 +# 83| r0_176(glval) = VariableAddress[x] : +# 83| r0_177(int) = Load : &:r0_176, ~mu0_2 +# 83| r0_178(int) = BitComplement : r0_177 +# 83| r0_179(glval) = VariableAddress[z] : +# 83| mu0_180(int) = Store : &:r0_179, r0_178 +# 83| r0_181(glval) = CopyValue : r0_179 +# 84| r0_182(glval) = VariableAddress[x] : +# 84| r0_183(int) = Load : &:r0_182, ~mu0_2 +# 84| r0_184(int) = Constant[0] : +# 84| r0_185(bool) = CompareNE : r0_183, r0_184 +# 84| r0_186(bool) = LogicalNot : r0_185 +# 84| r0_187(int) = Convert : r0_186 +# 84| r0_188(glval) = VariableAddress[z] : +# 84| mu0_189(int) = Store : &:r0_188, r0_187 +# 84| r0_190(glval) = CopyValue : r0_188 +# 85| v0_191(void) = NoOp : +# 50| v0_192(void) = ReturnVoid : +# 50| v0_193(void) = UnmodeledUse : mu* +# 50| v0_194(void) = ExitFunction : # 87| void IntegerCompare(int, int) # 87| Block 0 @@ -401,45 +431,51 @@ ir.cpp: # 90| r0_13(bool) = CompareEQ : r0_10, r0_12 # 90| r0_14(glval) = VariableAddress[b] : # 90| mu0_15(bool) = Store : &:r0_14, r0_13 -# 91| r0_16(glval) = VariableAddress[x] : -# 91| r0_17(int) = Load : &:r0_16, ~mu0_2 -# 91| r0_18(glval) = VariableAddress[y] : -# 91| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 91| r0_20(bool) = CompareNE : r0_17, r0_19 -# 91| r0_21(glval) = VariableAddress[b] : -# 91| mu0_22(bool) = Store : &:r0_21, r0_20 -# 92| r0_23(glval) = VariableAddress[x] : -# 92| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 92| r0_25(glval) = VariableAddress[y] : +# 90| r0_16(glval) = CopyValue : r0_14 +# 91| r0_17(glval) = VariableAddress[x] : +# 91| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 91| r0_19(glval) = VariableAddress[y] : +# 91| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 91| r0_21(bool) = CompareNE : r0_18, r0_20 +# 91| r0_22(glval) = VariableAddress[b] : +# 91| mu0_23(bool) = Store : &:r0_22, r0_21 +# 91| r0_24(glval) = CopyValue : r0_22 +# 92| r0_25(glval) = VariableAddress[x] : # 92| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 92| r0_27(bool) = CompareLT : r0_24, r0_26 -# 92| r0_28(glval) = VariableAddress[b] : -# 92| mu0_29(bool) = Store : &:r0_28, r0_27 -# 93| r0_30(glval) = VariableAddress[x] : -# 93| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 93| r0_32(glval) = VariableAddress[y] : -# 93| r0_33(int) = Load : &:r0_32, ~mu0_2 -# 93| r0_34(bool) = CompareGT : r0_31, r0_33 -# 93| r0_35(glval) = VariableAddress[b] : -# 93| mu0_36(bool) = Store : &:r0_35, r0_34 -# 94| r0_37(glval) = VariableAddress[x] : -# 94| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 94| r0_39(glval) = VariableAddress[y] : -# 94| r0_40(int) = Load : &:r0_39, ~mu0_2 -# 94| r0_41(bool) = CompareLE : r0_38, r0_40 -# 94| r0_42(glval) = VariableAddress[b] : -# 94| mu0_43(bool) = Store : &:r0_42, r0_41 -# 95| r0_44(glval) = VariableAddress[x] : -# 95| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 95| r0_46(glval) = VariableAddress[y] : -# 95| r0_47(int) = Load : &:r0_46, ~mu0_2 -# 95| r0_48(bool) = CompareGE : r0_45, r0_47 -# 95| r0_49(glval) = VariableAddress[b] : -# 95| mu0_50(bool) = Store : &:r0_49, r0_48 -# 96| v0_51(void) = NoOp : -# 87| v0_52(void) = ReturnVoid : -# 87| v0_53(void) = UnmodeledUse : mu* -# 87| v0_54(void) = ExitFunction : +# 92| r0_27(glval) = VariableAddress[y] : +# 92| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 92| r0_29(bool) = CompareLT : r0_26, r0_28 +# 92| r0_30(glval) = VariableAddress[b] : +# 92| mu0_31(bool) = Store : &:r0_30, r0_29 +# 92| r0_32(glval) = CopyValue : r0_30 +# 93| r0_33(glval) = VariableAddress[x] : +# 93| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 93| r0_35(glval) = VariableAddress[y] : +# 93| r0_36(int) = Load : &:r0_35, ~mu0_2 +# 93| r0_37(bool) = CompareGT : r0_34, r0_36 +# 93| r0_38(glval) = VariableAddress[b] : +# 93| mu0_39(bool) = Store : &:r0_38, r0_37 +# 93| r0_40(glval) = CopyValue : r0_38 +# 94| r0_41(glval) = VariableAddress[x] : +# 94| r0_42(int) = Load : &:r0_41, ~mu0_2 +# 94| r0_43(glval) = VariableAddress[y] : +# 94| r0_44(int) = Load : &:r0_43, ~mu0_2 +# 94| r0_45(bool) = CompareLE : r0_42, r0_44 +# 94| r0_46(glval) = VariableAddress[b] : +# 94| mu0_47(bool) = Store : &:r0_46, r0_45 +# 94| r0_48(glval) = CopyValue : r0_46 +# 95| r0_49(glval) = VariableAddress[x] : +# 95| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 95| r0_51(glval) = VariableAddress[y] : +# 95| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 95| r0_53(bool) = CompareGE : r0_50, r0_52 +# 95| r0_54(glval) = VariableAddress[b] : +# 95| mu0_55(bool) = Store : &:r0_54, r0_53 +# 95| r0_56(glval) = CopyValue : r0_54 +# 96| v0_57(void) = NoOp : +# 87| v0_58(void) = ReturnVoid : +# 87| v0_59(void) = UnmodeledUse : mu* +# 87| v0_60(void) = ExitFunction : # 98| void IntegerCrement(int) # 98| Block 0 @@ -457,31 +493,35 @@ ir.cpp: # 101| mu0_11(int) = Store : &:r0_7, r0_10 # 101| r0_12(glval) = VariableAddress[y] : # 101| mu0_13(int) = Store : &:r0_12, r0_10 -# 102| r0_14(glval) = VariableAddress[x] : -# 102| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 102| r0_16(int) = Constant[1] : -# 102| r0_17(int) = Sub : r0_15, r0_16 -# 102| mu0_18(int) = Store : &:r0_14, r0_17 -# 102| r0_19(glval) = VariableAddress[y] : -# 102| mu0_20(int) = Store : &:r0_19, r0_17 -# 103| r0_21(glval) = VariableAddress[x] : -# 103| r0_22(int) = Load : &:r0_21, ~mu0_2 -# 103| r0_23(int) = Constant[1] : -# 103| r0_24(int) = Add : r0_22, r0_23 -# 103| mu0_25(int) = Store : &:r0_21, r0_24 -# 103| r0_26(glval) = VariableAddress[y] : -# 103| mu0_27(int) = Store : &:r0_26, r0_22 -# 104| r0_28(glval) = VariableAddress[x] : -# 104| r0_29(int) = Load : &:r0_28, ~mu0_2 -# 104| r0_30(int) = Constant[1] : -# 104| r0_31(int) = Sub : r0_29, r0_30 -# 104| mu0_32(int) = Store : &:r0_28, r0_31 -# 104| r0_33(glval) = VariableAddress[y] : -# 104| mu0_34(int) = Store : &:r0_33, r0_29 -# 105| v0_35(void) = NoOp : -# 98| v0_36(void) = ReturnVoid : -# 98| v0_37(void) = UnmodeledUse : mu* -# 98| v0_38(void) = ExitFunction : +# 101| r0_14(glval) = CopyValue : r0_12 +# 102| r0_15(glval) = VariableAddress[x] : +# 102| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 102| r0_17(int) = Constant[1] : +# 102| r0_18(int) = Sub : r0_16, r0_17 +# 102| mu0_19(int) = Store : &:r0_15, r0_18 +# 102| r0_20(glval) = VariableAddress[y] : +# 102| mu0_21(int) = Store : &:r0_20, r0_18 +# 102| r0_22(glval) = CopyValue : r0_20 +# 103| r0_23(glval) = VariableAddress[x] : +# 103| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 103| r0_25(int) = Constant[1] : +# 103| r0_26(int) = Add : r0_24, r0_25 +# 103| mu0_27(int) = Store : &:r0_23, r0_26 +# 103| r0_28(glval) = VariableAddress[y] : +# 103| mu0_29(int) = Store : &:r0_28, r0_24 +# 103| r0_30(glval) = CopyValue : r0_28 +# 104| r0_31(glval) = VariableAddress[x] : +# 104| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 104| r0_33(int) = Constant[1] : +# 104| r0_34(int) = Sub : r0_32, r0_33 +# 104| mu0_35(int) = Store : &:r0_31, r0_34 +# 104| r0_36(glval) = VariableAddress[y] : +# 104| mu0_37(int) = Store : &:r0_36, r0_32 +# 104| r0_38(glval) = CopyValue : r0_36 +# 105| v0_39(void) = NoOp : +# 98| v0_40(void) = ReturnVoid : +# 98| v0_41(void) = UnmodeledUse : mu* +# 98| v0_42(void) = ExitFunction : # 107| void IntegerCrement_LValue(int) # 107| Block 0 @@ -497,19 +537,25 @@ ir.cpp: # 110| r0_9(int) = Constant[1] : # 110| r0_10(int) = Add : r0_8, r0_9 # 110| mu0_11(int) = Store : &:r0_7, r0_10 -# 110| r0_12(glval) = VariableAddress[p] : -# 110| mu0_13(int *) = Store : &:r0_12, r0_7 -# 111| r0_14(glval) = VariableAddress[x] : -# 111| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 111| r0_16(int) = Constant[1] : -# 111| r0_17(int) = Sub : r0_15, r0_16 -# 111| mu0_18(int) = Store : &:r0_14, r0_17 -# 111| r0_19(glval) = VariableAddress[p] : -# 111| mu0_20(int *) = Store : &:r0_19, r0_14 -# 112| v0_21(void) = NoOp : -# 107| v0_22(void) = ReturnVoid : -# 107| v0_23(void) = UnmodeledUse : mu* -# 107| v0_24(void) = ExitFunction : +# 110| r0_12(glval) = CopyValue : r0_7 +# 110| r0_13(int *) = CopyValue : r0_12 +# 110| r0_14(glval) = VariableAddress[p] : +# 110| mu0_15(int *) = Store : &:r0_14, r0_13 +# 110| r0_16(glval) = CopyValue : r0_14 +# 111| r0_17(glval) = VariableAddress[x] : +# 111| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 111| r0_19(int) = Constant[1] : +# 111| r0_20(int) = Sub : r0_18, r0_19 +# 111| mu0_21(int) = Store : &:r0_17, r0_20 +# 111| r0_22(glval) = CopyValue : r0_17 +# 111| r0_23(int *) = CopyValue : r0_22 +# 111| r0_24(glval) = VariableAddress[p] : +# 111| mu0_25(int *) = Store : &:r0_24, r0_23 +# 111| r0_26(glval) = CopyValue : r0_24 +# 112| v0_27(void) = NoOp : +# 107| v0_28(void) = ReturnVoid : +# 107| v0_29(void) = UnmodeledUse : mu* +# 107| v0_30(void) = ExitFunction : # 114| void FloatOps(double, double) # 114| Block 0 @@ -529,69 +575,80 @@ ir.cpp: # 117| r0_13(double) = Add : r0_10, r0_12 # 117| r0_14(glval) = VariableAddress[z] : # 117| mu0_15(double) = Store : &:r0_14, r0_13 -# 118| r0_16(glval) = VariableAddress[x] : -# 118| r0_17(double) = Load : &:r0_16, ~mu0_2 -# 118| r0_18(glval) = VariableAddress[y] : -# 118| r0_19(double) = Load : &:r0_18, ~mu0_2 -# 118| r0_20(double) = Sub : r0_17, r0_19 -# 118| r0_21(glval) = VariableAddress[z] : -# 118| mu0_22(double) = Store : &:r0_21, r0_20 -# 119| r0_23(glval) = VariableAddress[x] : -# 119| r0_24(double) = Load : &:r0_23, ~mu0_2 -# 119| r0_25(glval) = VariableAddress[y] : +# 117| r0_16(glval) = CopyValue : r0_14 +# 118| r0_17(glval) = VariableAddress[x] : +# 118| r0_18(double) = Load : &:r0_17, ~mu0_2 +# 118| r0_19(glval) = VariableAddress[y] : +# 118| r0_20(double) = Load : &:r0_19, ~mu0_2 +# 118| r0_21(double) = Sub : r0_18, r0_20 +# 118| r0_22(glval) = VariableAddress[z] : +# 118| mu0_23(double) = Store : &:r0_22, r0_21 +# 118| r0_24(glval) = CopyValue : r0_22 +# 119| r0_25(glval) = VariableAddress[x] : # 119| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 119| r0_27(double) = Mul : r0_24, r0_26 -# 119| r0_28(glval) = VariableAddress[z] : -# 119| mu0_29(double) = Store : &:r0_28, r0_27 -# 120| r0_30(glval) = VariableAddress[x] : -# 120| r0_31(double) = Load : &:r0_30, ~mu0_2 -# 120| r0_32(glval) = VariableAddress[y] : -# 120| r0_33(double) = Load : &:r0_32, ~mu0_2 -# 120| r0_34(double) = Div : r0_31, r0_33 -# 120| r0_35(glval) = VariableAddress[z] : -# 120| mu0_36(double) = Store : &:r0_35, r0_34 -# 122| r0_37(glval) = VariableAddress[x] : -# 122| r0_38(double) = Load : &:r0_37, ~mu0_2 -# 122| r0_39(glval) = VariableAddress[z] : -# 122| mu0_40(double) = Store : &:r0_39, r0_38 -# 124| r0_41(glval) = VariableAddress[x] : -# 124| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 124| r0_43(glval) = VariableAddress[z] : -# 124| r0_44(double) = Load : &:r0_43, ~mu0_2 -# 124| r0_45(double) = Add : r0_44, r0_42 -# 124| mu0_46(double) = Store : &:r0_43, r0_45 -# 125| r0_47(glval) = VariableAddress[x] : -# 125| r0_48(double) = Load : &:r0_47, ~mu0_2 -# 125| r0_49(glval) = VariableAddress[z] : -# 125| r0_50(double) = Load : &:r0_49, ~mu0_2 -# 125| r0_51(double) = Sub : r0_50, r0_48 -# 125| mu0_52(double) = Store : &:r0_49, r0_51 -# 126| r0_53(glval) = VariableAddress[x] : -# 126| r0_54(double) = Load : &:r0_53, ~mu0_2 -# 126| r0_55(glval) = VariableAddress[z] : -# 126| r0_56(double) = Load : &:r0_55, ~mu0_2 -# 126| r0_57(double) = Mul : r0_56, r0_54 -# 126| mu0_58(double) = Store : &:r0_55, r0_57 -# 127| r0_59(glval) = VariableAddress[x] : -# 127| r0_60(double) = Load : &:r0_59, ~mu0_2 -# 127| r0_61(glval) = VariableAddress[z] : -# 127| r0_62(double) = Load : &:r0_61, ~mu0_2 -# 127| r0_63(double) = Div : r0_62, r0_60 -# 127| mu0_64(double) = Store : &:r0_61, r0_63 -# 129| r0_65(glval) = VariableAddress[x] : -# 129| r0_66(double) = Load : &:r0_65, ~mu0_2 -# 129| r0_67(double) = CopyValue : r0_66 -# 129| r0_68(glval) = VariableAddress[z] : -# 129| mu0_69(double) = Store : &:r0_68, r0_67 -# 130| r0_70(glval) = VariableAddress[x] : -# 130| r0_71(double) = Load : &:r0_70, ~mu0_2 -# 130| r0_72(double) = Negate : r0_71 -# 130| r0_73(glval) = VariableAddress[z] : -# 130| mu0_74(double) = Store : &:r0_73, r0_72 -# 131| v0_75(void) = NoOp : -# 114| v0_76(void) = ReturnVoid : -# 114| v0_77(void) = UnmodeledUse : mu* -# 114| v0_78(void) = ExitFunction : +# 119| r0_27(glval) = VariableAddress[y] : +# 119| r0_28(double) = Load : &:r0_27, ~mu0_2 +# 119| r0_29(double) = Mul : r0_26, r0_28 +# 119| r0_30(glval) = VariableAddress[z] : +# 119| mu0_31(double) = Store : &:r0_30, r0_29 +# 119| r0_32(glval) = CopyValue : r0_30 +# 120| r0_33(glval) = VariableAddress[x] : +# 120| r0_34(double) = Load : &:r0_33, ~mu0_2 +# 120| r0_35(glval) = VariableAddress[y] : +# 120| r0_36(double) = Load : &:r0_35, ~mu0_2 +# 120| r0_37(double) = Div : r0_34, r0_36 +# 120| r0_38(glval) = VariableAddress[z] : +# 120| mu0_39(double) = Store : &:r0_38, r0_37 +# 120| r0_40(glval) = CopyValue : r0_38 +# 122| r0_41(glval) = VariableAddress[x] : +# 122| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 122| r0_43(glval) = VariableAddress[z] : +# 122| mu0_44(double) = Store : &:r0_43, r0_42 +# 122| r0_45(glval) = CopyValue : r0_43 +# 124| r0_46(glval) = VariableAddress[x] : +# 124| r0_47(double) = Load : &:r0_46, ~mu0_2 +# 124| r0_48(glval) = VariableAddress[z] : +# 124| r0_49(double) = Load : &:r0_48, ~mu0_2 +# 124| r0_50(double) = Add : r0_49, r0_47 +# 124| mu0_51(double) = Store : &:r0_48, r0_50 +# 124| r0_52(glval) = CopyValue : r0_48 +# 125| r0_53(glval) = VariableAddress[x] : +# 125| r0_54(double) = Load : &:r0_53, ~mu0_2 +# 125| r0_55(glval) = VariableAddress[z] : +# 125| r0_56(double) = Load : &:r0_55, ~mu0_2 +# 125| r0_57(double) = Sub : r0_56, r0_54 +# 125| mu0_58(double) = Store : &:r0_55, r0_57 +# 125| r0_59(glval) = CopyValue : r0_55 +# 126| r0_60(glval) = VariableAddress[x] : +# 126| r0_61(double) = Load : &:r0_60, ~mu0_2 +# 126| r0_62(glval) = VariableAddress[z] : +# 126| r0_63(double) = Load : &:r0_62, ~mu0_2 +# 126| r0_64(double) = Mul : r0_63, r0_61 +# 126| mu0_65(double) = Store : &:r0_62, r0_64 +# 126| r0_66(glval) = CopyValue : r0_62 +# 127| r0_67(glval) = VariableAddress[x] : +# 127| r0_68(double) = Load : &:r0_67, ~mu0_2 +# 127| r0_69(glval) = VariableAddress[z] : +# 127| r0_70(double) = Load : &:r0_69, ~mu0_2 +# 127| r0_71(double) = Div : r0_70, r0_68 +# 127| mu0_72(double) = Store : &:r0_69, r0_71 +# 127| r0_73(glval) = CopyValue : r0_69 +# 129| r0_74(glval) = VariableAddress[x] : +# 129| r0_75(double) = Load : &:r0_74, ~mu0_2 +# 129| r0_76(double) = CopyValue : r0_75 +# 129| r0_77(glval) = VariableAddress[z] : +# 129| mu0_78(double) = Store : &:r0_77, r0_76 +# 129| r0_79(glval) = CopyValue : r0_77 +# 130| r0_80(glval) = VariableAddress[x] : +# 130| r0_81(double) = Load : &:r0_80, ~mu0_2 +# 130| r0_82(double) = Negate : r0_81 +# 130| r0_83(glval) = VariableAddress[z] : +# 130| mu0_84(double) = Store : &:r0_83, r0_82 +# 130| r0_85(glval) = CopyValue : r0_83 +# 131| v0_86(void) = NoOp : +# 114| v0_87(void) = ReturnVoid : +# 114| v0_88(void) = UnmodeledUse : mu* +# 114| v0_89(void) = ExitFunction : # 133| void FloatCompare(double, double) # 133| Block 0 @@ -611,45 +668,51 @@ ir.cpp: # 136| r0_13(bool) = CompareEQ : r0_10, r0_12 # 136| r0_14(glval) = VariableAddress[b] : # 136| mu0_15(bool) = Store : &:r0_14, r0_13 -# 137| r0_16(glval) = VariableAddress[x] : -# 137| r0_17(double) = Load : &:r0_16, ~mu0_2 -# 137| r0_18(glval) = VariableAddress[y] : -# 137| r0_19(double) = Load : &:r0_18, ~mu0_2 -# 137| r0_20(bool) = CompareNE : r0_17, r0_19 -# 137| r0_21(glval) = VariableAddress[b] : -# 137| mu0_22(bool) = Store : &:r0_21, r0_20 -# 138| r0_23(glval) = VariableAddress[x] : -# 138| r0_24(double) = Load : &:r0_23, ~mu0_2 -# 138| r0_25(glval) = VariableAddress[y] : +# 136| r0_16(glval) = CopyValue : r0_14 +# 137| r0_17(glval) = VariableAddress[x] : +# 137| r0_18(double) = Load : &:r0_17, ~mu0_2 +# 137| r0_19(glval) = VariableAddress[y] : +# 137| r0_20(double) = Load : &:r0_19, ~mu0_2 +# 137| r0_21(bool) = CompareNE : r0_18, r0_20 +# 137| r0_22(glval) = VariableAddress[b] : +# 137| mu0_23(bool) = Store : &:r0_22, r0_21 +# 137| r0_24(glval) = CopyValue : r0_22 +# 138| r0_25(glval) = VariableAddress[x] : # 138| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 138| r0_27(bool) = CompareLT : r0_24, r0_26 -# 138| r0_28(glval) = VariableAddress[b] : -# 138| mu0_29(bool) = Store : &:r0_28, r0_27 -# 139| r0_30(glval) = VariableAddress[x] : -# 139| r0_31(double) = Load : &:r0_30, ~mu0_2 -# 139| r0_32(glval) = VariableAddress[y] : -# 139| r0_33(double) = Load : &:r0_32, ~mu0_2 -# 139| r0_34(bool) = CompareGT : r0_31, r0_33 -# 139| r0_35(glval) = VariableAddress[b] : -# 139| mu0_36(bool) = Store : &:r0_35, r0_34 -# 140| r0_37(glval) = VariableAddress[x] : -# 140| r0_38(double) = Load : &:r0_37, ~mu0_2 -# 140| r0_39(glval) = VariableAddress[y] : -# 140| r0_40(double) = Load : &:r0_39, ~mu0_2 -# 140| r0_41(bool) = CompareLE : r0_38, r0_40 -# 140| r0_42(glval) = VariableAddress[b] : -# 140| mu0_43(bool) = Store : &:r0_42, r0_41 -# 141| r0_44(glval) = VariableAddress[x] : -# 141| r0_45(double) = Load : &:r0_44, ~mu0_2 -# 141| r0_46(glval) = VariableAddress[y] : -# 141| r0_47(double) = Load : &:r0_46, ~mu0_2 -# 141| r0_48(bool) = CompareGE : r0_45, r0_47 -# 141| r0_49(glval) = VariableAddress[b] : -# 141| mu0_50(bool) = Store : &:r0_49, r0_48 -# 142| v0_51(void) = NoOp : -# 133| v0_52(void) = ReturnVoid : -# 133| v0_53(void) = UnmodeledUse : mu* -# 133| v0_54(void) = ExitFunction : +# 138| r0_27(glval) = VariableAddress[y] : +# 138| r0_28(double) = Load : &:r0_27, ~mu0_2 +# 138| r0_29(bool) = CompareLT : r0_26, r0_28 +# 138| r0_30(glval) = VariableAddress[b] : +# 138| mu0_31(bool) = Store : &:r0_30, r0_29 +# 138| r0_32(glval) = CopyValue : r0_30 +# 139| r0_33(glval) = VariableAddress[x] : +# 139| r0_34(double) = Load : &:r0_33, ~mu0_2 +# 139| r0_35(glval) = VariableAddress[y] : +# 139| r0_36(double) = Load : &:r0_35, ~mu0_2 +# 139| r0_37(bool) = CompareGT : r0_34, r0_36 +# 139| r0_38(glval) = VariableAddress[b] : +# 139| mu0_39(bool) = Store : &:r0_38, r0_37 +# 139| r0_40(glval) = CopyValue : r0_38 +# 140| r0_41(glval) = VariableAddress[x] : +# 140| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 140| r0_43(glval) = VariableAddress[y] : +# 140| r0_44(double) = Load : &:r0_43, ~mu0_2 +# 140| r0_45(bool) = CompareLE : r0_42, r0_44 +# 140| r0_46(glval) = VariableAddress[b] : +# 140| mu0_47(bool) = Store : &:r0_46, r0_45 +# 140| r0_48(glval) = CopyValue : r0_46 +# 141| r0_49(glval) = VariableAddress[x] : +# 141| r0_50(double) = Load : &:r0_49, ~mu0_2 +# 141| r0_51(glval) = VariableAddress[y] : +# 141| r0_52(double) = Load : &:r0_51, ~mu0_2 +# 141| r0_53(bool) = CompareGE : r0_50, r0_52 +# 141| r0_54(glval) = VariableAddress[b] : +# 141| mu0_55(bool) = Store : &:r0_54, r0_53 +# 141| r0_56(glval) = CopyValue : r0_54 +# 142| v0_57(void) = NoOp : +# 133| v0_58(void) = ReturnVoid : +# 133| v0_59(void) = UnmodeledUse : mu* +# 133| v0_60(void) = ExitFunction : # 144| void FloatCrement(float) # 144| Block 0 @@ -667,31 +730,35 @@ ir.cpp: # 147| mu0_11(float) = Store : &:r0_7, r0_10 # 147| r0_12(glval) = VariableAddress[y] : # 147| mu0_13(float) = Store : &:r0_12, r0_10 -# 148| r0_14(glval) = VariableAddress[x] : -# 148| r0_15(float) = Load : &:r0_14, ~mu0_2 -# 148| r0_16(float) = Constant[1.0] : -# 148| r0_17(float) = Sub : r0_15, r0_16 -# 148| mu0_18(float) = Store : &:r0_14, r0_17 -# 148| r0_19(glval) = VariableAddress[y] : -# 148| mu0_20(float) = Store : &:r0_19, r0_17 -# 149| r0_21(glval) = VariableAddress[x] : -# 149| r0_22(float) = Load : &:r0_21, ~mu0_2 -# 149| r0_23(float) = Constant[1.0] : -# 149| r0_24(float) = Add : r0_22, r0_23 -# 149| mu0_25(float) = Store : &:r0_21, r0_24 -# 149| r0_26(glval) = VariableAddress[y] : -# 149| mu0_27(float) = Store : &:r0_26, r0_22 -# 150| r0_28(glval) = VariableAddress[x] : -# 150| r0_29(float) = Load : &:r0_28, ~mu0_2 -# 150| r0_30(float) = Constant[1.0] : -# 150| r0_31(float) = Sub : r0_29, r0_30 -# 150| mu0_32(float) = Store : &:r0_28, r0_31 -# 150| r0_33(glval) = VariableAddress[y] : -# 150| mu0_34(float) = Store : &:r0_33, r0_29 -# 151| v0_35(void) = NoOp : -# 144| v0_36(void) = ReturnVoid : -# 144| v0_37(void) = UnmodeledUse : mu* -# 144| v0_38(void) = ExitFunction : +# 147| r0_14(glval) = CopyValue : r0_12 +# 148| r0_15(glval) = VariableAddress[x] : +# 148| r0_16(float) = Load : &:r0_15, ~mu0_2 +# 148| r0_17(float) = Constant[1.0] : +# 148| r0_18(float) = Sub : r0_16, r0_17 +# 148| mu0_19(float) = Store : &:r0_15, r0_18 +# 148| r0_20(glval) = VariableAddress[y] : +# 148| mu0_21(float) = Store : &:r0_20, r0_18 +# 148| r0_22(glval) = CopyValue : r0_20 +# 149| r0_23(glval) = VariableAddress[x] : +# 149| r0_24(float) = Load : &:r0_23, ~mu0_2 +# 149| r0_25(float) = Constant[1.0] : +# 149| r0_26(float) = Add : r0_24, r0_25 +# 149| mu0_27(float) = Store : &:r0_23, r0_26 +# 149| r0_28(glval) = VariableAddress[y] : +# 149| mu0_29(float) = Store : &:r0_28, r0_24 +# 149| r0_30(glval) = CopyValue : r0_28 +# 150| r0_31(glval) = VariableAddress[x] : +# 150| r0_32(float) = Load : &:r0_31, ~mu0_2 +# 150| r0_33(float) = Constant[1.0] : +# 150| r0_34(float) = Sub : r0_32, r0_33 +# 150| mu0_35(float) = Store : &:r0_31, r0_34 +# 150| r0_36(glval) = VariableAddress[y] : +# 150| mu0_37(float) = Store : &:r0_36, r0_32 +# 150| r0_38(glval) = CopyValue : r0_36 +# 151| v0_39(void) = NoOp : +# 144| v0_40(void) = ReturnVoid : +# 144| v0_41(void) = UnmodeledUse : mu* +# 144| v0_42(void) = ExitFunction : # 153| void PointerOps(int*, int) # 153| Block 0 @@ -713,61 +780,70 @@ ir.cpp: # 157| r0_15(int *) = PointerAdd[4] : r0_12, r0_14 # 157| r0_16(glval) = VariableAddress[q] : # 157| mu0_17(int *) = Store : &:r0_16, r0_15 -# 158| r0_18(glval) = VariableAddress[i] : -# 158| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 158| r0_20(glval) = VariableAddress[p] : -# 158| r0_21(int *) = Load : &:r0_20, ~mu0_2 -# 158| r0_22(int *) = PointerAdd[4] : r0_21, r0_19 -# 158| r0_23(glval) = VariableAddress[q] : -# 158| mu0_24(int *) = Store : &:r0_23, r0_22 -# 159| r0_25(glval) = VariableAddress[p] : -# 159| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 159| r0_27(glval) = VariableAddress[i] : -# 159| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 159| r0_29(int *) = PointerSub[4] : r0_26, r0_28 -# 159| r0_30(glval) = VariableAddress[q] : -# 159| mu0_31(int *) = Store : &:r0_30, r0_29 -# 160| r0_32(glval) = VariableAddress[p] : -# 160| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 160| r0_34(glval) = VariableAddress[q] : -# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 -# 160| r0_36(long) = PointerDiff[4] : r0_33, r0_35 -# 160| r0_37(int) = Convert : r0_36 -# 160| r0_38(glval) = VariableAddress[i] : -# 160| mu0_39(int) = Store : &:r0_38, r0_37 -# 162| r0_40(glval) = VariableAddress[p] : -# 162| r0_41(int *) = Load : &:r0_40, ~mu0_2 -# 162| r0_42(glval) = VariableAddress[q] : -# 162| mu0_43(int *) = Store : &:r0_42, r0_41 -# 164| r0_44(glval) = VariableAddress[i] : -# 164| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 164| r0_46(glval) = VariableAddress[q] : -# 164| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 164| r0_48(int *) = PointerAdd[4] : r0_47, r0_45 -# 164| mu0_49(int *) = Store : &:r0_46, r0_48 -# 165| r0_50(glval) = VariableAddress[i] : -# 165| r0_51(int) = Load : &:r0_50, ~mu0_2 -# 165| r0_52(glval) = VariableAddress[q] : -# 165| r0_53(int *) = Load : &:r0_52, ~mu0_2 -# 165| r0_54(int *) = PointerSub[4] : r0_53, r0_51 -# 165| mu0_55(int *) = Store : &:r0_52, r0_54 -# 167| r0_56(glval) = VariableAddress[p] : -# 167| r0_57(int *) = Load : &:r0_56, ~mu0_2 -# 167| r0_58(int *) = Constant[0] : -# 167| r0_59(bool) = CompareNE : r0_57, r0_58 -# 167| r0_60(glval) = VariableAddress[b] : -# 167| mu0_61(bool) = Store : &:r0_60, r0_59 -# 168| r0_62(glval) = VariableAddress[p] : -# 168| r0_63(int *) = Load : &:r0_62, ~mu0_2 -# 168| r0_64(int *) = Constant[0] : -# 168| r0_65(bool) = CompareNE : r0_63, r0_64 -# 168| r0_66(bool) = LogicalNot : r0_65 -# 168| r0_67(glval) = VariableAddress[b] : -# 168| mu0_68(bool) = Store : &:r0_67, r0_66 -# 169| v0_69(void) = NoOp : -# 153| v0_70(void) = ReturnVoid : -# 153| v0_71(void) = UnmodeledUse : mu* -# 153| v0_72(void) = ExitFunction : +# 157| r0_18(glval) = CopyValue : r0_16 +# 158| r0_19(glval) = VariableAddress[i] : +# 158| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 158| r0_21(glval) = VariableAddress[p] : +# 158| r0_22(int *) = Load : &:r0_21, ~mu0_2 +# 158| r0_23(int *) = PointerAdd[4] : r0_22, r0_20 +# 158| r0_24(glval) = VariableAddress[q] : +# 158| mu0_25(int *) = Store : &:r0_24, r0_23 +# 158| r0_26(glval) = CopyValue : r0_24 +# 159| r0_27(glval) = VariableAddress[p] : +# 159| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 159| r0_29(glval) = VariableAddress[i] : +# 159| r0_30(int) = Load : &:r0_29, ~mu0_2 +# 159| r0_31(int *) = PointerSub[4] : r0_28, r0_30 +# 159| r0_32(glval) = VariableAddress[q] : +# 159| mu0_33(int *) = Store : &:r0_32, r0_31 +# 159| r0_34(glval) = CopyValue : r0_32 +# 160| r0_35(glval) = VariableAddress[p] : +# 160| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 160| r0_37(glval) = VariableAddress[q] : +# 160| r0_38(int *) = Load : &:r0_37, ~mu0_2 +# 160| r0_39(long) = PointerDiff[4] : r0_36, r0_38 +# 160| r0_40(int) = Convert : r0_39 +# 160| r0_41(glval) = VariableAddress[i] : +# 160| mu0_42(int) = Store : &:r0_41, r0_40 +# 160| r0_43(glval) = CopyValue : r0_41 +# 162| r0_44(glval) = VariableAddress[p] : +# 162| r0_45(int *) = Load : &:r0_44, ~mu0_2 +# 162| r0_46(glval) = VariableAddress[q] : +# 162| mu0_47(int *) = Store : &:r0_46, r0_45 +# 162| r0_48(glval) = CopyValue : r0_46 +# 164| r0_49(glval) = VariableAddress[i] : +# 164| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 164| r0_51(glval) = VariableAddress[q] : +# 164| r0_52(int *) = Load : &:r0_51, ~mu0_2 +# 164| r0_53(int *) = PointerAdd[4] : r0_52, r0_50 +# 164| mu0_54(int *) = Store : &:r0_51, r0_53 +# 164| r0_55(glval) = CopyValue : r0_51 +# 165| r0_56(glval) = VariableAddress[i] : +# 165| r0_57(int) = Load : &:r0_56, ~mu0_2 +# 165| r0_58(glval) = VariableAddress[q] : +# 165| r0_59(int *) = Load : &:r0_58, ~mu0_2 +# 165| r0_60(int *) = PointerSub[4] : r0_59, r0_57 +# 165| mu0_61(int *) = Store : &:r0_58, r0_60 +# 165| r0_62(glval) = CopyValue : r0_58 +# 167| r0_63(glval) = VariableAddress[p] : +# 167| r0_64(int *) = Load : &:r0_63, ~mu0_2 +# 167| r0_65(int *) = Constant[0] : +# 167| r0_66(bool) = CompareNE : r0_64, r0_65 +# 167| r0_67(glval) = VariableAddress[b] : +# 167| mu0_68(bool) = Store : &:r0_67, r0_66 +# 167| r0_69(glval) = CopyValue : r0_67 +# 168| r0_70(glval) = VariableAddress[p] : +# 168| r0_71(int *) = Load : &:r0_70, ~mu0_2 +# 168| r0_72(int *) = Constant[0] : +# 168| r0_73(bool) = CompareNE : r0_71, r0_72 +# 168| r0_74(bool) = LogicalNot : r0_73 +# 168| r0_75(glval) = VariableAddress[b] : +# 168| mu0_76(bool) = Store : &:r0_75, r0_74 +# 168| r0_77(glval) = CopyValue : r0_75 +# 169| v0_78(void) = NoOp : +# 153| v0_79(void) = ReturnVoid : +# 153| v0_80(void) = UnmodeledUse : mu* +# 153| v0_81(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 @@ -788,68 +864,76 @@ ir.cpp: # 174| r0_14(int) = Load : &:r0_13, ~mu0_2 # 174| r0_15(glval) = VariableAddress[x] : # 174| mu0_16(int) = Store : &:r0_15, r0_14 -# 175| r0_17(glval) = VariableAddress[p] : -# 175| r0_18(int *) = Load : &:r0_17, ~mu0_2 -# 175| r0_19(glval) = VariableAddress[i] : -# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 175| r0_21(glval) = PointerAdd[4] : r0_18, r0_20 -# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 -# 175| r0_23(glval) = VariableAddress[x] : -# 175| mu0_24(int) = Store : &:r0_23, r0_22 -# 177| r0_25(glval) = VariableAddress[x] : -# 177| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 177| r0_27(glval) = VariableAddress[p] : -# 177| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 177| r0_29(glval) = VariableAddress[i] : -# 177| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 177| r0_31(glval) = PointerAdd[4] : r0_28, r0_30 -# 177| mu0_32(int) = Store : &:r0_31, r0_26 -# 178| r0_33(glval) = VariableAddress[x] : -# 178| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 178| r0_35(glval) = VariableAddress[p] : -# 178| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 178| r0_37(glval) = VariableAddress[i] : -# 178| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 178| r0_39(glval) = PointerAdd[4] : r0_36, r0_38 -# 178| mu0_40(int) = Store : &:r0_39, r0_34 -# 180| r0_41(glval) = VariableAddress[a] : -# 180| mu0_42(int[10]) = Uninitialized[a] : &:r0_41 -# 181| r0_43(glval) = VariableAddress[a] : -# 181| r0_44(int *) = Convert : r0_43 -# 181| r0_45(glval) = VariableAddress[i] : -# 181| r0_46(int) = Load : &:r0_45, ~mu0_2 -# 181| r0_47(glval) = PointerAdd[4] : r0_44, r0_46 -# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 -# 181| r0_49(glval) = VariableAddress[x] : -# 181| mu0_50(int) = Store : &:r0_49, r0_48 -# 182| r0_51(glval) = VariableAddress[a] : -# 182| r0_52(int *) = Convert : r0_51 -# 182| r0_53(glval) = VariableAddress[i] : -# 182| r0_54(int) = Load : &:r0_53, ~mu0_2 -# 182| r0_55(glval) = PointerAdd[4] : r0_52, r0_54 -# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 -# 182| r0_57(glval) = VariableAddress[x] : -# 182| mu0_58(int) = Store : &:r0_57, r0_56 -# 183| r0_59(glval) = VariableAddress[x] : -# 183| r0_60(int) = Load : &:r0_59, ~mu0_2 -# 183| r0_61(glval) = VariableAddress[a] : -# 183| r0_62(int *) = Convert : r0_61 -# 183| r0_63(glval) = VariableAddress[i] : -# 183| r0_64(int) = Load : &:r0_63, ~mu0_2 -# 183| r0_65(glval) = PointerAdd[4] : r0_62, r0_64 -# 183| mu0_66(int) = Store : &:r0_65, r0_60 -# 184| r0_67(glval) = VariableAddress[x] : -# 184| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 184| r0_69(glval) = VariableAddress[a] : -# 184| r0_70(int *) = Convert : r0_69 -# 184| r0_71(glval) = VariableAddress[i] : -# 184| r0_72(int) = Load : &:r0_71, ~mu0_2 -# 184| r0_73(glval) = PointerAdd[4] : r0_70, r0_72 -# 184| mu0_74(int) = Store : &:r0_73, r0_68 -# 185| v0_75(void) = NoOp : -# 171| v0_76(void) = ReturnVoid : -# 171| v0_77(void) = UnmodeledUse : mu* -# 171| v0_78(void) = ExitFunction : +# 174| r0_17(glval) = CopyValue : r0_15 +# 175| r0_18(glval) = VariableAddress[p] : +# 175| r0_19(int *) = Load : &:r0_18, ~mu0_2 +# 175| r0_20(glval) = VariableAddress[i] : +# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 175| r0_22(glval) = PointerAdd[4] : r0_19, r0_21 +# 175| r0_23(int) = Load : &:r0_22, ~mu0_2 +# 175| r0_24(glval) = VariableAddress[x] : +# 175| mu0_25(int) = Store : &:r0_24, r0_23 +# 175| r0_26(glval) = CopyValue : r0_24 +# 177| r0_27(glval) = VariableAddress[x] : +# 177| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 177| r0_29(glval) = VariableAddress[p] : +# 177| r0_30(int *) = Load : &:r0_29, ~mu0_2 +# 177| r0_31(glval) = VariableAddress[i] : +# 177| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 177| r0_33(glval) = PointerAdd[4] : r0_30, r0_32 +# 177| mu0_34(int) = Store : &:r0_33, r0_28 +# 177| r0_35(glval) = CopyValue : r0_33 +# 178| r0_36(glval) = VariableAddress[x] : +# 178| r0_37(int) = Load : &:r0_36, ~mu0_2 +# 178| r0_38(glval) = VariableAddress[p] : +# 178| r0_39(int *) = Load : &:r0_38, ~mu0_2 +# 178| r0_40(glval) = VariableAddress[i] : +# 178| r0_41(int) = Load : &:r0_40, ~mu0_2 +# 178| r0_42(glval) = PointerAdd[4] : r0_39, r0_41 +# 178| mu0_43(int) = Store : &:r0_42, r0_37 +# 178| r0_44(glval) = CopyValue : r0_42 +# 180| r0_45(glval) = VariableAddress[a] : +# 180| mu0_46(int[10]) = Uninitialized[a] : &:r0_45 +# 181| r0_47(glval) = VariableAddress[a] : +# 181| r0_48(int *) = Convert : r0_47 +# 181| r0_49(glval) = VariableAddress[i] : +# 181| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 181| r0_51(glval) = PointerAdd[4] : r0_48, r0_50 +# 181| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 181| r0_53(glval) = VariableAddress[x] : +# 181| mu0_54(int) = Store : &:r0_53, r0_52 +# 181| r0_55(glval) = CopyValue : r0_53 +# 182| r0_56(glval) = VariableAddress[a] : +# 182| r0_57(int *) = Convert : r0_56 +# 182| r0_58(glval) = VariableAddress[i] : +# 182| r0_59(int) = Load : &:r0_58, ~mu0_2 +# 182| r0_60(glval) = PointerAdd[4] : r0_57, r0_59 +# 182| r0_61(int) = Load : &:r0_60, ~mu0_2 +# 182| r0_62(glval) = VariableAddress[x] : +# 182| mu0_63(int) = Store : &:r0_62, r0_61 +# 182| r0_64(glval) = CopyValue : r0_62 +# 183| r0_65(glval) = VariableAddress[x] : +# 183| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 183| r0_67(glval) = VariableAddress[a] : +# 183| r0_68(int *) = Convert : r0_67 +# 183| r0_69(glval) = VariableAddress[i] : +# 183| r0_70(int) = Load : &:r0_69, ~mu0_2 +# 183| r0_71(glval) = PointerAdd[4] : r0_68, r0_70 +# 183| mu0_72(int) = Store : &:r0_71, r0_66 +# 183| r0_73(glval) = CopyValue : r0_71 +# 184| r0_74(glval) = VariableAddress[x] : +# 184| r0_75(int) = Load : &:r0_74, ~mu0_2 +# 184| r0_76(glval) = VariableAddress[a] : +# 184| r0_77(int *) = Convert : r0_76 +# 184| r0_78(glval) = VariableAddress[i] : +# 184| r0_79(int) = Load : &:r0_78, ~mu0_2 +# 184| r0_80(glval) = PointerAdd[4] : r0_77, r0_79 +# 184| mu0_81(int) = Store : &:r0_80, r0_75 +# 184| r0_82(glval) = CopyValue : r0_80 +# 185| v0_83(void) = NoOp : +# 171| v0_84(void) = ReturnVoid : +# 171| v0_85(void) = UnmodeledUse : mu* +# 171| v0_86(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -902,45 +986,51 @@ ir.cpp: # 196| r0_13(bool) = CompareEQ : r0_10, r0_12 # 196| r0_14(glval) = VariableAddress[b] : # 196| mu0_15(bool) = Store : &:r0_14, r0_13 -# 197| r0_16(glval) = VariableAddress[p] : -# 197| r0_17(int *) = Load : &:r0_16, ~mu0_2 -# 197| r0_18(glval) = VariableAddress[q] : -# 197| r0_19(int *) = Load : &:r0_18, ~mu0_2 -# 197| r0_20(bool) = CompareNE : r0_17, r0_19 -# 197| r0_21(glval) = VariableAddress[b] : -# 197| mu0_22(bool) = Store : &:r0_21, r0_20 -# 198| r0_23(glval) = VariableAddress[p] : -# 198| r0_24(int *) = Load : &:r0_23, ~mu0_2 -# 198| r0_25(glval) = VariableAddress[q] : +# 196| r0_16(glval) = CopyValue : r0_14 +# 197| r0_17(glval) = VariableAddress[p] : +# 197| r0_18(int *) = Load : &:r0_17, ~mu0_2 +# 197| r0_19(glval) = VariableAddress[q] : +# 197| r0_20(int *) = Load : &:r0_19, ~mu0_2 +# 197| r0_21(bool) = CompareNE : r0_18, r0_20 +# 197| r0_22(glval) = VariableAddress[b] : +# 197| mu0_23(bool) = Store : &:r0_22, r0_21 +# 197| r0_24(glval) = CopyValue : r0_22 +# 198| r0_25(glval) = VariableAddress[p] : # 198| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 198| r0_27(bool) = CompareLT : r0_24, r0_26 -# 198| r0_28(glval) = VariableAddress[b] : -# 198| mu0_29(bool) = Store : &:r0_28, r0_27 -# 199| r0_30(glval) = VariableAddress[p] : -# 199| r0_31(int *) = Load : &:r0_30, ~mu0_2 -# 199| r0_32(glval) = VariableAddress[q] : -# 199| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 199| r0_34(bool) = CompareGT : r0_31, r0_33 -# 199| r0_35(glval) = VariableAddress[b] : -# 199| mu0_36(bool) = Store : &:r0_35, r0_34 -# 200| r0_37(glval) = VariableAddress[p] : -# 200| r0_38(int *) = Load : &:r0_37, ~mu0_2 -# 200| r0_39(glval) = VariableAddress[q] : -# 200| r0_40(int *) = Load : &:r0_39, ~mu0_2 -# 200| r0_41(bool) = CompareLE : r0_38, r0_40 -# 200| r0_42(glval) = VariableAddress[b] : -# 200| mu0_43(bool) = Store : &:r0_42, r0_41 -# 201| r0_44(glval) = VariableAddress[p] : -# 201| r0_45(int *) = Load : &:r0_44, ~mu0_2 -# 201| r0_46(glval) = VariableAddress[q] : -# 201| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 201| r0_48(bool) = CompareGE : r0_45, r0_47 -# 201| r0_49(glval) = VariableAddress[b] : -# 201| mu0_50(bool) = Store : &:r0_49, r0_48 -# 202| v0_51(void) = NoOp : -# 193| v0_52(void) = ReturnVoid : -# 193| v0_53(void) = UnmodeledUse : mu* -# 193| v0_54(void) = ExitFunction : +# 198| r0_27(glval) = VariableAddress[q] : +# 198| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 198| r0_29(bool) = CompareLT : r0_26, r0_28 +# 198| r0_30(glval) = VariableAddress[b] : +# 198| mu0_31(bool) = Store : &:r0_30, r0_29 +# 198| r0_32(glval) = CopyValue : r0_30 +# 199| r0_33(glval) = VariableAddress[p] : +# 199| r0_34(int *) = Load : &:r0_33, ~mu0_2 +# 199| r0_35(glval) = VariableAddress[q] : +# 199| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 199| r0_37(bool) = CompareGT : r0_34, r0_36 +# 199| r0_38(glval) = VariableAddress[b] : +# 199| mu0_39(bool) = Store : &:r0_38, r0_37 +# 199| r0_40(glval) = CopyValue : r0_38 +# 200| r0_41(glval) = VariableAddress[p] : +# 200| r0_42(int *) = Load : &:r0_41, ~mu0_2 +# 200| r0_43(glval) = VariableAddress[q] : +# 200| r0_44(int *) = Load : &:r0_43, ~mu0_2 +# 200| r0_45(bool) = CompareLE : r0_42, r0_44 +# 200| r0_46(glval) = VariableAddress[b] : +# 200| mu0_47(bool) = Store : &:r0_46, r0_45 +# 200| r0_48(glval) = CopyValue : r0_46 +# 201| r0_49(glval) = VariableAddress[p] : +# 201| r0_50(int *) = Load : &:r0_49, ~mu0_2 +# 201| r0_51(glval) = VariableAddress[q] : +# 201| r0_52(int *) = Load : &:r0_51, ~mu0_2 +# 201| r0_53(bool) = CompareGE : r0_50, r0_52 +# 201| r0_54(glval) = VariableAddress[b] : +# 201| mu0_55(bool) = Store : &:r0_54, r0_53 +# 201| r0_56(glval) = CopyValue : r0_54 +# 202| v0_57(void) = NoOp : +# 193| v0_58(void) = ReturnVoid : +# 193| v0_59(void) = UnmodeledUse : mu* +# 193| v0_60(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 @@ -958,31 +1048,35 @@ ir.cpp: # 207| mu0_11(int *) = Store : &:r0_7, r0_10 # 207| r0_12(glval) = VariableAddress[q] : # 207| mu0_13(int *) = Store : &:r0_12, r0_10 -# 208| r0_14(glval) = VariableAddress[p] : -# 208| r0_15(int *) = Load : &:r0_14, ~mu0_2 -# 208| r0_16(int) = Constant[1] : -# 208| r0_17(int *) = PointerSub[4] : r0_15, r0_16 -# 208| mu0_18(int *) = Store : &:r0_14, r0_17 -# 208| r0_19(glval) = VariableAddress[q] : -# 208| mu0_20(int *) = Store : &:r0_19, r0_17 -# 209| r0_21(glval) = VariableAddress[p] : -# 209| r0_22(int *) = Load : &:r0_21, ~mu0_2 -# 209| r0_23(int) = Constant[1] : -# 209| r0_24(int *) = PointerAdd[4] : r0_22, r0_23 -# 209| mu0_25(int *) = Store : &:r0_21, r0_24 -# 209| r0_26(glval) = VariableAddress[q] : -# 209| mu0_27(int *) = Store : &:r0_26, r0_22 -# 210| r0_28(glval) = VariableAddress[p] : -# 210| r0_29(int *) = Load : &:r0_28, ~mu0_2 -# 210| r0_30(int) = Constant[1] : -# 210| r0_31(int *) = PointerSub[4] : r0_29, r0_30 -# 210| mu0_32(int *) = Store : &:r0_28, r0_31 -# 210| r0_33(glval) = VariableAddress[q] : -# 210| mu0_34(int *) = Store : &:r0_33, r0_29 -# 211| v0_35(void) = NoOp : -# 204| v0_36(void) = ReturnVoid : -# 204| v0_37(void) = UnmodeledUse : mu* -# 204| v0_38(void) = ExitFunction : +# 207| r0_14(glval) = CopyValue : r0_12 +# 208| r0_15(glval) = VariableAddress[p] : +# 208| r0_16(int *) = Load : &:r0_15, ~mu0_2 +# 208| r0_17(int) = Constant[1] : +# 208| r0_18(int *) = PointerSub[4] : r0_16, r0_17 +# 208| mu0_19(int *) = Store : &:r0_15, r0_18 +# 208| r0_20(glval) = VariableAddress[q] : +# 208| mu0_21(int *) = Store : &:r0_20, r0_18 +# 208| r0_22(glval) = CopyValue : r0_20 +# 209| r0_23(glval) = VariableAddress[p] : +# 209| r0_24(int *) = Load : &:r0_23, ~mu0_2 +# 209| r0_25(int) = Constant[1] : +# 209| r0_26(int *) = PointerAdd[4] : r0_24, r0_25 +# 209| mu0_27(int *) = Store : &:r0_23, r0_26 +# 209| r0_28(glval) = VariableAddress[q] : +# 209| mu0_29(int *) = Store : &:r0_28, r0_24 +# 209| r0_30(glval) = CopyValue : r0_28 +# 210| r0_31(glval) = VariableAddress[p] : +# 210| r0_32(int *) = Load : &:r0_31, ~mu0_2 +# 210| r0_33(int) = Constant[1] : +# 210| r0_34(int *) = PointerSub[4] : r0_32, r0_33 +# 210| mu0_35(int *) = Store : &:r0_31, r0_34 +# 210| r0_36(glval) = VariableAddress[q] : +# 210| mu0_37(int *) = Store : &:r0_36, r0_32 +# 210| r0_38(glval) = CopyValue : r0_36 +# 211| v0_39(void) = NoOp : +# 204| v0_40(void) = ReturnVoid : +# 204| v0_41(void) = UnmodeledUse : mu* +# 204| v0_42(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -997,36 +1091,40 @@ ir.cpp: # 216| r0_8(int) = Load : &:r0_7, ~mu0_2 # 216| r0_9(int) = Add : r0_8, r0_6 # 216| mu0_10(int) = Store : &:r0_7, r0_9 -# 219| r0_11(glval) = VariableAddress[y] : -# 219| r0_12(short) = Constant[5] : -# 219| mu0_13(short) = Store : &:r0_11, r0_12 -# 220| r0_14(glval) = VariableAddress[x] : -# 220| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 220| r0_16(glval) = VariableAddress[y] : -# 220| r0_17(short) = Load : &:r0_16, ~mu0_2 -# 220| r0_18(int) = Convert : r0_17 -# 220| r0_19(int) = Add : r0_18, r0_15 -# 220| r0_20(short) = Convert : r0_19 -# 220| mu0_21(short) = Store : &:r0_16, r0_20 -# 223| r0_22(int) = Constant[1] : -# 223| r0_23(glval) = VariableAddress[y] : -# 223| r0_24(short) = Load : &:r0_23, ~mu0_2 -# 223| r0_25(short) = ShiftLeft : r0_24, r0_22 -# 223| mu0_26(short) = Store : &:r0_23, r0_25 -# 226| r0_27(glval) = VariableAddress[z] : -# 226| r0_28(long) = Constant[7] : -# 226| mu0_29(long) = Store : &:r0_27, r0_28 -# 227| r0_30(float) = Constant[2.0] : -# 227| r0_31(glval) = VariableAddress[z] : -# 227| r0_32(long) = Load : &:r0_31, ~mu0_2 -# 227| r0_33(float) = Convert : r0_32 -# 227| r0_34(float) = Add : r0_33, r0_30 -# 227| r0_35(long) = Convert : r0_34 -# 227| mu0_36(long) = Store : &:r0_31, r0_35 -# 228| v0_37(void) = NoOp : -# 213| v0_38(void) = ReturnVoid : -# 213| v0_39(void) = UnmodeledUse : mu* -# 213| v0_40(void) = ExitFunction : +# 216| r0_11(glval) = CopyValue : r0_7 +# 219| r0_12(glval) = VariableAddress[y] : +# 219| r0_13(short) = Constant[5] : +# 219| mu0_14(short) = Store : &:r0_12, r0_13 +# 220| r0_15(glval) = VariableAddress[x] : +# 220| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 220| r0_17(glval) = VariableAddress[y] : +# 220| r0_18(short) = Load : &:r0_17, ~mu0_2 +# 220| r0_19(int) = Convert : r0_18 +# 220| r0_20(int) = Add : r0_19, r0_16 +# 220| r0_21(short) = Convert : r0_20 +# 220| mu0_22(short) = Store : &:r0_17, r0_21 +# 220| r0_23(glval) = CopyValue : r0_17 +# 223| r0_24(int) = Constant[1] : +# 223| r0_25(glval) = VariableAddress[y] : +# 223| r0_26(short) = Load : &:r0_25, ~mu0_2 +# 223| r0_27(short) = ShiftLeft : r0_26, r0_24 +# 223| mu0_28(short) = Store : &:r0_25, r0_27 +# 223| r0_29(glval) = CopyValue : r0_25 +# 226| r0_30(glval) = VariableAddress[z] : +# 226| r0_31(long) = Constant[7] : +# 226| mu0_32(long) = Store : &:r0_30, r0_31 +# 227| r0_33(float) = Constant[2.0] : +# 227| r0_34(glval) = VariableAddress[z] : +# 227| r0_35(long) = Load : &:r0_34, ~mu0_2 +# 227| r0_36(float) = Convert : r0_35 +# 227| r0_37(float) = Add : r0_36, r0_33 +# 227| r0_38(long) = Convert : r0_37 +# 227| mu0_39(long) = Store : &:r0_34, r0_38 +# 227| r0_40(glval) = CopyValue : r0_34 +# 228| v0_41(void) = NoOp : +# 213| v0_42(void) = ReturnVoid : +# 213| v0_43(void) = UnmodeledUse : mu* +# 213| v0_44(void) = ExitFunction : # 230| void UninitializedVariables() # 230| Block 0 @@ -1094,6 +1192,7 @@ ir.cpp: # 244| r2_1(int) = Load : &:r2_0, ~mu0_2 # 244| r2_2(glval) = VariableAddress[x] : # 244| mu2_3(int) = Store : &:r2_2, r2_1 +# 244| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 247| Block 3 @@ -1109,12 +1208,14 @@ ir.cpp: # 248| r4_0(int) = Constant[2] : # 248| r4_1(glval) = VariableAddress[x] : # 248| mu4_2(int) = Store : &:r4_1, r4_0 +# 248| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 250| Block 5 # 250| r5_0(int) = Constant[7] : # 250| r5_1(glval) = VariableAddress[x] : # 250| mu5_2(int) = Store : &:r5_1, r5_0 +# 250| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 251| Block 6 @@ -1142,6 +1243,7 @@ ir.cpp: # 255| r1_2(int) = Load : &:r1_1, ~mu0_2 # 255| r1_3(int) = Sub : r1_2, r1_0 # 255| mu1_4(int) = Store : &:r1_1, r1_3 +# 255| r1_5(glval) = CopyValue : r1_1 #-----| Goto (back edge) -> Block 3 # 257| Block 2 @@ -1174,11 +1276,12 @@ ir.cpp: # 261| r1_2(int) = Load : &:r1_1, ~mu0_2 # 261| r1_3(int) = Sub : r1_2, r1_0 # 261| mu1_4(int) = Store : &:r1_1, r1_3 -# 262| r1_5(glval) = VariableAddress[n] : -# 262| r1_6(int) = Load : &:r1_5, ~mu0_2 -# 262| r1_7(int) = Constant[0] : -# 262| r1_8(bool) = CompareGT : r1_6, r1_7 -# 262| v1_9(void) = ConditionalBranch : r1_8 +# 261| r1_5(glval) = CopyValue : r1_1 +# 262| r1_6(glval) = VariableAddress[n] : +# 262| r1_7(int) = Load : &:r1_6, ~mu0_2 +# 262| r1_8(int) = Constant[0] : +# 262| r1_9(bool) = CompareGT : r1_7, r1_8 +# 262| v1_10(void) = ConditionalBranch : r1_9 #-----| False -> Block 2 #-----| True (back edge) -> Block 1 @@ -1276,6 +1379,7 @@ ir.cpp: # 287| r2_3(int) = Load : &:r2_2, ~mu0_2 # 287| r2_4(int) = Add : r2_3, r2_1 # 287| mu2_5(int) = Store : &:r2_2, r2_4 +# 287| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 292| void For_InitCondition() @@ -1329,6 +1433,7 @@ ir.cpp: # 299| r2_3(int) = Load : &:r2_2, ~mu0_2 # 299| r2_4(int) = Add : r2_3, r2_1 # 299| mu2_5(int) = Store : &:r2_2, r2_4 +# 299| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 304| void For_ConditionUpdate() @@ -1357,6 +1462,7 @@ ir.cpp: # 306| r2_3(int) = Load : &:r2_2, ~mu0_2 # 306| r2_4(int) = Add : r2_3, r2_1 # 306| mu2_5(int) = Store : &:r2_2, r2_4 +# 306| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 309| Block 3 @@ -1391,6 +1497,7 @@ ir.cpp: # 312| r2_3(int) = Load : &:r2_2, ~mu0_2 # 312| r2_4(int) = Add : r2_3, r2_1 # 312| mu2_5(int) = Store : &:r2_2, r2_4 +# 312| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 315| Block 3 @@ -1424,6 +1531,7 @@ ir.cpp: # 318| r2_2(int) = Load : &:r2_1, ~mu0_2 # 318| r2_3(int) = Add : r2_2, r2_0 # 318| mu2_4(int) = Store : &:r2_1, r2_3 +# 318| r2_5(glval) = CopyValue : r2_1 #-----| Goto (back edge) -> Block 1 # 319| Block 3 @@ -1485,6 +1593,7 @@ ir.cpp: # 326| r4_3(int) = Load : &:r4_2, ~mu0_2 # 326| r4_4(int) = Add : r4_3, r4_1 # 326| mu4_5(int) = Store : &:r4_2, r4_4 +# 326| r4_6(glval) = CopyValue : r4_2 #-----| Goto (back edge) -> Block 1 # 331| Block 5 @@ -1545,16 +1654,18 @@ ir.cpp: # 342| r0_5(int) = Constant[1] : # 342| r0_6(glval) = VariableAddress[p] : # 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 -# 342| mu0_8(int) = Store : &:r0_7, r0_5 -# 343| r0_9(glval) = VariableAddress[#return] : -# 343| r0_10(glval) = VariableAddress[p] : -# 343| r0_11(int *) = Load : &:r0_10, ~mu0_2 -# 343| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 343| mu0_13(int) = Store : &:r0_9, r0_12 -# 341| r0_14(glval) = VariableAddress[#return] : -# 341| v0_15(void) = ReturnValue : &:r0_14, ~mu0_2 -# 341| v0_16(void) = UnmodeledUse : mu* -# 341| v0_17(void) = ExitFunction : +# 342| r0_8(glval) = CopyValue : r0_7 +# 342| mu0_9(int) = Store : &:r0_8, r0_5 +# 342| r0_10(glval) = CopyValue : r0_8 +# 343| r0_11(glval) = VariableAddress[#return] : +# 343| r0_12(glval) = VariableAddress[p] : +# 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 +# 343| r0_14(int) = Load : &:r0_13, ~mu0_2 +# 343| mu0_15(int) = Store : &:r0_11, r0_14 +# 341| r0_16(glval) = VariableAddress[#return] : +# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 341| v0_18(void) = UnmodeledUse : mu* +# 341| v0_19(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -1563,11 +1674,12 @@ ir.cpp: # 348| mu0_2(unknown) = UnmodeledDefinition : # 349| r0_3(glval) = VariableAddress[#return] : # 349| r0_4(glval) = VariableAddress[g] : -# 349| mu0_5(int *) = Store : &:r0_3, r0_4 -# 348| r0_6(glval) = VariableAddress[#return] : -# 348| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 348| v0_8(void) = UnmodeledUse : mu* -# 348| v0_9(void) = ExitFunction : +# 349| r0_5(int *) = CopyValue : r0_4 +# 349| mu0_6(int *) = Store : &:r0_3, r0_5 +# 348| r0_7(glval) = VariableAddress[#return] : +# 348| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 348| v0_9(void) = UnmodeledUse : mu* +# 348| v0_10(void) = ExitFunction : # 352| void Break(int) # 352| Block 0 @@ -1597,6 +1709,7 @@ ir.cpp: # 356| r3_2(int) = Load : &:r3_1, ~mu0_2 # 356| r3_3(int) = Sub : r3_2, r3_0 # 356| mu3_4(int) = Store : &:r3_1, r3_3 +# 356| r3_5(glval) = CopyValue : r3_1 #-----| Goto (back edge) -> Block 5 # 357| Block 4 @@ -1643,6 +1756,7 @@ ir.cpp: # 365| r3_2(int) = Load : &:r3_1, ~mu0_2 # 365| r3_3(int) = Sub : r3_2, r3_0 # 365| mu3_4(int) = Store : &:r3_1, r3_3 +# 365| r3_5(glval) = CopyValue : r3_1 #-----| Goto -> Block 4 # 361| Block 4 @@ -1717,11 +1831,12 @@ ir.cpp: # 381| r0_15(int) = Load : &:r0_14, ~mu0_2 # 381| r0_16(int) = Call : func:r0_11, 0:r0_13, 1:r0_15 # 381| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 381| mu0_18(int) = Store : &:r0_7, r0_16 -# 380| r0_19(glval) = VariableAddress[#return] : -# 380| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 380| v0_21(void) = UnmodeledUse : mu* -# 380| v0_22(void) = ExitFunction : +# 381| r0_18(int) = CopyValue : r0_16 +# 381| mu0_19(int) = Store : &:r0_7, r0_18 +# 380| r0_20(glval) = VariableAddress[#return] : +# 380| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 380| v0_22(void) = UnmodeledUse : mu* +# 380| v0_23(void) = ExitFunction : # 384| void Switch(int) # 384| Block 0 @@ -1746,6 +1861,7 @@ ir.cpp: # 387| r1_0(int) = Constant[1234] : # 387| r1_1(glval) = VariableAddress[y] : # 387| mu1_2(int) = Store : &:r1_1, r1_0 +# 387| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 389| Block 2 @@ -1753,7 +1869,8 @@ ir.cpp: # 390| r2_1(int) = Constant[-1] : # 390| r2_2(glval) = VariableAddress[y] : # 390| mu2_3(int) = Store : &:r2_2, r2_1 -# 391| v2_4(void) = NoOp : +# 390| r2_4(glval) = CopyValue : r2_2 +# 391| v2_5(void) = NoOp : #-----| Goto -> Block 9 # 393| Block 3 @@ -1765,7 +1882,8 @@ ir.cpp: # 395| r4_1(int) = Constant[1] : # 395| r4_2(glval) = VariableAddress[y] : # 395| mu4_3(int) = Store : &:r4_2, r4_1 -# 396| v4_4(void) = NoOp : +# 395| r4_4(glval) = CopyValue : r4_2 +# 396| v4_5(void) = NoOp : #-----| Goto -> Block 9 # 398| Block 5 @@ -1773,6 +1891,7 @@ ir.cpp: # 399| r5_1(int) = Constant[3] : # 399| r5_2(glval) = VariableAddress[y] : # 399| mu5_3(int) = Store : &:r5_2, r5_1 +# 399| r5_4(glval) = CopyValue : r5_2 #-----| Goto -> Block 6 # 400| Block 6 @@ -1780,7 +1899,8 @@ ir.cpp: # 401| r6_1(int) = Constant[4] : # 401| r6_2(glval) = VariableAddress[y] : # 401| mu6_3(int) = Store : &:r6_2, r6_1 -# 402| v6_4(void) = NoOp : +# 401| r6_4(glval) = CopyValue : r6_2 +# 402| v6_5(void) = NoOp : #-----| Goto -> Block 9 # 404| Block 7 @@ -1788,13 +1908,15 @@ ir.cpp: # 405| r7_1(int) = Constant[0] : # 405| r7_2(glval) = VariableAddress[y] : # 405| mu7_3(int) = Store : &:r7_2, r7_1 -# 406| v7_4(void) = NoOp : +# 405| r7_4(glval) = CopyValue : r7_2 +# 406| v7_5(void) = NoOp : #-----| Goto -> Block 9 # 408| Block 8 # 408| r8_0(int) = Constant[5678] : # 408| r8_1(glval) = VariableAddress[y] : # 408| mu8_2(int) = Store : &:r8_1, r8_0 +# 408| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 9 # 409| Block 9 @@ -1831,20 +1953,23 @@ ir.cpp: # 428| r0_6(glval) = VariableAddress[pt] : # 428| r0_7(glval) = FieldAddress[x] : r0_6 # 428| mu0_8(int) = Store : &:r0_7, r0_5 -# 429| r0_9(glval) = VariableAddress[pt] : -# 429| r0_10(glval) = FieldAddress[x] : r0_9 -# 429| r0_11(int) = Load : &:r0_10, ~mu0_2 -# 429| r0_12(glval) = VariableAddress[pt] : -# 429| r0_13(glval) = FieldAddress[y] : r0_12 -# 429| mu0_14(int) = Store : &:r0_13, r0_11 -# 430| r0_15(glval) = VariableAddress[p] : -# 430| r0_16(glval) = VariableAddress[pt] : -# 430| r0_17(glval) = FieldAddress[y] : r0_16 -# 430| mu0_18(int *) = Store : &:r0_15, r0_17 -# 431| v0_19(void) = NoOp : -# 426| v0_20(void) = ReturnVoid : -# 426| v0_21(void) = UnmodeledUse : mu* -# 426| v0_22(void) = ExitFunction : +# 428| r0_9(glval) = CopyValue : r0_7 +# 429| r0_10(glval) = VariableAddress[pt] : +# 429| r0_11(glval) = FieldAddress[x] : r0_10 +# 429| r0_12(int) = Load : &:r0_11, ~mu0_2 +# 429| r0_13(glval) = VariableAddress[pt] : +# 429| r0_14(glval) = FieldAddress[y] : r0_13 +# 429| mu0_15(int) = Store : &:r0_14, r0_12 +# 429| r0_16(glval) = CopyValue : r0_14 +# 430| r0_17(glval) = VariableAddress[p] : +# 430| r0_18(glval) = VariableAddress[pt] : +# 430| r0_19(glval) = FieldAddress[y] : r0_18 +# 430| r0_20(int *) = CopyValue : r0_19 +# 430| mu0_21(int *) = Store : &:r0_17, r0_20 +# 431| v0_22(void) = NoOp : +# 426| v0_23(void) = ReturnVoid : +# 426| v0_24(void) = UnmodeledUse : mu* +# 426| v0_25(void) = ExitFunction : # 433| void LogicalOr(bool, bool) # 433| Block 0 @@ -1874,6 +1999,7 @@ ir.cpp: # 436| r2_0(int) = Constant[7] : # 436| r2_1(glval) = VariableAddress[x] : # 436| mu2_2(int) = Store : &:r2_1, r2_0 +# 436| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 439| Block 3 @@ -1894,12 +2020,14 @@ ir.cpp: # 440| r5_0(int) = Constant[1] : # 440| r5_1(glval) = VariableAddress[x] : # 440| mu5_2(int) = Store : &:r5_1, r5_0 +# 440| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 443| Block 6 # 443| r6_0(int) = Constant[5] : # 443| r6_1(glval) = VariableAddress[x] : # 443| mu6_2(int) = Store : &:r6_1, r6_0 +# 443| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 445| Block 7 @@ -1936,6 +2064,7 @@ ir.cpp: # 450| r2_0(int) = Constant[7] : # 450| r2_1(glval) = VariableAddress[x] : # 450| mu2_2(int) = Store : &:r2_1, r2_0 +# 450| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 453| Block 3 @@ -1956,12 +2085,14 @@ ir.cpp: # 454| r5_0(int) = Constant[1] : # 454| r5_1(glval) = VariableAddress[x] : # 454| mu5_2(int) = Store : &:r5_1, r5_0 +# 454| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 457| Block 6 # 457| r6_0(int) = Constant[5] : # 457| r6_1(glval) = VariableAddress[x] : # 457| mu6_2(int) = Store : &:r6_1, r6_0 +# 457| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 459| Block 7 @@ -1991,6 +2122,7 @@ ir.cpp: # 464| r1_0(int) = Constant[1] : # 464| r1_1(glval) = VariableAddress[x] : # 464| mu1_2(int) = Store : &:r1_1, r1_0 +# 464| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 467| Block 2 @@ -2011,12 +2143,14 @@ ir.cpp: # 468| r4_0(int) = Constant[2] : # 468| r4_1(glval) = VariableAddress[x] : # 468| mu4_2(int) = Store : &:r4_1, r4_0 +# 468| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 471| Block 5 # 471| r5_0(int) = Constant[3] : # 471| r5_1(glval) = VariableAddress[x] : # 471| mu5_2(int) = Store : &:r5_1, r5_0 +# 471| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 473| Block 6 @@ -2060,9 +2194,10 @@ ir.cpp: # 478| r3_1(bool) = Load : &:r3_0, ~mu0_2 # 478| r3_2(glval) = VariableAddress[x] : # 478| mu3_3(bool) = Store : &:r3_2, r3_1 -# 479| r3_4(glval) = VariableAddress[a] : -# 479| r3_5(bool) = Load : &:r3_4, ~mu0_2 -# 479| v3_6(void) = ConditionalBranch : r3_5 +# 478| r3_4(glval) = CopyValue : r3_2 +# 479| r3_5(glval) = VariableAddress[a] : +# 479| r3_6(bool) = Load : &:r3_5, ~mu0_2 +# 479| v3_7(void) = ConditionalBranch : r3_6 #-----| False -> Block 9 #-----| True -> Block 8 @@ -2091,10 +2226,11 @@ ir.cpp: # 479| r7_2(bool) = LogicalNot : r7_1 # 479| r7_3(glval) = VariableAddress[x] : # 479| mu7_4(bool) = Store : &:r7_3, r7_2 -# 480| v7_5(void) = NoOp : -# 475| v7_6(void) = ReturnVoid : -# 475| v7_7(void) = UnmodeledUse : mu* -# 475| v7_8(void) = ExitFunction : +# 479| r7_5(glval) = CopyValue : r7_3 +# 480| v7_6(void) = NoOp : +# 475| v7_7(void) = ReturnVoid : +# 475| v7_8(void) = UnmodeledUse : mu* +# 475| v7_9(void) = ExitFunction : # 479| Block 8 # 479| r8_0(glval) = VariableAddress[#temp479:11] : @@ -2120,9 +2256,10 @@ ir.cpp: # 477| r11_1(bool) = Load : &:r11_0, ~mu0_2 # 477| r11_2(glval) = VariableAddress[x] : # 477| mu11_3(bool) = Store : &:r11_2, r11_1 -# 478| r11_4(glval) = VariableAddress[a] : -# 478| r11_5(bool) = Load : &:r11_4, ~mu0_2 -# 478| v11_6(void) = ConditionalBranch : r11_5 +# 477| r11_4(glval) = CopyValue : r11_2 +# 478| r11_5(glval) = VariableAddress[a] : +# 478| r11_6(bool) = Load : &:r11_5, ~mu0_2 +# 478| v11_7(void) = ConditionalBranch : r11_6 #-----| False -> Block 5 #-----| True -> Block 4 @@ -2195,10 +2332,11 @@ ir.cpp: # 489| r1_0(glval) = VariableAddress[#temp489:6] : # 489| r1_1(glval) = Load : &:r1_0, ~mu0_2 # 489| mu1_2(int) = Store : &:r1_1, r0_9 -# 490| v1_3(void) = NoOp : -# 486| v1_4(void) = ReturnVoid : -# 486| v1_5(void) = UnmodeledUse : mu* -# 486| v1_6(void) = ExitFunction : +# 489| r1_3(glval) = CopyValue : r1_1 +# 490| v1_4(void) = NoOp : +# 486| v1_5(void) = ReturnVoid : +# 486| v1_6(void) = UnmodeledUse : mu* +# 486| v1_7(void) = ExitFunction : # 489| Block 2 # 489| r2_0(glval) = VariableAddress[x] : @@ -2257,13 +2395,15 @@ ir.cpp: # 499| r0_9(int *) = Constant[0] : # 499| r0_10(glval) = VariableAddress[p] : # 499| mu0_11(int *) = Store : &:r0_10, r0_9 -# 500| r0_12(int *) = Constant[0] : -# 500| r0_13(glval) = VariableAddress[q] : -# 500| mu0_14(int *) = Store : &:r0_13, r0_12 -# 501| v0_15(void) = NoOp : -# 496| v0_16(void) = ReturnVoid : -# 496| v0_17(void) = UnmodeledUse : mu* -# 496| v0_18(void) = ExitFunction : +# 499| r0_12(glval) = CopyValue : r0_10 +# 500| r0_13(int *) = Constant[0] : +# 500| r0_14(glval) = VariableAddress[q] : +# 500| mu0_15(int *) = Store : &:r0_14, r0_13 +# 500| r0_16(glval) = CopyValue : r0_14 +# 501| v0_17(void) = NoOp : +# 496| v0_18(void) = ReturnVoid : +# 496| v0_19(void) = UnmodeledUse : mu* +# 496| v0_20(void) = ExitFunction : # 503| void InitList(int, float) # 503| Block 0 @@ -2491,7 +2631,8 @@ ir.cpp: # 540| r3_1(int) = Load : &:r3_0, ~mu0_2 # 540| r3_2(glval) = VariableAddress[y] : # 540| mu3_3(int) = Store : &:r3_2, r3_1 -# 541| v3_4(void) = NoOp : +# 540| r3_4(glval) = CopyValue : r3_2 +# 541| v3_5(void) = NoOp : #-----| Goto -> Block 1 # 543| int EarlyReturnValue(int, int) @@ -2687,18 +2828,27 @@ ir.cpp: # 591| r0_4(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : # 591| mu0_5(..(*)(..)) = Store : &:r0_3, r0_4 # 592| r0_6(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 592| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : -# 592| mu0_8(..(*)(..)) = Store : &:r0_7, r0_6 -# 593| r0_9(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : -# 593| r0_10(glval<..(*)(..)>) = VariableAddress[pfn] : -# 593| mu0_11(..(*)(..)) = Store : &:r0_10, r0_9 -# 594| r0_12(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 594| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : -# 594| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 -# 595| v0_15(void) = NoOp : -# 590| v0_16(void) = ReturnVoid : -# 590| v0_17(void) = UnmodeledUse : mu* -# 590| v0_18(void) = ExitFunction : +# 592| r0_7(..(*)(..)) = CopyValue : r0_6 +# 592| r0_8(glval<..(*)(..)>) = VariableAddress[pfn] : +# 592| mu0_9(..(*)(..)) = Store : &:r0_8, r0_7 +# 592| r0_10(glval<..(*)(..)>) = CopyValue : r0_8 +# 593| r0_11(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_12(..(*)(..)) = CopyValue : r0_11 +# 593| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : +# 593| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 +# 593| r0_15(glval<..(*)(..)>) = CopyValue : r0_13 +# 594| r0_16(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 594| r0_17(..(*)(..)) = CopyValue : r0_16 +# 594| r0_18(..(*)(..)) = CopyValue : r0_17 +# 594| r0_19(..(*)(..)) = CopyValue : r0_18 +# 594| r0_20(..(*)(..)) = CopyValue : r0_19 +# 594| r0_21(glval<..(*)(..)>) = VariableAddress[pfn] : +# 594| mu0_22(..(*)(..)) = Store : &:r0_21, r0_20 +# 594| r0_23(glval<..(*)(..)>) = CopyValue : r0_21 +# 595| v0_24(void) = NoOp : +# 590| v0_25(void) = ReturnVoid : +# 590| v0_26(void) = UnmodeledUse : mu* +# 590| v0_27(void) = ExitFunction : # 615| void DeclareObject() # 615| Block 0 @@ -2744,25 +2894,26 @@ ir.cpp: # 622| mu0_8(String) = InitializeParameter[s] : &:r0_7 # 623| r0_9(glval) = VariableAddress[r] : # 623| r0_10(String &) = Load : &:r0_9, ~mu0_2 -# 623| r0_11(glval) = Convert : r0_10 -# 623| r0_12(glval) = FunctionAddress[c_str] : -# 623| r0_13(char *) = Call : func:r0_12, this:r0_11 -# 623| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 624| r0_15(glval) = VariableAddress[p] : -# 624| r0_16(String *) = Load : &:r0_15, ~mu0_2 -# 624| r0_17(String *) = Convert : r0_16 -# 624| r0_18(glval) = FunctionAddress[c_str] : -# 624| r0_19(char *) = Call : func:r0_18, this:r0_17 -# 624| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 625| r0_21(glval) = VariableAddress[s] : -# 625| r0_22(glval) = Convert : r0_21 -# 625| r0_23(glval) = FunctionAddress[c_str] : -# 625| r0_24(char *) = Call : func:r0_23, this:r0_22 -# 625| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 626| v0_26(void) = NoOp : -# 622| v0_27(void) = ReturnVoid : -# 622| v0_28(void) = UnmodeledUse : mu* -# 622| v0_29(void) = ExitFunction : +# 623| r0_11(glval) = CopyValue : r0_10 +# 623| r0_12(glval) = Convert : r0_11 +# 623| r0_13(glval) = FunctionAddress[c_str] : +# 623| r0_14(char *) = Call : func:r0_13, this:r0_12 +# 623| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 624| r0_16(glval) = VariableAddress[p] : +# 624| r0_17(String *) = Load : &:r0_16, ~mu0_2 +# 624| r0_18(String *) = Convert : r0_17 +# 624| r0_19(glval) = FunctionAddress[c_str] : +# 624| r0_20(char *) = Call : func:r0_19, this:r0_18 +# 624| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 +# 625| r0_22(glval) = VariableAddress[s] : +# 625| r0_23(glval) = Convert : r0_22 +# 625| r0_24(glval) = FunctionAddress[c_str] : +# 625| r0_25(char *) = Call : func:r0_24, this:r0_23 +# 625| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 626| v0_27(void) = NoOp : +# 622| v0_28(void) = ReturnVoid : +# 622| v0_29(void) = UnmodeledUse : mu* +# 622| v0_30(void) = ExitFunction : # 630| int C::StaticMemberFunction(int) # 630| Block 0 @@ -2824,35 +2975,43 @@ ir.cpp: # 643| r0_5(C *) = CopyValue : r0_3 # 643| r0_6(glval) = FieldAddress[m_a] : r0_5 # 643| mu0_7(int) = Store : &:r0_6, r0_4 -# 644| r0_8(int) = Constant[1] : -# 644| r0_9(C *) = CopyValue : r0_3 -# 644| r0_10(glval) = FieldAddress[m_a] : r0_9 -# 644| mu0_11(int) = Store : &:r0_10, r0_8 -# 645| r0_12(int) = Constant[2] : -#-----| r0_13(C *) = CopyValue : r0_3 -# 645| r0_14(glval) = FieldAddress[m_a] : r0_13 -# 645| mu0_15(int) = Store : &:r0_14, r0_12 -# 646| r0_16(glval) = VariableAddress[x] : -# 646| mu0_17(int) = Uninitialized[x] : &:r0_16 -# 647| r0_18(C *) = CopyValue : r0_3 -# 647| r0_19(glval) = FieldAddress[m_a] : r0_18 -# 647| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 647| r0_21(glval) = VariableAddress[x] : -# 647| mu0_22(int) = Store : &:r0_21, r0_20 -# 648| r0_23(C *) = CopyValue : r0_3 -# 648| r0_24(glval) = FieldAddress[m_a] : r0_23 -# 648| r0_25(int) = Load : &:r0_24, ~mu0_2 -# 648| r0_26(glval) = VariableAddress[x] : -# 648| mu0_27(int) = Store : &:r0_26, r0_25 -#-----| r0_28(C *) = CopyValue : r0_3 -# 649| r0_29(glval) = FieldAddress[m_a] : r0_28 -# 649| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 649| r0_31(glval) = VariableAddress[x] : -# 649| mu0_32(int) = Store : &:r0_31, r0_30 -# 650| v0_33(void) = NoOp : -# 642| v0_34(void) = ReturnVoid : -# 642| v0_35(void) = UnmodeledUse : mu* -# 642| v0_36(void) = ExitFunction : +# 643| r0_8(glval) = CopyValue : r0_6 +# 644| r0_9(int) = Constant[1] : +# 644| r0_10(C *) = CopyValue : r0_3 +# 644| r0_11(glval) = CopyValue : r0_10 +# 644| r0_12(glval) = FieldAddress[m_a] : r0_11 +# 644| mu0_13(int) = Store : &:r0_12, r0_9 +# 644| r0_14(glval) = CopyValue : r0_12 +# 645| r0_15(int) = Constant[2] : +#-----| r0_16(C *) = CopyValue : r0_3 +# 645| r0_17(glval) = FieldAddress[m_a] : r0_16 +# 645| mu0_18(int) = Store : &:r0_17, r0_15 +# 645| r0_19(glval) = CopyValue : r0_17 +# 646| r0_20(glval) = VariableAddress[x] : +# 646| mu0_21(int) = Uninitialized[x] : &:r0_20 +# 647| r0_22(C *) = CopyValue : r0_3 +# 647| r0_23(glval) = FieldAddress[m_a] : r0_22 +# 647| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 647| r0_25(glval) = VariableAddress[x] : +# 647| mu0_26(int) = Store : &:r0_25, r0_24 +# 647| r0_27(glval) = CopyValue : r0_25 +# 648| r0_28(C *) = CopyValue : r0_3 +# 648| r0_29(glval) = CopyValue : r0_28 +# 648| r0_30(glval) = FieldAddress[m_a] : r0_29 +# 648| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 648| r0_32(glval) = VariableAddress[x] : +# 648| mu0_33(int) = Store : &:r0_32, r0_31 +# 648| r0_34(glval) = CopyValue : r0_32 +#-----| r0_35(C *) = CopyValue : r0_3 +# 649| r0_36(glval) = FieldAddress[m_a] : r0_35 +# 649| r0_37(int) = Load : &:r0_36, ~mu0_2 +# 649| r0_38(glval) = VariableAddress[x] : +# 649| mu0_39(int) = Store : &:r0_38, r0_37 +# 649| r0_40(glval) = CopyValue : r0_38 +# 650| v0_41(void) = NoOp : +# 642| v0_42(void) = ReturnVoid : +# 642| v0_43(void) = UnmodeledUse : mu* +# 642| v0_44(void) = ExitFunction : # 652| void C::MethodCalls() # 652| Block 0 @@ -2866,19 +3025,20 @@ ir.cpp: # 653| r0_7(int) = Call : func:r0_5, this:r0_4, 0:r0_6 # 653| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 # 654| r0_9(C *) = CopyValue : r0_3 -# 654| r0_10(glval) = FunctionAddress[InstanceMemberFunction] : -# 654| r0_11(int) = Constant[1] : -# 654| r0_12(int) = Call : func:r0_10, this:r0_9, 0:r0_11 -# 654| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(C *) = CopyValue : r0_3 -# 655| r0_15(glval) = FunctionAddress[InstanceMemberFunction] : -# 655| r0_16(int) = Constant[2] : -# 655| r0_17(int) = Call : func:r0_15, this:r0_14, 0:r0_16 -# 655| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 -# 656| v0_19(void) = NoOp : -# 652| v0_20(void) = ReturnVoid : -# 652| v0_21(void) = UnmodeledUse : mu* -# 652| v0_22(void) = ExitFunction : +# 654| r0_10(glval) = CopyValue : r0_9 +# 654| r0_11(glval) = FunctionAddress[InstanceMemberFunction] : +# 654| r0_12(int) = Constant[1] : +# 654| r0_13(int) = Call : func:r0_11, this:r0_10, 0:r0_12 +# 654| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_15(C *) = CopyValue : r0_3 +# 655| r0_16(glval) = FunctionAddress[InstanceMemberFunction] : +# 655| r0_17(int) = Constant[2] : +# 655| r0_18(int) = Call : func:r0_16, this:r0_15, 0:r0_17 +# 655| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 656| v0_20(void) = NoOp : +# 652| v0_21(void) = ReturnVoid : +# 652| v0_22(void) = UnmodeledUse : mu* +# 652| v0_23(void) = ExitFunction : # 658| void C::C() # 658| Block 0 @@ -2934,11 +3094,12 @@ ir.cpp: # 679| mu0_2(unknown) = UnmodeledDefinition : # 680| r0_3(glval) = VariableAddress[#return] : # 680| r0_4(glval) = VariableAddress[g] : -# 680| mu0_5(int &) = Store : &:r0_3, r0_4 -# 679| r0_6(glval) = VariableAddress[#return] : -# 679| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 679| v0_8(void) = UnmodeledUse : mu* -# 679| v0_9(void) = ExitFunction : +# 680| r0_5(int &) = CopyValue : r0_4 +# 680| mu0_6(int &) = Store : &:r0_3, r0_5 +# 679| r0_7(glval) = VariableAddress[#return] : +# 679| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 679| v0_9(void) = UnmodeledUse : mu* +# 679| v0_10(void) = ExitFunction : # 685| void InitReference(int) # 685| Block 0 @@ -2949,44 +3110,51 @@ ir.cpp: # 685| mu0_4(int) = InitializeParameter[x] : &:r0_3 # 686| r0_5(glval) = VariableAddress[r] : # 686| r0_6(glval) = VariableAddress[x] : -# 686| mu0_7(int &) = Store : &:r0_5, r0_6 -# 687| r0_8(glval) = VariableAddress[r2] : -# 687| r0_9(glval) = VariableAddress[r] : -# 687| r0_10(int &) = Load : &:r0_9, ~mu0_2 -# 687| mu0_11(int &) = Store : &:r0_8, r0_10 -# 688| r0_12(glval) = VariableAddress[r3] : -# 688| r0_13(glval) = FunctionAddress[ReturnReference] : -# 688| r0_14(String &) = Call : func:r0_13 -# 688| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 688| r0_16(glval) = Convert : r0_14 -# 688| mu0_17(String &) = Store : &:r0_12, r0_16 -# 689| v0_18(void) = NoOp : -# 685| v0_19(void) = ReturnVoid : -# 685| v0_20(void) = UnmodeledUse : mu* -# 685| v0_21(void) = ExitFunction : +# 686| r0_7(int &) = CopyValue : r0_6 +# 686| mu0_8(int &) = Store : &:r0_5, r0_7 +# 687| r0_9(glval) = VariableAddress[r2] : +# 687| r0_10(glval) = VariableAddress[r] : +# 687| r0_11(int &) = Load : &:r0_10, ~mu0_2 +# 687| r0_12(glval) = CopyValue : r0_11 +# 687| r0_13(int &) = CopyValue : r0_12 +# 687| mu0_14(int &) = Store : &:r0_9, r0_13 +# 688| r0_15(glval) = VariableAddress[r3] : +# 688| r0_16(glval) = FunctionAddress[ReturnReference] : +# 688| r0_17(String &) = Call : func:r0_16 +# 688| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 688| r0_19(glval) = CopyValue : r0_17 +# 688| r0_20(glval) = Convert : r0_19 +# 688| r0_21(String &) = CopyValue : r0_20 +# 688| mu0_22(String &) = Store : &:r0_15, r0_21 +# 689| v0_23(void) = NoOp : +# 685| v0_24(void) = ReturnVoid : +# 685| v0_25(void) = UnmodeledUse : mu* +# 685| v0_26(void) = ExitFunction : # 691| void ArrayReferences() # 691| Block 0 -# 691| v0_0(void) = EnterFunction : -# 691| mu0_1(unknown) = AliasedDefinition : -# 691| mu0_2(unknown) = UnmodeledDefinition : -# 692| r0_3(glval) = VariableAddress[a] : -# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 -# 693| r0_5(glval) = VariableAddress[ra] : -# 693| r0_6(glval) = VariableAddress[a] : -# 693| mu0_7(int(&)[10]) = Store : &:r0_5, r0_6 -# 694| r0_8(glval) = VariableAddress[x] : -# 694| r0_9(glval) = VariableAddress[ra] : -# 694| r0_10(int(&)[10]) = Load : &:r0_9, ~mu0_2 -# 694| r0_11(int *) = Convert : r0_10 -# 694| r0_12(int) = Constant[5] : -# 694| r0_13(glval) = PointerAdd[4] : r0_11, r0_12 -# 694| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 694| mu0_15(int) = Store : &:r0_8, r0_14 -# 695| v0_16(void) = NoOp : -# 691| v0_17(void) = ReturnVoid : -# 691| v0_18(void) = UnmodeledUse : mu* -# 691| v0_19(void) = ExitFunction : +# 691| v0_0(void) = EnterFunction : +# 691| mu0_1(unknown) = AliasedDefinition : +# 691| mu0_2(unknown) = UnmodeledDefinition : +# 692| r0_3(glval) = VariableAddress[a] : +# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 +# 693| r0_5(glval) = VariableAddress[ra] : +# 693| r0_6(glval) = VariableAddress[a] : +# 693| r0_7(int(&)[10]) = CopyValue : r0_6 +# 693| mu0_8(int(&)[10]) = Store : &:r0_5, r0_7 +# 694| r0_9(glval) = VariableAddress[x] : +# 694| r0_10(glval) = VariableAddress[ra] : +# 694| r0_11(int(&)[10]) = Load : &:r0_10, ~mu0_2 +# 694| r0_12(glval) = CopyValue : r0_11 +# 694| r0_13(int *) = Convert : r0_12 +# 694| r0_14(int) = Constant[5] : +# 694| r0_15(glval) = PointerAdd[4] : r0_13, r0_14 +# 694| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 694| mu0_17(int) = Store : &:r0_9, r0_16 +# 695| v0_18(void) = NoOp : +# 691| v0_19(void) = ReturnVoid : +# 691| v0_20(void) = UnmodeledUse : mu* +# 691| v0_21(void) = ExitFunction : # 697| void FunctionReferences() # 697| Block 0 @@ -2995,20 +3163,23 @@ ir.cpp: # 697| mu0_2(unknown) = UnmodeledDefinition : # 698| r0_3(glval<..(&)(..)>) = VariableAddress[rfn] : # 698| r0_4(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 698| mu0_5(..(&)(..)) = Store : &:r0_3, r0_4 -# 699| r0_6(glval<..(*)(..)>) = VariableAddress[pfn] : -# 699| r0_7(glval<..(&)(..)>) = VariableAddress[rfn] : -# 699| r0_8(..(&)(..)) = Load : &:r0_7, ~mu0_2 -# 699| mu0_9(..(*)(..)) = Store : &:r0_6, r0_8 -# 700| r0_10(glval<..(&)(..)>) = VariableAddress[rfn] : -# 700| r0_11(..(&)(..)) = Load : &:r0_10, ~mu0_2 -# 700| r0_12(int) = Constant[5] : -# 700| r0_13(int) = Call : func:r0_11, 0:r0_12 -# 700| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 701| v0_15(void) = NoOp : -# 697| v0_16(void) = ReturnVoid : -# 697| v0_17(void) = UnmodeledUse : mu* -# 697| v0_18(void) = ExitFunction : +# 698| r0_5(..(&)(..)) = CopyValue : r0_4 +# 698| mu0_6(..(&)(..)) = Store : &:r0_3, r0_5 +# 699| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : +# 699| r0_8(glval<..(&)(..)>) = VariableAddress[rfn] : +# 699| r0_9(..(&)(..)) = Load : &:r0_8, ~mu0_2 +# 699| r0_10(..(*)(..)) = CopyValue : r0_9 +# 699| mu0_11(..(*)(..)) = Store : &:r0_7, r0_10 +# 700| r0_12(glval<..(&)(..)>) = VariableAddress[rfn] : +# 700| r0_13(..(&)(..)) = Load : &:r0_12, ~mu0_2 +# 700| r0_14(..(*)(..)) = CopyValue : r0_13 +# 700| r0_15(int) = Constant[5] : +# 700| r0_16(int) = Call : func:r0_14, 0:r0_15 +# 700| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 701| v0_18(void) = NoOp : +# 697| v0_19(void) = ReturnVoid : +# 697| v0_20(void) = UnmodeledUse : mu* +# 697| v0_21(void) = ExitFunction : # 704| int min(int, int) # 704| Block 0 @@ -3166,6 +3337,7 @@ ir.cpp: # 731| r6_4(int) = Load : &:r6_3, ~mu0_2 # 731| r6_5(glval) = VariableAddress[x] : # 731| mu6_6(int) = Store : &:r6_5, r6_4 +# 731| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 731| Block 7 @@ -3182,6 +3354,7 @@ ir.cpp: # 733| r8_0(int) = Constant[7] : # 733| r8_1(glval) = VariableAddress[x] : # 733| mu8_2(int) = Store : &:r8_1, r8_0 +# 733| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 14 # 735| Block 9 @@ -3232,19 +3405,25 @@ ir.cpp: #-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 #-----| r0_6(Base *) = CopyValue : r0_3 #-----| r0_7(glval) = FieldAddress[base_s] : r0_6 -# 745| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Base &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = FieldAddress[base_s] : r0_10 -# 745| r0_12(String &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 745| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(glval) = VariableAddress[#return] : -#-----| r0_15(Base *) = CopyValue : r0_3 -#-----| mu0_16(Base &) = Store : &:r0_14, r0_15 -# 745| r0_17(glval) = VariableAddress[#return] : -# 745| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 -# 745| v0_19(void) = UnmodeledUse : mu* -# 745| v0_20(void) = ExitFunction : +#-----| r0_8(String *) = CopyValue : r0_7 +# 745| r0_9(glval) = FunctionAddress[operator=] : +#-----| r0_10(glval) = VariableAddress[p#0] : +#-----| r0_11(Base &) = Load : &:r0_10, ~mu0_2 +#-----| r0_12(glval) = CopyValue : r0_11 +#-----| r0_13(glval) = FieldAddress[base_s] : r0_12 +#-----| r0_14(String &) = CopyValue : r0_13 +# 745| r0_15(String &) = Call : func:r0_9, this:r0_8, 0:r0_14 +# 745| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_17(glval) = CopyValue : r0_15 +#-----| r0_18(glval) = VariableAddress[#return] : +#-----| r0_19(Base *) = CopyValue : r0_3 +#-----| r0_20(glval) = CopyValue : r0_19 +#-----| r0_21(Base &) = CopyValue : r0_20 +#-----| mu0_22(Base &) = Store : &:r0_18, r0_21 +# 745| r0_23(glval) = VariableAddress[#return] : +# 745| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 +# 745| v0_25(void) = UnmodeledUse : mu* +# 745| v0_26(void) = ExitFunction : # 745| void Base::Base(Base const&) # 745| Block 0 @@ -3306,24 +3485,35 @@ ir.cpp: # 754| r0_8(glval) = FunctionAddress[operator=] : #-----| r0_9(glval) = VariableAddress[p#0] : #-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Base *) = ConvertToBase[Middle : Base] : r0_10 -# 754| r0_12(Base &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 754| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(Middle *) = CopyValue : r0_3 -#-----| r0_15(glval) = FieldAddress[middle_s] : r0_14 -# 754| r0_16(glval) = FunctionAddress[operator=] : -#-----| r0_17(glval) = VariableAddress[p#0] : -#-----| r0_18(Middle &) = Load : &:r0_17, ~mu0_2 -#-----| r0_19(glval) = FieldAddress[middle_s] : r0_18 -# 754| r0_20(String &) = Call : func:r0_16, this:r0_15, 0:r0_19 -# 754| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_22(glval) = VariableAddress[#return] : -#-----| r0_23(Middle *) = CopyValue : r0_3 -#-----| mu0_24(Middle &) = Store : &:r0_22, r0_23 -# 754| r0_25(glval) = VariableAddress[#return] : -# 754| v0_26(void) = ReturnValue : &:r0_25, ~mu0_2 -# 754| v0_27(void) = UnmodeledUse : mu* -# 754| v0_28(void) = ExitFunction : +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Middle *) = CopyValue : r0_11 +#-----| r0_13(Base *) = ConvertToBase[Middle : Base] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Base &) = CopyValue : r0_14 +# 754| r0_16(Base &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 754| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_18(glval) = CopyValue : r0_16 +#-----| r0_19(Middle *) = CopyValue : r0_3 +#-----| r0_20(glval) = FieldAddress[middle_s] : r0_19 +#-----| r0_21(String *) = CopyValue : r0_20 +# 754| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Middle &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = CopyValue : r0_24 +#-----| r0_26(glval) = FieldAddress[middle_s] : r0_25 +#-----| r0_27(String &) = CopyValue : r0_26 +# 754| r0_28(String &) = Call : func:r0_22, this:r0_21, 0:r0_27 +# 754| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_30(glval) = CopyValue : r0_28 +#-----| r0_31(glval) = VariableAddress[#return] : +#-----| r0_32(Middle *) = CopyValue : r0_3 +#-----| r0_33(glval) = CopyValue : r0_32 +#-----| r0_34(Middle &) = CopyValue : r0_33 +#-----| mu0_35(Middle &) = Store : &:r0_31, r0_34 +# 754| r0_36(glval) = VariableAddress[#return] : +# 754| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 754| v0_38(void) = UnmodeledUse : mu* +# 754| v0_39(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 @@ -3376,24 +3566,35 @@ ir.cpp: # 763| r0_8(glval) = FunctionAddress[operator=] : #-----| r0_9(glval) = VariableAddress[p#0] : #-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Middle *) = ConvertToBase[Derived : Middle] : r0_10 -# 763| r0_12(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 763| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(Derived *) = CopyValue : r0_3 -#-----| r0_15(glval) = FieldAddress[derived_s] : r0_14 -# 763| r0_16(glval) = FunctionAddress[operator=] : -#-----| r0_17(glval) = VariableAddress[p#0] : -#-----| r0_18(Derived &) = Load : &:r0_17, ~mu0_2 -#-----| r0_19(glval) = FieldAddress[derived_s] : r0_18 -# 763| r0_20(String &) = Call : func:r0_16, this:r0_15, 0:r0_19 -# 763| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_22(glval) = VariableAddress[#return] : -#-----| r0_23(Derived *) = CopyValue : r0_3 -#-----| mu0_24(Derived &) = Store : &:r0_22, r0_23 -# 763| r0_25(glval) = VariableAddress[#return] : -# 763| v0_26(void) = ReturnValue : &:r0_25, ~mu0_2 -# 763| v0_27(void) = UnmodeledUse : mu* -# 763| v0_28(void) = ExitFunction : +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Derived *) = CopyValue : r0_11 +#-----| r0_13(Middle *) = ConvertToBase[Derived : Middle] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Middle &) = CopyValue : r0_14 +# 763| r0_16(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 763| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_18(glval) = CopyValue : r0_16 +#-----| r0_19(Derived *) = CopyValue : r0_3 +#-----| r0_20(glval) = FieldAddress[derived_s] : r0_19 +#-----| r0_21(String *) = CopyValue : r0_20 +# 763| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Derived &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = CopyValue : r0_24 +#-----| r0_26(glval) = FieldAddress[derived_s] : r0_25 +#-----| r0_27(String &) = CopyValue : r0_26 +# 763| r0_28(String &) = Call : func:r0_22, this:r0_21, 0:r0_27 +# 763| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_30(glval) = CopyValue : r0_28 +#-----| r0_31(glval) = VariableAddress[#return] : +#-----| r0_32(Derived *) = CopyValue : r0_3 +#-----| r0_33(glval) = CopyValue : r0_32 +#-----| r0_34(Derived &) = CopyValue : r0_33 +#-----| mu0_35(Derived &) = Store : &:r0_31, r0_34 +# 763| r0_36(glval) = VariableAddress[#return] : +# 763| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 763| v0_38(void) = UnmodeledUse : mu* +# 763| v0_39(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 @@ -3582,193 +3783,236 @@ ir.cpp: # 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 # 804| r0_15(glval) = VariableAddress[pb] : # 804| r0_16(glval) = VariableAddress[b] : -# 804| mu0_17(Base *) = Store : &:r0_15, r0_16 -# 805| r0_18(glval) = VariableAddress[pm] : -# 805| r0_19(glval) = VariableAddress[m] : -# 805| mu0_20(Middle *) = Store : &:r0_18, r0_19 -# 806| r0_21(glval) = VariableAddress[pd] : -# 806| r0_22(glval) = VariableAddress[d] : -# 806| mu0_23(Derived *) = Store : &:r0_21, r0_22 -# 808| r0_24(glval) = VariableAddress[b] : -# 808| r0_25(glval) = FunctionAddress[operator=] : -# 808| r0_26(glval) = VariableAddress[m] : -# 808| r0_27(glval) = ConvertToBase[Middle : Base] : r0_26 -# 808| r0_28(Base &) = Call : func:r0_25, this:r0_24, 0:r0_27 -# 808| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 809| r0_30(glval) = VariableAddress[b] : -# 809| r0_31(glval) = FunctionAddress[operator=] : -# 809| r0_32(glval) = FunctionAddress[Base] : -# 809| r0_33(glval) = VariableAddress[m] : -# 809| r0_34(glval) = ConvertToBase[Middle : Base] : r0_33 -# 809| v0_35(void) = Call : func:r0_32, 0:r0_34 -# 809| mu0_36(unknown) = ^CallSideEffect : ~mu0_2 -# 809| r0_37(glval) = Convert : v0_35 -# 809| r0_38(Base &) = Call : func:r0_31, this:r0_30, 0:r0_37 -# 809| mu0_39(unknown) = ^CallSideEffect : ~mu0_2 -# 810| r0_40(glval) = VariableAddress[b] : -# 810| r0_41(glval) = FunctionAddress[operator=] : -# 810| r0_42(glval) = FunctionAddress[Base] : -# 810| r0_43(glval) = VariableAddress[m] : -# 810| r0_44(glval) = ConvertToBase[Middle : Base] : r0_43 -# 810| v0_45(void) = Call : func:r0_42, 0:r0_44 -# 810| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 -# 810| r0_47(glval) = Convert : v0_45 -# 810| r0_48(Base &) = Call : func:r0_41, this:r0_40, 0:r0_47 -# 810| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 -# 811| r0_50(glval) = VariableAddress[pm] : -# 811| r0_51(Middle *) = Load : &:r0_50, ~mu0_2 -# 811| r0_52(Base *) = ConvertToBase[Middle : Base] : r0_51 -# 811| r0_53(glval) = VariableAddress[pb] : -# 811| mu0_54(Base *) = Store : &:r0_53, r0_52 -# 812| r0_55(glval) = VariableAddress[pm] : -# 812| r0_56(Middle *) = Load : &:r0_55, ~mu0_2 -# 812| r0_57(Base *) = ConvertToBase[Middle : Base] : r0_56 -# 812| r0_58(glval) = VariableAddress[pb] : -# 812| mu0_59(Base *) = Store : &:r0_58, r0_57 -# 813| r0_60(glval) = VariableAddress[pm] : -# 813| r0_61(Middle *) = Load : &:r0_60, ~mu0_2 -# 813| r0_62(Base *) = ConvertToBase[Middle : Base] : r0_61 -# 813| r0_63(glval) = VariableAddress[pb] : -# 813| mu0_64(Base *) = Store : &:r0_63, r0_62 -# 814| r0_65(glval) = VariableAddress[pm] : -# 814| r0_66(Middle *) = Load : &:r0_65, ~mu0_2 -# 814| r0_67(Base *) = Convert : r0_66 -# 814| r0_68(glval) = VariableAddress[pb] : -# 814| mu0_69(Base *) = Store : &:r0_68, r0_67 -# 816| r0_70(glval) = VariableAddress[m] : -# 816| r0_71(glval) = FunctionAddress[operator=] : -# 816| r0_72(glval) = VariableAddress[b] : -# 816| r0_73(glval) = ConvertToDerived[Middle : Base] : r0_72 -# 816| r0_74(glval) = Convert : r0_73 -# 816| r0_75(Middle &) = Call : func:r0_71, this:r0_70, 0:r0_74 -# 816| mu0_76(unknown) = ^CallSideEffect : ~mu0_2 -# 817| r0_77(glval) = VariableAddress[m] : -# 817| r0_78(glval) = FunctionAddress[operator=] : -# 817| r0_79(glval) = VariableAddress[b] : -# 817| r0_80(glval) = ConvertToDerived[Middle : Base] : r0_79 -# 817| r0_81(glval) = Convert : r0_80 -# 817| r0_82(Middle &) = Call : func:r0_78, this:r0_77, 0:r0_81 -# 817| mu0_83(unknown) = ^CallSideEffect : ~mu0_2 -# 818| r0_84(glval) = VariableAddress[pb] : -# 818| r0_85(Base *) = Load : &:r0_84, ~mu0_2 -# 818| r0_86(Middle *) = ConvertToDerived[Middle : Base] : r0_85 -# 818| r0_87(glval) = VariableAddress[pm] : -# 818| mu0_88(Middle *) = Store : &:r0_87, r0_86 -# 819| r0_89(glval) = VariableAddress[pb] : -# 819| r0_90(Base *) = Load : &:r0_89, ~mu0_2 -# 819| r0_91(Middle *) = ConvertToDerived[Middle : Base] : r0_90 -# 819| r0_92(glval) = VariableAddress[pm] : -# 819| mu0_93(Middle *) = Store : &:r0_92, r0_91 -# 820| r0_94(glval) = VariableAddress[pb] : -# 820| r0_95(Base *) = Load : &:r0_94, ~mu0_2 -# 820| r0_96(Middle *) = Convert : r0_95 -# 820| r0_97(glval) = VariableAddress[pm] : -# 820| mu0_98(Middle *) = Store : &:r0_97, r0_96 -# 822| r0_99(glval) = VariableAddress[b] : -# 822| r0_100(glval) = FunctionAddress[operator=] : -# 822| r0_101(glval) = VariableAddress[d] : -# 822| r0_102(glval) = ConvertToBase[Derived : Middle] : r0_101 -# 822| r0_103(glval) = ConvertToBase[Middle : Base] : r0_102 -# 822| r0_104(Base &) = Call : func:r0_100, this:r0_99, 0:r0_103 -# 822| mu0_105(unknown) = ^CallSideEffect : ~mu0_2 -# 823| r0_106(glval) = VariableAddress[b] : -# 823| r0_107(glval) = FunctionAddress[operator=] : -# 823| r0_108(glval) = FunctionAddress[Base] : -# 823| r0_109(glval) = VariableAddress[d] : -# 823| r0_110(glval) = ConvertToBase[Derived : Middle] : r0_109 -# 823| r0_111(glval) = ConvertToBase[Middle : Base] : r0_110 -# 823| v0_112(void) = Call : func:r0_108, 0:r0_111 -# 823| mu0_113(unknown) = ^CallSideEffect : ~mu0_2 -# 823| r0_114(glval) = Convert : v0_112 -# 823| r0_115(Base &) = Call : func:r0_107, this:r0_106, 0:r0_114 -# 823| mu0_116(unknown) = ^CallSideEffect : ~mu0_2 -# 824| r0_117(glval) = VariableAddress[b] : -# 824| r0_118(glval) = FunctionAddress[operator=] : -# 824| r0_119(glval) = FunctionAddress[Base] : -# 824| r0_120(glval) = VariableAddress[d] : -# 824| r0_121(glval) = ConvertToBase[Derived : Middle] : r0_120 -# 824| r0_122(glval) = ConvertToBase[Middle : Base] : r0_121 -# 824| v0_123(void) = Call : func:r0_119, 0:r0_122 -# 824| mu0_124(unknown) = ^CallSideEffect : ~mu0_2 -# 824| r0_125(glval) = Convert : v0_123 -# 824| r0_126(Base &) = Call : func:r0_118, this:r0_117, 0:r0_125 -# 824| mu0_127(unknown) = ^CallSideEffect : ~mu0_2 -# 825| r0_128(glval) = VariableAddress[pd] : -# 825| r0_129(Derived *) = Load : &:r0_128, ~mu0_2 -# 825| r0_130(Middle *) = ConvertToBase[Derived : Middle] : r0_129 -# 825| r0_131(Base *) = ConvertToBase[Middle : Base] : r0_130 -# 825| r0_132(glval) = VariableAddress[pb] : -# 825| mu0_133(Base *) = Store : &:r0_132, r0_131 -# 826| r0_134(glval) = VariableAddress[pd] : -# 826| r0_135(Derived *) = Load : &:r0_134, ~mu0_2 -# 826| r0_136(Middle *) = ConvertToBase[Derived : Middle] : r0_135 -# 826| r0_137(Base *) = ConvertToBase[Middle : Base] : r0_136 -# 826| r0_138(glval) = VariableAddress[pb] : -# 826| mu0_139(Base *) = Store : &:r0_138, r0_137 -# 827| r0_140(glval) = VariableAddress[pd] : -# 827| r0_141(Derived *) = Load : &:r0_140, ~mu0_2 -# 827| r0_142(Middle *) = ConvertToBase[Derived : Middle] : r0_141 -# 827| r0_143(Base *) = ConvertToBase[Middle : Base] : r0_142 -# 827| r0_144(glval) = VariableAddress[pb] : -# 827| mu0_145(Base *) = Store : &:r0_144, r0_143 -# 828| r0_146(glval) = VariableAddress[pd] : -# 828| r0_147(Derived *) = Load : &:r0_146, ~mu0_2 -# 828| r0_148(Base *) = Convert : r0_147 -# 828| r0_149(glval) = VariableAddress[pb] : -# 828| mu0_150(Base *) = Store : &:r0_149, r0_148 -# 830| r0_151(glval) = VariableAddress[d] : -# 830| r0_152(glval) = FunctionAddress[operator=] : -# 830| r0_153(glval) = VariableAddress[b] : -# 830| r0_154(glval) = ConvertToDerived[Middle : Base] : r0_153 -# 830| r0_155(glval) = ConvertToDerived[Derived : Middle] : r0_154 -# 830| r0_156(glval) = Convert : r0_155 -# 830| r0_157(Derived &) = Call : func:r0_152, this:r0_151, 0:r0_156 -# 830| mu0_158(unknown) = ^CallSideEffect : ~mu0_2 -# 831| r0_159(glval) = VariableAddress[d] : -# 831| r0_160(glval) = FunctionAddress[operator=] : -# 831| r0_161(glval) = VariableAddress[b] : -# 831| r0_162(glval) = ConvertToDerived[Middle : Base] : r0_161 -# 831| r0_163(glval) = ConvertToDerived[Derived : Middle] : r0_162 -# 831| r0_164(glval) = Convert : r0_163 -# 831| r0_165(Derived &) = Call : func:r0_160, this:r0_159, 0:r0_164 -# 831| mu0_166(unknown) = ^CallSideEffect : ~mu0_2 -# 832| r0_167(glval) = VariableAddress[pb] : -# 832| r0_168(Base *) = Load : &:r0_167, ~mu0_2 -# 832| r0_169(Middle *) = ConvertToDerived[Middle : Base] : r0_168 -# 832| r0_170(Derived *) = ConvertToDerived[Derived : Middle] : r0_169 -# 832| r0_171(glval) = VariableAddress[pd] : -# 832| mu0_172(Derived *) = Store : &:r0_171, r0_170 -# 833| r0_173(glval) = VariableAddress[pb] : -# 833| r0_174(Base *) = Load : &:r0_173, ~mu0_2 -# 833| r0_175(Middle *) = ConvertToDerived[Middle : Base] : r0_174 -# 833| r0_176(Derived *) = ConvertToDerived[Derived : Middle] : r0_175 -# 833| r0_177(glval) = VariableAddress[pd] : -# 833| mu0_178(Derived *) = Store : &:r0_177, r0_176 -# 834| r0_179(glval) = VariableAddress[pb] : -# 834| r0_180(Base *) = Load : &:r0_179, ~mu0_2 -# 834| r0_181(Derived *) = Convert : r0_180 -# 834| r0_182(glval) = VariableAddress[pd] : -# 834| mu0_183(Derived *) = Store : &:r0_182, r0_181 -# 836| r0_184(glval) = VariableAddress[pmv] : -# 836| r0_185(MiddleVB1 *) = Constant[0] : -# 836| mu0_186(MiddleVB1 *) = Store : &:r0_184, r0_185 -# 837| r0_187(glval) = VariableAddress[pdv] : -# 837| r0_188(DerivedVB *) = Constant[0] : -# 837| mu0_189(DerivedVB *) = Store : &:r0_187, r0_188 -# 838| r0_190(glval) = VariableAddress[pmv] : -# 838| r0_191(MiddleVB1 *) = Load : &:r0_190, ~mu0_2 -# 838| r0_192(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_191 -# 838| r0_193(glval) = VariableAddress[pb] : -# 838| mu0_194(Base *) = Store : &:r0_193, r0_192 -# 839| r0_195(glval) = VariableAddress[pdv] : -# 839| r0_196(DerivedVB *) = Load : &:r0_195, ~mu0_2 -# 839| r0_197(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_196 -# 839| r0_198(glval) = VariableAddress[pb] : -# 839| mu0_199(Base *) = Store : &:r0_198, r0_197 -# 840| v0_200(void) = NoOp : -# 799| v0_201(void) = ReturnVoid : -# 799| v0_202(void) = UnmodeledUse : mu* -# 799| v0_203(void) = ExitFunction : +# 804| r0_17(Base *) = CopyValue : r0_16 +# 804| mu0_18(Base *) = Store : &:r0_15, r0_17 +# 805| r0_19(glval) = VariableAddress[pm] : +# 805| r0_20(glval) = VariableAddress[m] : +# 805| r0_21(Middle *) = CopyValue : r0_20 +# 805| mu0_22(Middle *) = Store : &:r0_19, r0_21 +# 806| r0_23(glval) = VariableAddress[pd] : +# 806| r0_24(glval) = VariableAddress[d] : +# 806| r0_25(Derived *) = CopyValue : r0_24 +# 806| mu0_26(Derived *) = Store : &:r0_23, r0_25 +# 808| r0_27(glval) = VariableAddress[b] : +# 808| r0_28(glval) = FunctionAddress[operator=] : +# 808| r0_29(glval) = VariableAddress[m] : +# 808| r0_30(glval) = ConvertToBase[Middle : Base] : r0_29 +# 808| r0_31(Base &) = CopyValue : r0_30 +# 808| r0_32(Base &) = Call : func:r0_28, this:r0_27, 0:r0_31 +# 808| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 808| r0_34(glval) = CopyValue : r0_32 +# 809| r0_35(glval) = VariableAddress[b] : +# 809| r0_36(glval) = FunctionAddress[operator=] : +# 809| r0_37(glval) = FunctionAddress[Base] : +# 809| r0_38(glval) = VariableAddress[m] : +# 809| r0_39(glval) = ConvertToBase[Middle : Base] : r0_38 +# 809| r0_40(Base &) = CopyValue : r0_39 +# 809| v0_41(void) = Call : func:r0_37, 0:r0_40 +# 809| mu0_42(unknown) = ^CallSideEffect : ~mu0_2 +# 809| r0_43(glval) = Convert : v0_41 +# 809| r0_44(Base &) = CopyValue : r0_43 +# 809| r0_45(Base &) = Call : func:r0_36, this:r0_35, 0:r0_44 +# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 +# 809| r0_47(glval) = CopyValue : r0_45 +# 810| r0_48(glval) = VariableAddress[b] : +# 810| r0_49(glval) = FunctionAddress[operator=] : +# 810| r0_50(glval) = FunctionAddress[Base] : +# 810| r0_51(glval) = VariableAddress[m] : +# 810| r0_52(glval) = ConvertToBase[Middle : Base] : r0_51 +# 810| r0_53(Base &) = CopyValue : r0_52 +# 810| v0_54(void) = Call : func:r0_50, 0:r0_53 +# 810| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 810| r0_56(glval) = Convert : v0_54 +# 810| r0_57(Base &) = CopyValue : r0_56 +# 810| r0_58(Base &) = Call : func:r0_49, this:r0_48, 0:r0_57 +# 810| mu0_59(unknown) = ^CallSideEffect : ~mu0_2 +# 810| r0_60(glval) = CopyValue : r0_58 +# 811| r0_61(glval) = VariableAddress[pm] : +# 811| r0_62(Middle *) = Load : &:r0_61, ~mu0_2 +# 811| r0_63(Base *) = ConvertToBase[Middle : Base] : r0_62 +# 811| r0_64(glval) = VariableAddress[pb] : +# 811| mu0_65(Base *) = Store : &:r0_64, r0_63 +# 811| r0_66(glval) = CopyValue : r0_64 +# 812| r0_67(glval) = VariableAddress[pm] : +# 812| r0_68(Middle *) = Load : &:r0_67, ~mu0_2 +# 812| r0_69(Base *) = ConvertToBase[Middle : Base] : r0_68 +# 812| r0_70(glval) = VariableAddress[pb] : +# 812| mu0_71(Base *) = Store : &:r0_70, r0_69 +# 812| r0_72(glval) = CopyValue : r0_70 +# 813| r0_73(glval) = VariableAddress[pm] : +# 813| r0_74(Middle *) = Load : &:r0_73, ~mu0_2 +# 813| r0_75(Base *) = ConvertToBase[Middle : Base] : r0_74 +# 813| r0_76(glval) = VariableAddress[pb] : +# 813| mu0_77(Base *) = Store : &:r0_76, r0_75 +# 813| r0_78(glval) = CopyValue : r0_76 +# 814| r0_79(glval) = VariableAddress[pm] : +# 814| r0_80(Middle *) = Load : &:r0_79, ~mu0_2 +# 814| r0_81(Base *) = Convert : r0_80 +# 814| r0_82(glval) = VariableAddress[pb] : +# 814| mu0_83(Base *) = Store : &:r0_82, r0_81 +# 814| r0_84(glval) = CopyValue : r0_82 +# 816| r0_85(glval) = VariableAddress[m] : +# 816| r0_86(glval) = FunctionAddress[operator=] : +# 816| r0_87(glval) = VariableAddress[b] : +# 816| r0_88(glval) = ConvertToDerived[Middle : Base] : r0_87 +# 816| r0_89(glval) = Convert : r0_88 +# 816| r0_90(Middle &) = CopyValue : r0_89 +# 816| r0_91(Middle &) = Call : func:r0_86, this:r0_85, 0:r0_90 +# 816| mu0_92(unknown) = ^CallSideEffect : ~mu0_2 +# 816| r0_93(glval) = CopyValue : r0_91 +# 817| r0_94(glval) = VariableAddress[m] : +# 817| r0_95(glval) = FunctionAddress[operator=] : +# 817| r0_96(glval) = VariableAddress[b] : +# 817| r0_97(glval) = ConvertToDerived[Middle : Base] : r0_96 +# 817| r0_98(glval) = Convert : r0_97 +# 817| r0_99(Middle &) = CopyValue : r0_98 +# 817| r0_100(Middle &) = Call : func:r0_95, this:r0_94, 0:r0_99 +# 817| mu0_101(unknown) = ^CallSideEffect : ~mu0_2 +# 817| r0_102(glval) = CopyValue : r0_100 +# 818| r0_103(glval) = VariableAddress[pb] : +# 818| r0_104(Base *) = Load : &:r0_103, ~mu0_2 +# 818| r0_105(Middle *) = ConvertToDerived[Middle : Base] : r0_104 +# 818| r0_106(glval) = VariableAddress[pm] : +# 818| mu0_107(Middle *) = Store : &:r0_106, r0_105 +# 818| r0_108(glval) = CopyValue : r0_106 +# 819| r0_109(glval) = VariableAddress[pb] : +# 819| r0_110(Base *) = Load : &:r0_109, ~mu0_2 +# 819| r0_111(Middle *) = ConvertToDerived[Middle : Base] : r0_110 +# 819| r0_112(glval) = VariableAddress[pm] : +# 819| mu0_113(Middle *) = Store : &:r0_112, r0_111 +# 819| r0_114(glval) = CopyValue : r0_112 +# 820| r0_115(glval) = VariableAddress[pb] : +# 820| r0_116(Base *) = Load : &:r0_115, ~mu0_2 +# 820| r0_117(Middle *) = Convert : r0_116 +# 820| r0_118(glval) = VariableAddress[pm] : +# 820| mu0_119(Middle *) = Store : &:r0_118, r0_117 +# 820| r0_120(glval) = CopyValue : r0_118 +# 822| r0_121(glval) = VariableAddress[b] : +# 822| r0_122(glval) = FunctionAddress[operator=] : +# 822| r0_123(glval) = VariableAddress[d] : +# 822| r0_124(glval) = ConvertToBase[Derived : Middle] : r0_123 +# 822| r0_125(glval) = ConvertToBase[Middle : Base] : r0_124 +# 822| r0_126(Base &) = CopyValue : r0_125 +# 822| r0_127(Base &) = Call : func:r0_122, this:r0_121, 0:r0_126 +# 822| mu0_128(unknown) = ^CallSideEffect : ~mu0_2 +# 822| r0_129(glval) = CopyValue : r0_127 +# 823| r0_130(glval) = VariableAddress[b] : +# 823| r0_131(glval) = FunctionAddress[operator=] : +# 823| r0_132(glval) = FunctionAddress[Base] : +# 823| r0_133(glval) = VariableAddress[d] : +# 823| r0_134(glval) = ConvertToBase[Derived : Middle] : r0_133 +# 823| r0_135(glval) = ConvertToBase[Middle : Base] : r0_134 +# 823| r0_136(Base &) = CopyValue : r0_135 +# 823| v0_137(void) = Call : func:r0_132, 0:r0_136 +# 823| mu0_138(unknown) = ^CallSideEffect : ~mu0_2 +# 823| r0_139(glval) = Convert : v0_137 +# 823| r0_140(Base &) = CopyValue : r0_139 +# 823| r0_141(Base &) = Call : func:r0_131, this:r0_130, 0:r0_140 +# 823| mu0_142(unknown) = ^CallSideEffect : ~mu0_2 +# 823| r0_143(glval) = CopyValue : r0_141 +# 824| r0_144(glval) = VariableAddress[b] : +# 824| r0_145(glval) = FunctionAddress[operator=] : +# 824| r0_146(glval) = FunctionAddress[Base] : +# 824| r0_147(glval) = VariableAddress[d] : +# 824| r0_148(glval) = ConvertToBase[Derived : Middle] : r0_147 +# 824| r0_149(glval) = ConvertToBase[Middle : Base] : r0_148 +# 824| r0_150(Base &) = CopyValue : r0_149 +# 824| v0_151(void) = Call : func:r0_146, 0:r0_150 +# 824| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 +# 824| r0_153(glval) = Convert : v0_151 +# 824| r0_154(Base &) = CopyValue : r0_153 +# 824| r0_155(Base &) = Call : func:r0_145, this:r0_144, 0:r0_154 +# 824| mu0_156(unknown) = ^CallSideEffect : ~mu0_2 +# 824| r0_157(glval) = CopyValue : r0_155 +# 825| r0_158(glval) = VariableAddress[pd] : +# 825| r0_159(Derived *) = Load : &:r0_158, ~mu0_2 +# 825| r0_160(Middle *) = ConvertToBase[Derived : Middle] : r0_159 +# 825| r0_161(Base *) = ConvertToBase[Middle : Base] : r0_160 +# 825| r0_162(glval) = VariableAddress[pb] : +# 825| mu0_163(Base *) = Store : &:r0_162, r0_161 +# 825| r0_164(glval) = CopyValue : r0_162 +# 826| r0_165(glval) = VariableAddress[pd] : +# 826| r0_166(Derived *) = Load : &:r0_165, ~mu0_2 +# 826| r0_167(Middle *) = ConvertToBase[Derived : Middle] : r0_166 +# 826| r0_168(Base *) = ConvertToBase[Middle : Base] : r0_167 +# 826| r0_169(glval) = VariableAddress[pb] : +# 826| mu0_170(Base *) = Store : &:r0_169, r0_168 +# 826| r0_171(glval) = CopyValue : r0_169 +# 827| r0_172(glval) = VariableAddress[pd] : +# 827| r0_173(Derived *) = Load : &:r0_172, ~mu0_2 +# 827| r0_174(Middle *) = ConvertToBase[Derived : Middle] : r0_173 +# 827| r0_175(Base *) = ConvertToBase[Middle : Base] : r0_174 +# 827| r0_176(glval) = VariableAddress[pb] : +# 827| mu0_177(Base *) = Store : &:r0_176, r0_175 +# 827| r0_178(glval) = CopyValue : r0_176 +# 828| r0_179(glval) = VariableAddress[pd] : +# 828| r0_180(Derived *) = Load : &:r0_179, ~mu0_2 +# 828| r0_181(Base *) = Convert : r0_180 +# 828| r0_182(glval) = VariableAddress[pb] : +# 828| mu0_183(Base *) = Store : &:r0_182, r0_181 +# 828| r0_184(glval) = CopyValue : r0_182 +# 830| r0_185(glval) = VariableAddress[d] : +# 830| r0_186(glval) = FunctionAddress[operator=] : +# 830| r0_187(glval) = VariableAddress[b] : +# 830| r0_188(glval) = ConvertToDerived[Middle : Base] : r0_187 +# 830| r0_189(glval) = ConvertToDerived[Derived : Middle] : r0_188 +# 830| r0_190(glval) = Convert : r0_189 +# 830| r0_191(Derived &) = CopyValue : r0_190 +# 830| r0_192(Derived &) = Call : func:r0_186, this:r0_185, 0:r0_191 +# 830| mu0_193(unknown) = ^CallSideEffect : ~mu0_2 +# 830| r0_194(glval) = CopyValue : r0_192 +# 831| r0_195(glval) = VariableAddress[d] : +# 831| r0_196(glval) = FunctionAddress[operator=] : +# 831| r0_197(glval) = VariableAddress[b] : +# 831| r0_198(glval) = ConvertToDerived[Middle : Base] : r0_197 +# 831| r0_199(glval) = ConvertToDerived[Derived : Middle] : r0_198 +# 831| r0_200(glval) = Convert : r0_199 +# 831| r0_201(Derived &) = CopyValue : r0_200 +# 831| r0_202(Derived &) = Call : func:r0_196, this:r0_195, 0:r0_201 +# 831| mu0_203(unknown) = ^CallSideEffect : ~mu0_2 +# 831| r0_204(glval) = CopyValue : r0_202 +# 832| r0_205(glval) = VariableAddress[pb] : +# 832| r0_206(Base *) = Load : &:r0_205, ~mu0_2 +# 832| r0_207(Middle *) = ConvertToDerived[Middle : Base] : r0_206 +# 832| r0_208(Derived *) = ConvertToDerived[Derived : Middle] : r0_207 +# 832| r0_209(glval) = VariableAddress[pd] : +# 832| mu0_210(Derived *) = Store : &:r0_209, r0_208 +# 832| r0_211(glval) = CopyValue : r0_209 +# 833| r0_212(glval) = VariableAddress[pb] : +# 833| r0_213(Base *) = Load : &:r0_212, ~mu0_2 +# 833| r0_214(Middle *) = ConvertToDerived[Middle : Base] : r0_213 +# 833| r0_215(Derived *) = ConvertToDerived[Derived : Middle] : r0_214 +# 833| r0_216(glval) = VariableAddress[pd] : +# 833| mu0_217(Derived *) = Store : &:r0_216, r0_215 +# 833| r0_218(glval) = CopyValue : r0_216 +# 834| r0_219(glval) = VariableAddress[pb] : +# 834| r0_220(Base *) = Load : &:r0_219, ~mu0_2 +# 834| r0_221(Derived *) = Convert : r0_220 +# 834| r0_222(glval) = VariableAddress[pd] : +# 834| mu0_223(Derived *) = Store : &:r0_222, r0_221 +# 834| r0_224(glval) = CopyValue : r0_222 +# 836| r0_225(glval) = VariableAddress[pmv] : +# 836| r0_226(MiddleVB1 *) = Constant[0] : +# 836| mu0_227(MiddleVB1 *) = Store : &:r0_225, r0_226 +# 837| r0_228(glval) = VariableAddress[pdv] : +# 837| r0_229(DerivedVB *) = Constant[0] : +# 837| mu0_230(DerivedVB *) = Store : &:r0_228, r0_229 +# 838| r0_231(glval) = VariableAddress[pmv] : +# 838| r0_232(MiddleVB1 *) = Load : &:r0_231, ~mu0_2 +# 838| r0_233(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_232 +# 838| r0_234(glval) = VariableAddress[pb] : +# 838| mu0_235(Base *) = Store : &:r0_234, r0_233 +# 838| r0_236(glval) = CopyValue : r0_234 +# 839| r0_237(glval) = VariableAddress[pdv] : +# 839| r0_238(DerivedVB *) = Load : &:r0_237, ~mu0_2 +# 839| r0_239(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_238 +# 839| r0_240(glval) = VariableAddress[pb] : +# 839| mu0_241(Base *) = Store : &:r0_240, r0_239 +# 839| r0_242(glval) = CopyValue : r0_240 +# 840| v0_243(void) = NoOp : +# 799| v0_244(void) = ReturnVoid : +# 799| v0_245(void) = UnmodeledUse : mu* +# 799| v0_246(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -3826,42 +4070,48 @@ ir.cpp: # 851| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 # 853| r0_11(glval) = VariableAddress[pb] : # 853| r0_12(glval) = VariableAddress[b] : -# 853| mu0_13(PolymorphicBase *) = Store : &:r0_11, r0_12 -# 854| r0_14(glval) = VariableAddress[pd] : -# 854| r0_15(glval) = VariableAddress[d] : -# 854| mu0_16(PolymorphicDerived *) = Store : &:r0_14, r0_15 -# 857| r0_17(glval) = VariableAddress[pd] : -# 857| r0_18(PolymorphicDerived *) = Load : &:r0_17, ~mu0_2 -# 857| r0_19(PolymorphicBase *) = CheckedConvertOrNull : r0_18 -# 857| r0_20(glval) = VariableAddress[pb] : -# 857| mu0_21(PolymorphicBase *) = Store : &:r0_20, r0_19 -# 858| r0_22(glval) = VariableAddress[rb] : -# 858| r0_23(glval) = VariableAddress[d] : -# 858| r0_24(glval) = CheckedConvertOrThrow : r0_23 -# 858| mu0_25(PolymorphicBase &) = Store : &:r0_22, r0_24 -# 860| r0_26(glval) = VariableAddress[pb] : -# 860| r0_27(PolymorphicBase *) = Load : &:r0_26, ~mu0_2 -# 860| r0_28(PolymorphicDerived *) = CheckedConvertOrNull : r0_27 -# 860| r0_29(glval) = VariableAddress[pd] : -# 860| mu0_30(PolymorphicDerived *) = Store : &:r0_29, r0_28 -# 861| r0_31(glval) = VariableAddress[rd] : -# 861| r0_32(glval) = VariableAddress[b] : -# 861| r0_33(glval) = CheckedConvertOrThrow : r0_32 -# 861| mu0_34(PolymorphicDerived &) = Store : &:r0_31, r0_33 -# 863| r0_35(glval) = VariableAddress[pv] : -# 863| r0_36(glval) = VariableAddress[pb] : -# 863| r0_37(PolymorphicBase *) = Load : &:r0_36, ~mu0_2 -# 863| r0_38(void *) = DynamicCastToVoid : r0_37 -# 863| mu0_39(void *) = Store : &:r0_35, r0_38 -# 864| r0_40(glval) = VariableAddress[pcv] : -# 864| r0_41(glval) = VariableAddress[pd] : -# 864| r0_42(PolymorphicDerived *) = Load : &:r0_41, ~mu0_2 -# 864| r0_43(void *) = DynamicCastToVoid : r0_42 -# 864| mu0_44(void *) = Store : &:r0_40, r0_43 -# 865| v0_45(void) = NoOp : -# 849| v0_46(void) = ReturnVoid : -# 849| v0_47(void) = UnmodeledUse : mu* -# 849| v0_48(void) = ExitFunction : +# 853| r0_13(PolymorphicBase *) = CopyValue : r0_12 +# 853| mu0_14(PolymorphicBase *) = Store : &:r0_11, r0_13 +# 854| r0_15(glval) = VariableAddress[pd] : +# 854| r0_16(glval) = VariableAddress[d] : +# 854| r0_17(PolymorphicDerived *) = CopyValue : r0_16 +# 854| mu0_18(PolymorphicDerived *) = Store : &:r0_15, r0_17 +# 857| r0_19(glval) = VariableAddress[pd] : +# 857| r0_20(PolymorphicDerived *) = Load : &:r0_19, ~mu0_2 +# 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 +# 857| r0_22(glval) = VariableAddress[pb] : +# 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 +# 857| r0_24(glval) = CopyValue : r0_22 +# 858| r0_25(glval) = VariableAddress[rb] : +# 858| r0_26(glval) = VariableAddress[d] : +# 858| r0_27(glval) = CheckedConvertOrThrow : r0_26 +# 858| r0_28(PolymorphicBase &) = CopyValue : r0_27 +# 858| mu0_29(PolymorphicBase &) = Store : &:r0_25, r0_28 +# 860| r0_30(glval) = VariableAddress[pb] : +# 860| r0_31(PolymorphicBase *) = Load : &:r0_30, ~mu0_2 +# 860| r0_32(PolymorphicDerived *) = CheckedConvertOrNull : r0_31 +# 860| r0_33(glval) = VariableAddress[pd] : +# 860| mu0_34(PolymorphicDerived *) = Store : &:r0_33, r0_32 +# 860| r0_35(glval) = CopyValue : r0_33 +# 861| r0_36(glval) = VariableAddress[rd] : +# 861| r0_37(glval) = VariableAddress[b] : +# 861| r0_38(glval) = CheckedConvertOrThrow : r0_37 +# 861| r0_39(PolymorphicDerived &) = CopyValue : r0_38 +# 861| mu0_40(PolymorphicDerived &) = Store : &:r0_36, r0_39 +# 863| r0_41(glval) = VariableAddress[pv] : +# 863| r0_42(glval) = VariableAddress[pb] : +# 863| r0_43(PolymorphicBase *) = Load : &:r0_42, ~mu0_2 +# 863| r0_44(void *) = DynamicCastToVoid : r0_43 +# 863| mu0_45(void *) = Store : &:r0_41, r0_44 +# 864| r0_46(glval) = VariableAddress[pcv] : +# 864| r0_47(glval) = VariableAddress[pd] : +# 864| r0_48(PolymorphicDerived *) = Load : &:r0_47, ~mu0_2 +# 864| r0_49(void *) = DynamicCastToVoid : r0_48 +# 864| mu0_50(void *) = Store : &:r0_46, r0_49 +# 865| v0_51(void) = NoOp : +# 849| v0_52(void) = ReturnVoid : +# 849| v0_53(void) = UnmodeledUse : mu* +# 849| v0_54(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -3895,36 +4145,46 @@ ir.cpp: # 874| r0_11(char *) = Convert : r0_10 # 874| r0_12(glval) = VariableAddress[p] : # 874| mu0_13(char *) = Store : &:r0_12, r0_11 -# 875| r0_14(glval) = VariableAddress[a] : -# 875| r0_15(char *) = Convert : r0_14 -# 875| r0_16(int) = Constant[0] : -# 875| r0_17(glval) = PointerAdd[1] : r0_15, r0_16 -# 875| r0_18(char *) = Convert : r0_17 -# 875| r0_19(glval) = VariableAddress[p] : -# 875| mu0_20(char *) = Store : &:r0_19, r0_18 -# 876| r0_21(glval) = StringConstant["test"] : -# 876| r0_22(char *) = Convert : r0_21 -# 876| r0_23(int) = Constant[0] : -# 876| r0_24(glval) = PointerAdd[1] : r0_22, r0_23 -# 876| r0_25(glval) = VariableAddress[p] : -# 876| mu0_26(char *) = Store : &:r0_25, r0_24 -# 877| r0_27(glval) = VariableAddress[ra] : -# 877| r0_28(glval) = VariableAddress[a] : -# 877| mu0_29(char(&)[5]) = Store : &:r0_27, r0_28 -# 878| r0_30(glval) = VariableAddress[rs] : -# 878| r0_31(glval) = StringConstant["test"] : -# 878| mu0_32(char(&)[5]) = Store : &:r0_30, r0_31 -# 879| r0_33(glval) = VariableAddress[pa] : -# 879| r0_34(glval) = VariableAddress[a] : -# 879| r0_35(char(*)[5]) = Convert : r0_34 -# 879| mu0_36(char(*)[5]) = Store : &:r0_33, r0_35 -# 880| r0_37(glval) = StringConstant["test"] : -# 880| r0_38(glval) = VariableAddress[pa] : -# 880| mu0_39(char(*)[5]) = Store : &:r0_38, r0_37 -# 881| v0_40(void) = NoOp : -# 871| v0_41(void) = ReturnVoid : -# 871| v0_42(void) = UnmodeledUse : mu* -# 871| v0_43(void) = ExitFunction : +# 874| r0_14(glval) = CopyValue : r0_12 +# 875| r0_15(glval) = VariableAddress[a] : +# 875| r0_16(char *) = Convert : r0_15 +# 875| r0_17(int) = Constant[0] : +# 875| r0_18(glval) = PointerAdd[1] : r0_16, r0_17 +# 875| r0_19(char *) = CopyValue : r0_18 +# 875| r0_20(char *) = Convert : r0_19 +# 875| r0_21(glval) = VariableAddress[p] : +# 875| mu0_22(char *) = Store : &:r0_21, r0_20 +# 875| r0_23(glval) = CopyValue : r0_21 +# 876| r0_24(glval) = StringConstant["test"] : +# 876| r0_25(char *) = Convert : r0_24 +# 876| r0_26(int) = Constant[0] : +# 876| r0_27(glval) = PointerAdd[1] : r0_25, r0_26 +# 876| r0_28(char *) = CopyValue : r0_27 +# 876| r0_29(glval) = VariableAddress[p] : +# 876| mu0_30(char *) = Store : &:r0_29, r0_28 +# 876| r0_31(glval) = CopyValue : r0_29 +# 877| r0_32(glval) = VariableAddress[ra] : +# 877| r0_33(glval) = VariableAddress[a] : +# 877| r0_34(char(&)[5]) = CopyValue : r0_33 +# 877| mu0_35(char(&)[5]) = Store : &:r0_32, r0_34 +# 878| r0_36(glval) = VariableAddress[rs] : +# 878| r0_37(glval) = StringConstant["test"] : +# 878| r0_38(char(&)[5]) = CopyValue : r0_37 +# 878| mu0_39(char(&)[5]) = Store : &:r0_36, r0_38 +# 879| r0_40(glval) = VariableAddress[pa] : +# 879| r0_41(glval) = VariableAddress[a] : +# 879| r0_42(char(*)[5]) = CopyValue : r0_41 +# 879| r0_43(char(*)[5]) = Convert : r0_42 +# 879| mu0_44(char(*)[5]) = Store : &:r0_40, r0_43 +# 880| r0_45(glval) = StringConstant["test"] : +# 880| r0_46(char(*)[5]) = CopyValue : r0_45 +# 880| r0_47(glval) = VariableAddress[pa] : +# 880| mu0_48(char(*)[5]) = Store : &:r0_47, r0_46 +# 880| r0_49(glval) = CopyValue : r0_47 +# 881| v0_50(void) = NoOp : +# 871| v0_51(void) = ReturnVoid : +# 871| v0_52(void) = UnmodeledUse : mu* +# 871| v0_53(void) = ExitFunction : # 883| void FuncPtrConversions(int(*)(int), void*) # 883| Block 0 @@ -3940,15 +4200,17 @@ ir.cpp: # 884| r0_9(void *) = Convert : r0_8 # 884| r0_10(glval) = VariableAddress[p] : # 884| mu0_11(void *) = Store : &:r0_10, r0_9 -# 885| r0_12(glval) = VariableAddress[p] : -# 885| r0_13(void *) = Load : &:r0_12, ~mu0_2 -# 885| r0_14(..(*)(..)) = Convert : r0_13 -# 885| r0_15(glval<..(*)(..)>) = VariableAddress[pfn] : -# 885| mu0_16(..(*)(..)) = Store : &:r0_15, r0_14 -# 886| v0_17(void) = NoOp : -# 883| v0_18(void) = ReturnVoid : -# 883| v0_19(void) = UnmodeledUse : mu* -# 883| v0_20(void) = ExitFunction : +# 884| r0_12(glval) = CopyValue : r0_10 +# 885| r0_13(glval) = VariableAddress[p] : +# 885| r0_14(void *) = Load : &:r0_13, ~mu0_2 +# 885| r0_15(..(*)(..)) = Convert : r0_14 +# 885| r0_16(glval<..(*)(..)>) = VariableAddress[pfn] : +# 885| mu0_17(..(*)(..)) = Store : &:r0_16, r0_15 +# 885| r0_18(glval<..(*)(..)>) = CopyValue : r0_16 +# 886| v0_19(void) = NoOp : +# 883| v0_20(void) = ReturnVoid : +# 883| v0_21(void) = UnmodeledUse : mu* +# 883| v0_22(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4246,7 +4508,8 @@ ir.cpp: # 967| mu0_13(bool) = Store : &:r0_7, r0_12 # 967| r0_14(glval) = VariableAddress[b] : # 967| r0_15(bool) = Load : &:r0_14, ~mu0_2 -# 967| v0_16(void) = ConditionalBranch : r0_15 +# 967| r0_16(bool) = CopyValue : r0_15 +# 967| v0_17(void) = ConditionalBranch : r0_16 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4254,6 +4517,7 @@ ir.cpp: # 968| r1_0(int) = Constant[5] : # 968| r1_1(glval) = VariableAddress[x] : # 968| mu1_2(int) = Store : &:r1_1, r1_0 +# 968| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 6 # 970| Block 2 @@ -4268,7 +4532,8 @@ ir.cpp: # 970| r2_8(int) = Load : &:r2_7, ~mu0_2 # 970| r2_9(int) = Constant[0] : # 970| r2_10(bool) = CompareNE : r2_8, r2_9 -# 970| v2_11(void) = ConditionalBranch : r2_10 +# 970| r2_11(bool) = CopyValue : r2_10 +# 970| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4276,17 +4541,20 @@ ir.cpp: # 971| r3_0(int) = Constant[7] : # 971| r3_1(glval) = VariableAddress[y] : # 971| mu3_2(int) = Store : &:r3_1, r3_0 +# 971| r3_3(glval) = CopyValue : r3_1 #-----| Goto -> Block 6 # 973| Block 4 # 973| r4_0(glval) = VariableAddress[p] : # 973| r4_1(glval) = VariableAddress[x] : -# 973| mu4_2(int *) = Store : &:r4_0, r4_1 -# 973| r4_3(glval) = VariableAddress[p] : -# 973| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 973| r4_5(int *) = Constant[0] : -# 973| r4_6(bool) = CompareNE : r4_4, r4_5 -# 973| v4_7(void) = ConditionalBranch : r4_6 +# 973| r4_2(int *) = CopyValue : r4_1 +# 973| mu4_3(int *) = Store : &:r4_0, r4_2 +# 973| r4_4(glval) = VariableAddress[p] : +# 973| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 973| r4_6(int *) = Constant[0] : +# 973| r4_7(bool) = CompareNE : r4_5, r4_6 +# 973| r4_8(bool) = CopyValue : r4_7 +# 973| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4294,7 +4562,9 @@ ir.cpp: # 974| r5_0(int) = Constant[2] : # 974| r5_1(glval) = VariableAddress[p] : # 974| r5_2(int *) = Load : &:r5_1, ~mu0_2 -# 974| mu5_3(int) = Store : &:r5_2, r5_0 +# 974| r5_3(glval) = CopyValue : r5_2 +# 974| mu5_4(int) = Store : &:r5_3, r5_0 +# 974| r5_5(glval) = CopyValue : r5_3 #-----| Goto -> Block 6 # 976| Block 6 @@ -4330,7 +4600,8 @@ ir.cpp: # 981| r2_8(int) = Load : &:r2_7, ~mu0_2 # 981| r2_9(int) = Constant[0] : # 981| r2_10(bool) = CompareNE : r2_8, r2_9 -# 981| v2_11(void) = ConditionalBranch : r2_10 +# 981| r2_11(bool) = CopyValue : r2_10 +# 981| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4341,12 +4612,14 @@ ir.cpp: # 983| Block 4 # 983| r4_0(glval) = VariableAddress[p] : # 983| r4_1(glval) = VariableAddress[x] : -# 983| mu4_2(int *) = Store : &:r4_0, r4_1 -# 983| r4_3(glval) = VariableAddress[p] : -# 983| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 983| r4_5(int *) = Constant[0] : -# 983| r4_6(bool) = CompareNE : r4_4, r4_5 -# 983| v4_7(void) = ConditionalBranch : r4_6 +# 983| r4_2(int *) = CopyValue : r4_1 +# 983| mu4_3(int *) = Store : &:r4_0, r4_2 +# 983| r4_4(glval) = VariableAddress[p] : +# 983| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 983| r4_6(int *) = Constant[0] : +# 983| r4_7(bool) = CompareNE : r4_5, r4_6 +# 983| r4_8(bool) = CopyValue : r4_7 +# 983| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4370,7 +4643,8 @@ ir.cpp: # 979| mu7_6(bool) = Store : &:r7_0, r7_5 # 979| r7_7(glval) = VariableAddress[b] : # 979| r7_8(bool) = Load : &:r7_7, ~mu0_2 -# 979| v7_9(void) = ConditionalBranch : r7_8 +# 979| r7_9(bool) = CopyValue : r7_8 +# 979| v7_10(void) = ConditionalBranch : r7_9 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4428,6 +4702,7 @@ ir.cpp: # 995| r1_1(int) = Load : &:r1_0, ~mu0_2 # 995| r1_2(glval) = VariableAddress[w] : # 995| mu1_3(int) = Store : &:r1_2, r1_1 +# 995| r1_4(glval) = CopyValue : r1_2 #-----| Goto -> Block 3 # 997| Block 2 @@ -4435,6 +4710,7 @@ ir.cpp: # 997| r2_1(int) = Load : &:r2_0, ~mu0_2 # 997| r2_2(glval) = VariableAddress[w] : # 997| mu2_3(int) = Store : &:r2_2, r2_1 +# 997| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 999| Block 3 @@ -4544,147 +4820,159 @@ ir.cpp: # 1031| void Lambda(int, String const&) # 1031| Block 0 -# 1031| v0_0(void) = EnterFunction : -# 1031| mu0_1(unknown) = AliasedDefinition : -# 1031| mu0_2(unknown) = UnmodeledDefinition : -# 1031| r0_3(glval) = VariableAddress[x] : -# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 -# 1031| r0_5(glval) = VariableAddress[s] : -# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 -# 1032| r0_7(glval) = VariableAddress[lambda_empty] : -# 1032| r0_8(glval) = VariableAddress[#temp1032:23] : -# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8 -# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2 -# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10 -# 1033| r0_12(char) = Constant[65] : -# 1034| r0_13(glval) = VariableAddress[lambda_ref] : -# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : -# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 -# 1034| r0_16(glval) = FieldAddress[s] : r0_14 -#-----| r0_17(glval) = VariableAddress[s] : -#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(String &) = Store : &:r0_16, r0_18 -# 1034| r0_20(glval) = FieldAddress[x] : r0_14 -#-----| r0_21(glval) = VariableAddress[x] : -#-----| mu0_22(int &) = Store : &:r0_20, r0_21 -# 1034| r0_23(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 -# 1034| mu0_24(decltype([...](...){...})) = Store : &:r0_13, r0_23 -# 1035| r0_25(glval) = VariableAddress[lambda_ref] : -# 1035| r0_26(glval) = Convert : r0_25 -# 1035| r0_27(glval) = FunctionAddress[operator()] : -# 1035| r0_28(float) = Constant[1.0] : -# 1035| r0_29(char) = Call : func:r0_27, this:r0_26, 0:r0_28 -# 1035| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_31(glval) = VariableAddress[lambda_val] : -# 1036| r0_32(glval) = FunctionAddress[(constructor)] : -# 1036| r0_33(glval) = VariableAddress[#temp1036:21] : -# 1036| mu0_34(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_33 -# 1036| r0_35(glval) = FieldAddress[s] : r0_33 -#-----| r0_36(glval) = FunctionAddress[String] : -#-----| v0_37(void) = Call : func:r0_36, this:r0_35 -#-----| mu0_38(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_39(glval) = FieldAddress[x] : r0_33 -#-----| r0_40(glval) = VariableAddress[x] : -#-----| r0_41(int) = Load : &:r0_40, ~mu0_2 -#-----| mu0_42(int) = Store : &:r0_39, r0_41 -# 1036| r0_43(decltype([...](...){...})) = Load : &:r0_33, ~mu0_2 -# 1036| v0_44(void) = Call : func:r0_32, this:r0_31, 0:r0_43 -# 1036| mu0_45(unknown) = ^CallSideEffect : ~mu0_2 -# 1037| r0_46(glval) = VariableAddress[lambda_val] : -# 1037| r0_47(glval) = Convert : r0_46 -# 1037| r0_48(glval) = FunctionAddress[operator()] : -# 1037| r0_49(float) = Constant[2.0] : -# 1037| r0_50(char) = Call : func:r0_48, this:r0_47, 0:r0_49 -# 1037| mu0_51(unknown) = ^CallSideEffect : ~mu0_2 -# 1038| r0_52(glval) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_53(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_54(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_53 -# 1038| r0_55(glval) = FieldAddress[s] : r0_53 -# 1038| r0_56(glval) = VariableAddress[s] : -# 1038| r0_57(String &) = Load : &:r0_56, ~mu0_2 -# 1038| mu0_58(String &) = Store : &:r0_55, r0_57 -# 1038| r0_59(decltype([...](...){...})) = Load : &:r0_53, ~mu0_2 -# 1038| mu0_60(decltype([...](...){...})) = Store : &:r0_52, r0_59 -# 1039| r0_61(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_62(glval) = Convert : r0_61 -# 1039| r0_63(glval) = FunctionAddress[operator()] : -# 1039| r0_64(float) = Constant[3.0] : -# 1039| r0_65(char) = Call : func:r0_63, this:r0_62, 0:r0_64 -# 1039| mu0_66(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_67(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_68(glval) = FunctionAddress[(constructor)] : -# 1040| r0_69(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_70(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_69 -# 1040| r0_71(glval) = FieldAddress[s] : r0_69 -#-----| r0_72(glval) = FunctionAddress[String] : -#-----| v0_73(void) = Call : func:r0_72, this:r0_71 -#-----| mu0_74(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_75(decltype([...](...){...})) = Load : &:r0_69, ~mu0_2 -# 1040| v0_76(void) = Call : func:r0_68, this:r0_67, 0:r0_75 -# 1040| mu0_77(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| r0_78(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_79(glval) = Convert : r0_78 -# 1041| r0_80(glval) = FunctionAddress[operator()] : -# 1041| r0_81(float) = Constant[4.0] : -# 1041| r0_82(char) = Call : func:r0_80, this:r0_79, 0:r0_81 -# 1041| mu0_83(unknown) = ^CallSideEffect : ~mu0_2 -# 1042| r0_84(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_85(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_86(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_85 -# 1042| r0_87(glval) = FieldAddress[s] : r0_85 -# 1042| r0_88(glval) = VariableAddress[s] : -# 1042| r0_89(String &) = Load : &:r0_88, ~mu0_2 -# 1042| mu0_90(String &) = Store : &:r0_87, r0_89 -# 1042| r0_91(glval) = FieldAddress[x] : r0_85 -# 1042| r0_92(glval) = VariableAddress[x] : -# 1042| r0_93(int) = Load : &:r0_92, ~mu0_2 -# 1042| mu0_94(int) = Store : &:r0_91, r0_93 -# 1042| r0_95(decltype([...](...){...})) = Load : &:r0_85, ~mu0_2 -# 1042| mu0_96(decltype([...](...){...})) = Store : &:r0_84, r0_95 -# 1043| r0_97(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_98(glval) = Convert : r0_97 -# 1043| r0_99(glval) = FunctionAddress[operator()] : -# 1043| r0_100(float) = Constant[5.0] : -# 1043| r0_101(char) = Call : func:r0_99, this:r0_98, 0:r0_100 -# 1043| mu0_102(unknown) = ^CallSideEffect : ~mu0_2 -# 1044| r0_103(glval) = VariableAddress[r] : -# 1044| r0_104(glval) = VariableAddress[x] : -# 1044| r0_105(int) = Load : &:r0_104, ~mu0_2 -# 1044| r0_106(int) = Constant[1] : -# 1044| r0_107(int) = Sub : r0_105, r0_106 -# 1044| mu0_108(int) = Store : &:r0_103, r0_107 -# 1045| r0_109(glval) = VariableAddress[lambda_inits] : -# 1045| r0_110(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_111(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_110 -# 1045| r0_112(glval) = FieldAddress[s] : r0_110 -# 1045| r0_113(glval) = VariableAddress[s] : -# 1045| r0_114(String &) = Load : &:r0_113, ~mu0_2 -# 1045| mu0_115(String &) = Store : &:r0_112, r0_114 -# 1045| r0_116(glval) = FieldAddress[x] : r0_110 -# 1045| r0_117(glval) = VariableAddress[x] : -# 1045| r0_118(int) = Load : &:r0_117, ~mu0_2 -# 1045| mu0_119(int) = Store : &:r0_116, r0_118 -# 1045| r0_120(glval) = FieldAddress[i] : r0_110 -# 1045| r0_121(glval) = VariableAddress[x] : -# 1045| r0_122(int) = Load : &:r0_121, ~mu0_2 -# 1045| r0_123(int) = Constant[1] : -# 1045| r0_124(int) = Add : r0_122, r0_123 -# 1045| mu0_125(int) = Store : &:r0_120, r0_124 -# 1045| r0_126(glval) = FieldAddress[j] : r0_110 -# 1045| r0_127(glval) = VariableAddress[r] : -# 1045| mu0_128(int &) = Store : &:r0_126, r0_127 -# 1045| r0_129(decltype([...](...){...})) = Load : &:r0_110, ~mu0_2 -# 1045| mu0_130(decltype([...](...){...})) = Store : &:r0_109, r0_129 -# 1046| r0_131(glval) = VariableAddress[lambda_inits] : -# 1046| r0_132(glval) = Convert : r0_131 -# 1046| r0_133(glval) = FunctionAddress[operator()] : -# 1046| r0_134(float) = Constant[6.0] : -# 1046| r0_135(char) = Call : func:r0_133, this:r0_132, 0:r0_134 -# 1046| mu0_136(unknown) = ^CallSideEffect : ~mu0_2 -# 1047| v0_137(void) = NoOp : -# 1031| v0_138(void) = ReturnVoid : -# 1031| v0_139(void) = UnmodeledUse : mu* -# 1031| v0_140(void) = ExitFunction : +# 1031| v0_0(void) = EnterFunction : +# 1031| mu0_1(unknown) = AliasedDefinition : +# 1031| mu0_2(unknown) = UnmodeledDefinition : +# 1031| r0_3(glval) = VariableAddress[x] : +# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 +# 1031| r0_5(glval) = VariableAddress[s] : +# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 +# 1032| r0_7(glval) = VariableAddress[lambda_empty] : +# 1032| r0_8(glval) = VariableAddress[#temp1032:23] : +# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8 +# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2 +# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10 +# 1033| r0_12(char) = Constant[65] : +# 1034| r0_13(glval) = VariableAddress[lambda_ref] : +# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : +# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 +# 1034| r0_16(glval) = FieldAddress[s] : r0_14 +#-----| r0_17(glval) = VariableAddress[s] : +#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 +# 1034| r0_19(glval) = CopyValue : r0_18 +# 1034| r0_20(String &) = CopyValue : r0_19 +# 1034| mu0_21(String &) = Store : &:r0_16, r0_20 +# 1034| r0_22(glval) = FieldAddress[x] : r0_14 +#-----| r0_23(glval) = VariableAddress[x] : +#-----| r0_24(int &) = CopyValue : r0_23 +#-----| mu0_25(int &) = Store : &:r0_22, r0_24 +# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 +# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26 +# 1035| r0_28(glval) = VariableAddress[lambda_ref] : +# 1035| r0_29(glval) = Convert : r0_28 +# 1035| r0_30(glval) = FunctionAddress[operator()] : +# 1035| r0_31(float) = Constant[1.0] : +# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31 +# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_34(glval) = VariableAddress[lambda_val] : +# 1036| r0_35(glval) = FunctionAddress[(constructor)] : +# 1036| r0_36(glval) = VariableAddress[#temp1036:21] : +# 1036| mu0_37(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_36 +# 1036| r0_38(glval) = FieldAddress[s] : r0_36 +#-----| r0_39(glval) = FunctionAddress[String] : +#-----| v0_40(void) = Call : func:r0_39, this:r0_38 +#-----| mu0_41(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_42(glval) = FieldAddress[x] : r0_36 +#-----| r0_43(glval) = VariableAddress[x] : +#-----| r0_44(int) = Load : &:r0_43, ~mu0_2 +#-----| mu0_45(int) = Store : &:r0_42, r0_44 +# 1036| r0_46(decltype([...](...){...})) = Load : &:r0_36, ~mu0_2 +# 1036| r0_47(lambda [] type at line 1036, col. 21 &) = CopyValue : r0_46 +# 1036| v0_48(void) = Call : func:r0_35, this:r0_34, 0:r0_47 +# 1036| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| r0_50(glval) = VariableAddress[lambda_val] : +# 1037| r0_51(glval) = Convert : r0_50 +# 1037| r0_52(glval) = FunctionAddress[operator()] : +# 1037| r0_53(float) = Constant[2.0] : +# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53 +# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 1038| r0_56(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_57(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_58(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_57 +# 1038| r0_59(glval) = FieldAddress[s] : r0_57 +# 1038| r0_60(glval) = VariableAddress[s] : +# 1038| r0_61(String &) = Load : &:r0_60, ~mu0_2 +# 1038| r0_62(glval) = CopyValue : r0_61 +# 1038| r0_63(String &) = CopyValue : r0_62 +# 1038| mu0_64(String &) = Store : &:r0_59, r0_63 +# 1038| r0_65(decltype([...](...){...})) = Load : &:r0_57, ~mu0_2 +# 1038| mu0_66(decltype([...](...){...})) = Store : &:r0_56, r0_65 +# 1039| r0_67(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_68(glval) = Convert : r0_67 +# 1039| r0_69(glval) = FunctionAddress[operator()] : +# 1039| r0_70(float) = Constant[3.0] : +# 1039| r0_71(char) = Call : func:r0_69, this:r0_68, 0:r0_70 +# 1039| mu0_72(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_73(glval) = VariableAddress[lambda_val_explicit] : +# 1040| r0_74(glval) = FunctionAddress[(constructor)] : +# 1040| r0_75(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_76(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_75 +# 1040| r0_77(glval) = FieldAddress[s] : r0_75 +#-----| r0_78(glval) = FunctionAddress[String] : +#-----| v0_79(void) = Call : func:r0_78, this:r0_77 +#-----| mu0_80(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_81(decltype([...](...){...})) = Load : &:r0_75, ~mu0_2 +# 1040| r0_82(lambda [] type at line 1040, col. 30 &) = CopyValue : r0_81 +# 1040| v0_83(void) = Call : func:r0_74, this:r0_73, 0:r0_82 +# 1040| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| r0_85(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_86(glval) = Convert : r0_85 +# 1041| r0_87(glval) = FunctionAddress[operator()] : +# 1041| r0_88(float) = Constant[4.0] : +# 1041| r0_89(char) = Call : func:r0_87, this:r0_86, 0:r0_88 +# 1041| mu0_90(unknown) = ^CallSideEffect : ~mu0_2 +# 1042| r0_91(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_92(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_93(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_92 +# 1042| r0_94(glval) = FieldAddress[s] : r0_92 +# 1042| r0_95(glval) = VariableAddress[s] : +# 1042| r0_96(String &) = Load : &:r0_95, ~mu0_2 +# 1042| r0_97(glval) = CopyValue : r0_96 +# 1042| r0_98(String &) = CopyValue : r0_97 +# 1042| mu0_99(String &) = Store : &:r0_94, r0_98 +# 1042| r0_100(glval) = FieldAddress[x] : r0_92 +# 1042| r0_101(glval) = VariableAddress[x] : +# 1042| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 1042| mu0_103(int) = Store : &:r0_100, r0_102 +# 1042| r0_104(decltype([...](...){...})) = Load : &:r0_92, ~mu0_2 +# 1042| mu0_105(decltype([...](...){...})) = Store : &:r0_91, r0_104 +# 1043| r0_106(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_107(glval) = Convert : r0_106 +# 1043| r0_108(glval) = FunctionAddress[operator()] : +# 1043| r0_109(float) = Constant[5.0] : +# 1043| r0_110(char) = Call : func:r0_108, this:r0_107, 0:r0_109 +# 1043| mu0_111(unknown) = ^CallSideEffect : ~mu0_2 +# 1044| r0_112(glval) = VariableAddress[r] : +# 1044| r0_113(glval) = VariableAddress[x] : +# 1044| r0_114(int) = Load : &:r0_113, ~mu0_2 +# 1044| r0_115(int) = Constant[1] : +# 1044| r0_116(int) = Sub : r0_114, r0_115 +# 1044| mu0_117(int) = Store : &:r0_112, r0_116 +# 1045| r0_118(glval) = VariableAddress[lambda_inits] : +# 1045| r0_119(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_120(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_119 +# 1045| r0_121(glval) = FieldAddress[s] : r0_119 +# 1045| r0_122(glval) = VariableAddress[s] : +# 1045| r0_123(String &) = Load : &:r0_122, ~mu0_2 +# 1045| r0_124(glval) = CopyValue : r0_123 +# 1045| r0_125(String &) = CopyValue : r0_124 +# 1045| mu0_126(String &) = Store : &:r0_121, r0_125 +# 1045| r0_127(glval) = FieldAddress[x] : r0_119 +# 1045| r0_128(glval) = VariableAddress[x] : +# 1045| r0_129(int) = Load : &:r0_128, ~mu0_2 +# 1045| mu0_130(int) = Store : &:r0_127, r0_129 +# 1045| r0_131(glval) = FieldAddress[i] : r0_119 +# 1045| r0_132(glval) = VariableAddress[x] : +# 1045| r0_133(int) = Load : &:r0_132, ~mu0_2 +# 1045| r0_134(int) = Constant[1] : +# 1045| r0_135(int) = Add : r0_133, r0_134 +# 1045| mu0_136(int) = Store : &:r0_131, r0_135 +# 1045| r0_137(glval) = FieldAddress[j] : r0_119 +# 1045| r0_138(glval) = VariableAddress[r] : +# 1045| r0_139(int &) = CopyValue : r0_138 +# 1045| mu0_140(int &) = Store : &:r0_137, r0_139 +# 1045| r0_141(decltype([...](...){...})) = Load : &:r0_119, ~mu0_2 +# 1045| mu0_142(decltype([...](...){...})) = Store : &:r0_118, r0_141 +# 1046| r0_143(glval) = VariableAddress[lambda_inits] : +# 1046| r0_144(glval) = Convert : r0_143 +# 1046| r0_145(glval) = FunctionAddress[operator()] : +# 1046| r0_146(float) = Constant[6.0] : +# 1046| r0_147(char) = Call : func:r0_145, this:r0_144, 0:r0_146 +# 1046| mu0_148(unknown) = ^CallSideEffect : ~mu0_2 +# 1047| v0_149(void) = NoOp : +# 1031| v0_150(void) = ReturnVoid : +# 1031| v0_151(void) = UnmodeledUse : mu* +# 1031| v0_152(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 @@ -4741,20 +5029,21 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1034| r0_10(glval) = FunctionAddress[c_str] : -# 1034| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1034| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int &) = Load : &:r0_14, ~mu0_2 -# 1034| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 1034| r0_17(glval) = PointerAdd[1] : r0_11, r0_16 -# 1034| r0_18(char) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(char) = Store : &:r0_6, r0_18 -# 1034| r0_20(glval) = VariableAddress[#return] : -# 1034| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 -# 1034| v0_22(void) = UnmodeledUse : mu* -# 1034| v0_23(void) = ExitFunction : +# 1034| r0_10(glval) = CopyValue : r0_9 +# 1034| r0_11(glval) = FunctionAddress[c_str] : +# 1034| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1034| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int &) = Load : &:r0_15, ~mu0_2 +# 1034| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 1034| r0_18(glval) = PointerAdd[1] : r0_12, r0_17 +# 1034| r0_19(char) = Load : &:r0_18, ~mu0_2 +# 1034| mu0_20(char) = Store : &:r0_6, r0_19 +# 1034| r0_21(glval) = VariableAddress[#return] : +# 1034| v0_22(void) = ReturnValue : &:r0_21, ~mu0_2 +# 1034| v0_23(void) = UnmodeledUse : mu* +# 1034| v0_24(void) = ExitFunction : # 1036| void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::~() # 1036| Block 0 @@ -4808,17 +5097,18 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1038, col. 30 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1038| r0_10(glval) = FunctionAddress[c_str] : -# 1038| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1038| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1038| r0_13(int) = Constant[0] : -# 1038| r0_14(glval) = PointerAdd[1] : r0_11, r0_13 -# 1038| r0_15(char) = Load : &:r0_14, ~mu0_2 -# 1038| mu0_16(char) = Store : &:r0_6, r0_15 -# 1038| r0_17(glval) = VariableAddress[#return] : -# 1038| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 -# 1038| v0_19(void) = UnmodeledUse : mu* -# 1038| v0_20(void) = ExitFunction : +# 1038| r0_10(glval) = CopyValue : r0_9 +# 1038| r0_11(glval) = FunctionAddress[c_str] : +# 1038| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1038| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1038| r0_14(int) = Constant[0] : +# 1038| r0_15(glval) = PointerAdd[1] : r0_12, r0_14 +# 1038| r0_16(char) = Load : &:r0_15, ~mu0_2 +# 1038| mu0_17(char) = Store : &:r0_6, r0_16 +# 1038| r0_18(glval) = VariableAddress[#return] : +# 1038| v0_19(void) = ReturnValue : &:r0_18, ~mu0_2 +# 1038| v0_20(void) = UnmodeledUse : mu* +# 1038| v0_21(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 @@ -4887,19 +5177,20 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1042| r0_10(glval) = FunctionAddress[c_str] : -# 1042| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1042| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 1042| r0_16(glval) = PointerAdd[1] : r0_11, r0_15 -# 1042| r0_17(char) = Load : &:r0_16, ~mu0_2 -# 1042| mu0_18(char) = Store : &:r0_6, r0_17 -# 1042| r0_19(glval) = VariableAddress[#return] : -# 1042| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 1042| v0_21(void) = UnmodeledUse : mu* -# 1042| v0_22(void) = ExitFunction : +# 1042| r0_10(glval) = CopyValue : r0_9 +# 1042| r0_11(glval) = FunctionAddress[c_str] : +# 1042| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1042| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 1042| r0_17(glval) = PointerAdd[1] : r0_12, r0_16 +# 1042| r0_18(char) = Load : &:r0_17, ~mu0_2 +# 1042| mu0_19(char) = Store : &:r0_6, r0_18 +# 1042| r0_20(glval) = VariableAddress[#return] : +# 1042| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 1042| v0_22(void) = UnmodeledUse : mu* +# 1042| v0_23(void) = ExitFunction : # 1045| char (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::operator()(float) const # 1045| Block 0 @@ -4913,28 +5204,29 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1045| r0_10(glval) = FunctionAddress[c_str] : -# 1045| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1045| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int) = Load : &:r0_14, ~mu0_2 -#-----| r0_16(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_17(glval) = FieldAddress[i] : r0_16 -# 1045| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 1045| r0_19(int) = Add : r0_15, r0_18 -#-----| r0_20(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_21(glval) = FieldAddress[j] : r0_20 -# 1045| r0_22(int &) = Load : &:r0_21, ~mu0_2 -# 1045| r0_23(int) = Load : &:r0_22, ~mu0_2 -# 1045| r0_24(int) = Sub : r0_19, r0_23 -# 1045| r0_25(glval) = PointerAdd[1] : r0_11, r0_24 -# 1045| r0_26(char) = Load : &:r0_25, ~mu0_2 -# 1045| mu0_27(char) = Store : &:r0_6, r0_26 -# 1045| r0_28(glval) = VariableAddress[#return] : -# 1045| v0_29(void) = ReturnValue : &:r0_28, ~mu0_2 -# 1045| v0_30(void) = UnmodeledUse : mu* -# 1045| v0_31(void) = ExitFunction : +# 1045| r0_10(glval) = CopyValue : r0_9 +# 1045| r0_11(glval) = FunctionAddress[c_str] : +# 1045| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1045| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int) = Load : &:r0_15, ~mu0_2 +#-----| r0_17(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_18(glval) = FieldAddress[i] : r0_17 +# 1045| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 1045| r0_20(int) = Add : r0_16, r0_19 +#-----| r0_21(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_22(glval) = FieldAddress[j] : r0_21 +# 1045| r0_23(int &) = Load : &:r0_22, ~mu0_2 +# 1045| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 1045| r0_25(int) = Sub : r0_20, r0_24 +# 1045| r0_26(glval) = PointerAdd[1] : r0_12, r0_25 +# 1045| r0_27(char) = Load : &:r0_26, ~mu0_2 +# 1045| mu0_28(char) = Store : &:r0_6, r0_27 +# 1045| r0_29(glval) = VariableAddress[#return] : +# 1045| v0_30(void) = ReturnValue : &:r0_29, ~mu0_2 +# 1045| v0_31(void) = UnmodeledUse : mu* +# 1045| v0_32(void) = ExitFunction : # 1068| void RangeBasedFor(vector const&) # 1068| Block 0 @@ -4946,132 +5238,144 @@ ir.cpp: # 1069| r0_5(glval &>) = VariableAddress[(__range)] : # 1069| r0_6(glval &>) = VariableAddress[v] : # 1069| r0_7(vector &) = Load : &:r0_6, ~mu0_2 -# 1069| mu0_8(vector &) = Store : &:r0_5, r0_7 -# 1069| r0_9(glval) = VariableAddress[(__begin)] : -#-----| r0_10(glval &>) = VariableAddress[(__range)] : -#-----| r0_11(vector &) = Load : &:r0_10, ~mu0_2 -# 1069| r0_12(glval) = FunctionAddress[begin] : -# 1069| r0_13(iterator) = Call : func:r0_12, this:r0_11 -# 1069| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| mu0_15(iterator) = Store : &:r0_9, r0_13 -# 1069| r0_16(glval) = VariableAddress[(__end)] : -#-----| r0_17(glval &>) = VariableAddress[(__range)] : -#-----| r0_18(vector &) = Load : &:r0_17, ~mu0_2 -# 1069| r0_19(glval) = FunctionAddress[end] : -# 1069| r0_20(iterator) = Call : func:r0_19, this:r0_18 -# 1069| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| mu0_22(iterator) = Store : &:r0_16, r0_20 -#-----| Goto -> Block 1 +# 1069| r0_8(glval>) = CopyValue : r0_7 +# 1069| r0_9(vector &) = CopyValue : r0_8 +# 1069| mu0_10(vector &) = Store : &:r0_5, r0_9 +# 1069| r0_11(glval) = VariableAddress[(__begin)] : +#-----| r0_12(glval &>) = VariableAddress[(__range)] : +#-----| r0_13(vector &) = Load : &:r0_12, ~mu0_2 +#-----| r0_14(glval>) = CopyValue : r0_13 +# 1069| r0_15(glval) = FunctionAddress[begin] : +# 1069| r0_16(iterator) = Call : func:r0_15, this:r0_14 +# 1069| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| mu0_18(iterator) = Store : &:r0_11, r0_16 +# 1069| r0_19(glval) = VariableAddress[(__end)] : +#-----| r0_20(glval &>) = VariableAddress[(__range)] : +#-----| r0_21(vector &) = Load : &:r0_20, ~mu0_2 +#-----| r0_22(glval>) = CopyValue : r0_21 +# 1069| r0_23(glval) = FunctionAddress[end] : +# 1069| r0_24(iterator) = Call : func:r0_23, this:r0_22 +# 1069| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| mu0_26(iterator) = Store : &:r0_19, r0_24 +#-----| Goto -> Block 3 -#-----| Block 1 -#-----| r1_0(glval) = VariableAddress[(__begin)] : -#-----| r1_1(glval) = Convert : r1_0 -# 1069| r1_2(glval) = FunctionAddress[operator!=] : -#-----| r1_3(glval) = VariableAddress[(__end)] : -#-----| r1_4(iterator) = Load : &:r1_3, ~mu0_2 -# 1069| r1_5(bool) = Call : func:r1_2, this:r1_1, 0:r1_4 -# 1069| mu1_6(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| v1_7(void) = ConditionalBranch : r1_5 -#-----| False -> Block 5 -#-----| True -> Block 2 +# 1077| Block 1 +# 1077| v1_0(void) = NoOp : +#-----| Goto -> Block 2 -# 1069| Block 2 -# 1069| r2_0(glval) = VariableAddress[e] : -#-----| r2_1(glval) = VariableAddress[(__begin)] : -#-----| r2_2(glval) = Convert : r2_1 -# 1069| r2_3(glval) = FunctionAddress[operator*] : -# 1069| r2_4(int &) = Call : func:r2_3, this:r2_2 -# 1069| mu2_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| r2_6(int) = Load : &:r2_4, ~mu0_2 -# 1069| mu2_7(int) = Store : &:r2_0, r2_6 -# 1070| r2_8(glval) = VariableAddress[e] : -# 1070| r2_9(int) = Load : &:r2_8, ~mu0_2 -# 1070| r2_10(int) = Constant[0] : -# 1070| r2_11(bool) = CompareGT : r2_9, r2_10 -# 1070| v2_12(void) = ConditionalBranch : r2_11 -#-----| False -> Block 4 -#-----| True -> Block 3 +# 1079| Block 2 +# 1079| v2_0(void) = NoOp : +# 1080| v2_1(void) = NoOp : +# 1068| v2_2(void) = ReturnVoid : +# 1068| v2_3(void) = UnmodeledUse : mu* +# 1068| v2_4(void) = ExitFunction : -# 1071| Block 3 -# 1071| v3_0(void) = NoOp : -#-----| Goto -> Block 4 +#-----| Block 3 +#-----| r3_0(glval) = VariableAddress[(__begin)] : +#-----| r3_1(glval) = Convert : r3_0 +# 1069| r3_2(glval) = FunctionAddress[operator!=] : +#-----| r3_3(glval) = VariableAddress[(__end)] : +#-----| r3_4(iterator) = Load : &:r3_3, ~mu0_2 +# 1069| r3_5(bool) = Call : func:r3_2, this:r3_1, 0:r3_4 +# 1069| mu3_6(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| v3_7(void) = ConditionalBranch : r3_5 +#-----| False -> Block 7 +#-----| True -> Block 4 # 1069| Block 4 -# 1069| v4_0(void) = NoOp : -#-----| r4_1(glval) = VariableAddress[(__begin)] : -# 1069| r4_2(glval) = FunctionAddress[operator++] : -# 1069| r4_3(iterator &) = Call : func:r4_2, this:r4_1 -# 1069| mu4_4(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto (back edge) -> Block 1 +# 1069| r4_0(glval) = VariableAddress[e] : +#-----| r4_1(glval) = VariableAddress[(__begin)] : +#-----| r4_2(glval) = Convert : r4_1 +# 1069| r4_3(glval) = FunctionAddress[operator*] : +# 1069| r4_4(int &) = Call : func:r4_3, this:r4_2 +# 1069| mu4_5(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| r4_6(int) = Load : &:r4_4, ~mu0_2 +# 1069| mu4_7(int) = Store : &:r4_0, r4_6 +# 1070| r4_8(glval) = VariableAddress[e] : +# 1070| r4_9(int) = Load : &:r4_8, ~mu0_2 +# 1070| r4_10(int) = Constant[0] : +# 1070| r4_11(bool) = CompareGT : r4_9, r4_10 +# 1070| v4_12(void) = ConditionalBranch : r4_11 +#-----| False -> Block 6 +#-----| True -> Block 5 -# 1075| Block 5 -# 1075| r5_0(glval &>) = VariableAddress[(__range)] : -# 1075| r5_1(glval &>) = VariableAddress[v] : -# 1075| r5_2(vector &) = Load : &:r5_1, ~mu0_2 -# 1075| mu5_3(vector &) = Store : &:r5_0, r5_2 -# 1075| r5_4(glval) = VariableAddress[(__begin)] : -#-----| r5_5(glval &>) = VariableAddress[(__range)] : -#-----| r5_6(vector &) = Load : &:r5_5, ~mu0_2 -# 1075| r5_7(glval) = FunctionAddress[begin] : -# 1075| r5_8(iterator) = Call : func:r5_7, this:r5_6 -# 1075| mu5_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| mu5_10(iterator) = Store : &:r5_4, r5_8 -# 1075| r5_11(glval) = VariableAddress[(__end)] : -#-----| r5_12(glval &>) = VariableAddress[(__range)] : -#-----| r5_13(vector &) = Load : &:r5_12, ~mu0_2 -# 1075| r5_14(glval) = FunctionAddress[end] : -# 1075| r5_15(iterator) = Call : func:r5_14, this:r5_13 -# 1075| mu5_16(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| mu5_17(iterator) = Store : &:r5_11, r5_15 +# 1071| Block 5 +# 1071| v5_0(void) = NoOp : #-----| Goto -> Block 6 -#-----| Block 6 -#-----| r6_0(glval) = VariableAddress[(__begin)] : -#-----| r6_1(glval) = Convert : r6_0 -# 1075| r6_2(glval) = FunctionAddress[operator!=] : -#-----| r6_3(glval) = VariableAddress[(__end)] : -#-----| r6_4(iterator) = Load : &:r6_3, ~mu0_2 -# 1075| r6_5(bool) = Call : func:r6_2, this:r6_1, 0:r6_4 -# 1075| mu6_6(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| v6_7(void) = ConditionalBranch : r6_5 -#-----| False -> Block 10 -#-----| True -> Block 8 +# 1069| Block 6 +# 1069| v6_0(void) = NoOp : +#-----| r6_1(glval) = VariableAddress[(__begin)] : +# 1069| r6_2(glval) = FunctionAddress[operator++] : +# 1069| r6_3(iterator &) = Call : func:r6_2, this:r6_1 +# 1069| mu6_4(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| r6_5(glval) = CopyValue : r6_3 +#-----| Goto (back edge) -> Block 3 -#-----| Block 7 -#-----| r7_0(glval) = VariableAddress[(__begin)] : -# 1075| r7_1(glval) = FunctionAddress[operator++] : -# 1075| r7_2(iterator &) = Call : func:r7_1, this:r7_0 -# 1075| mu7_3(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto (back edge) -> Block 6 +# 1075| Block 7 +# 1075| r7_0(glval &>) = VariableAddress[(__range)] : +# 1075| r7_1(glval &>) = VariableAddress[v] : +# 1075| r7_2(vector &) = Load : &:r7_1, ~mu0_2 +# 1075| r7_3(glval>) = CopyValue : r7_2 +# 1075| r7_4(vector &) = CopyValue : r7_3 +# 1075| mu7_5(vector &) = Store : &:r7_0, r7_4 +# 1075| r7_6(glval) = VariableAddress[(__begin)] : +#-----| r7_7(glval &>) = VariableAddress[(__range)] : +#-----| r7_8(vector &) = Load : &:r7_7, ~mu0_2 +#-----| r7_9(glval>) = CopyValue : r7_8 +# 1075| r7_10(glval) = FunctionAddress[begin] : +# 1075| r7_11(iterator) = Call : func:r7_10, this:r7_9 +# 1075| mu7_12(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| mu7_13(iterator) = Store : &:r7_6, r7_11 +# 1075| r7_14(glval) = VariableAddress[(__end)] : +#-----| r7_15(glval &>) = VariableAddress[(__range)] : +#-----| r7_16(vector &) = Load : &:r7_15, ~mu0_2 +#-----| r7_17(glval>) = CopyValue : r7_16 +# 1075| r7_18(glval) = FunctionAddress[end] : +# 1075| r7_19(iterator) = Call : func:r7_18, this:r7_17 +# 1075| mu7_20(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| mu7_21(iterator) = Store : &:r7_14, r7_19 +#-----| Goto -> Block 8 -# 1075| Block 8 -# 1075| r8_0(glval) = VariableAddress[e] : -#-----| r8_1(glval) = VariableAddress[(__begin)] : -#-----| r8_2(glval) = Convert : r8_1 -# 1075| r8_3(glval) = FunctionAddress[operator*] : -# 1075| r8_4(int &) = Call : func:r8_3, this:r8_2 -# 1075| mu8_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| r8_6(glval) = Convert : r8_4 -# 1075| mu8_7(int &) = Store : &:r8_0, r8_6 -# 1076| r8_8(glval) = VariableAddress[e] : -# 1076| r8_9(int &) = Load : &:r8_8, ~mu0_2 -# 1076| r8_10(int) = Load : &:r8_9, ~mu0_2 -# 1076| r8_11(int) = Constant[5] : -# 1076| r8_12(bool) = CompareLT : r8_10, r8_11 -# 1076| v8_13(void) = ConditionalBranch : r8_12 -#-----| False -> Block 7 -#-----| True -> Block 9 +#-----| Block 8 +#-----| r8_0(glval) = VariableAddress[(__begin)] : +#-----| r8_1(glval) = Convert : r8_0 +# 1075| r8_2(glval) = FunctionAddress[operator!=] : +#-----| r8_3(glval) = VariableAddress[(__end)] : +#-----| r8_4(iterator) = Load : &:r8_3, ~mu0_2 +# 1075| r8_5(bool) = Call : func:r8_2, this:r8_1, 0:r8_4 +# 1075| mu8_6(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| v8_7(void) = ConditionalBranch : r8_5 +#-----| False -> Block 2 +#-----| True -> Block 10 -# 1077| Block 9 -# 1077| v9_0(void) = NoOp : -#-----| Goto -> Block 10 +#-----| Block 9 +#-----| r9_0(glval) = VariableAddress[(__begin)] : +# 1075| r9_1(glval) = FunctionAddress[operator++] : +# 1075| r9_2(iterator &) = Call : func:r9_1, this:r9_0 +# 1075| mu9_3(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| r9_4(glval) = CopyValue : r9_2 +#-----| Goto (back edge) -> Block 8 -# 1079| Block 10 -# 1079| v10_0(void) = NoOp : -# 1080| v10_1(void) = NoOp : -# 1068| v10_2(void) = ReturnVoid : -# 1068| v10_3(void) = UnmodeledUse : mu* -# 1068| v10_4(void) = ExitFunction : +# 1075| Block 10 +# 1075| r10_0(glval) = VariableAddress[e] : +#-----| r10_1(glval) = VariableAddress[(__begin)] : +#-----| r10_2(glval) = Convert : r10_1 +# 1075| r10_3(glval) = FunctionAddress[operator*] : +# 1075| r10_4(int &) = Call : func:r10_3, this:r10_2 +# 1075| mu10_5(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| r10_6(glval) = CopyValue : r10_4 +# 1075| r10_7(glval) = Convert : r10_6 +# 1075| r10_8(int &) = CopyValue : r10_7 +# 1075| mu10_9(int &) = Store : &:r10_0, r10_8 +# 1076| r10_10(glval) = VariableAddress[e] : +# 1076| r10_11(int &) = Load : &:r10_10, ~mu0_2 +# 1076| r10_12(int) = Load : &:r10_11, ~mu0_2 +# 1076| r10_13(int) = Constant[5] : +# 1076| r10_14(bool) = CompareLT : r10_12, r10_13 +# 1076| v10_15(void) = ConditionalBranch : r10_14 +#-----| False -> Block 9 +#-----| True -> Block 1 # 1099| int AsmStmt(int) # 1099| Block 0 @@ -5154,6 +5458,7 @@ ir.cpp: # 1130| r2_2(int) = Constant[1] : # 1130| r2_3(int) = Add : r2_1, r2_2 # 1130| mu2_4(int) = Store : &:r2_0, r2_3 +# 1130| r2_5(glval) = CopyValue : r2_0 #-----| Goto (back edge) -> Block 1 # 1130| Block 3 @@ -5219,6 +5524,7 @@ ir.cpp: # 1140| r6_4(int) = Load : &:r6_3, ~mu0_2 # 1140| r6_5(glval) = VariableAddress[x] : # 1140| mu6_6(int) = Store : &:r6_5, r6_4 +# 1140| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 1140| Block 7 @@ -5235,6 +5541,7 @@ ir.cpp: # 1142| r8_0(int) = Constant[7] : # 1142| r8_1(glval) = VariableAddress[x] : # 1142| mu8_2(int) = Store : &:r8_1, r8_0 +# 1142| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 13 # 1144| Block 9 @@ -5309,28 +5616,30 @@ ir.cpp: # 1156| r0_34(int) = Load : &:r0_33, ~mu0_2 # 1156| r0_35(glval) = PointerAdd[4] : r0_32, r0_34 # 1156| mu0_36(int) = Store : &:r0_35, r0_31 -# 1157| r0_37(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : -# 1157| r0_38(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1157| r0_39(__attribute((vector_size(16))) int) = Load : &:r0_38, ~mu0_2 -# 1157| r0_40(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1157| r0_41(__attribute((vector_size(16))) int) = Load : &:r0_40, ~mu0_2 -#-----| r0_42(int) = Constant[3] : -# 1157| r0_43(int) = Constant[2] : -# 1157| r0_44(int) = Constant[1] : -# 1157| r0_45(int) = Constant[0] : -# 1157| r0_46(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_39, 1:r0_41, 2:r0_42, 3:r0_43, 4:r0_44, 5:r0_45 -# 1157| mu0_47(__attribute((vector_size(16))) int) = Store : &:r0_37, r0_46 -# 1158| r0_48(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1158| r0_49(__attribute((vector_size(16))) int) = Load : &:r0_48, ~mu0_2 -# 1158| r0_50(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : -# 1158| r0_51(__attribute((vector_size(16))) int) = Load : &:r0_50, ~mu0_2 -# 1158| r0_52(__attribute((vector_size(16))) int) = Add : r0_49, r0_51 -# 1158| r0_53(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1158| mu0_54(__attribute((vector_size(16))) int) = Store : &:r0_53, r0_52 -# 1159| v0_55(void) = NoOp : -# 1153| v0_56(void) = ReturnVoid : -# 1153| v0_57(void) = UnmodeledUse : mu* -# 1153| v0_58(void) = ExitFunction : +# 1156| r0_37(glval) = CopyValue : r0_35 +# 1157| r0_38(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : +# 1157| r0_39(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1157| r0_40(__attribute((vector_size(16))) int) = Load : &:r0_39, ~mu0_2 +# 1157| r0_41(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1157| r0_42(__attribute((vector_size(16))) int) = Load : &:r0_41, ~mu0_2 +#-----| r0_43(int) = Constant[3] : +# 1157| r0_44(int) = Constant[2] : +# 1157| r0_45(int) = Constant[1] : +# 1157| r0_46(int) = Constant[0] : +# 1157| r0_47(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_40, 1:r0_42, 2:r0_43, 3:r0_44, 4:r0_45, 5:r0_46 +# 1157| mu0_48(__attribute((vector_size(16))) int) = Store : &:r0_38, r0_47 +# 1158| r0_49(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1158| r0_50(__attribute((vector_size(16))) int) = Load : &:r0_49, ~mu0_2 +# 1158| r0_51(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : +# 1158| r0_52(__attribute((vector_size(16))) int) = Load : &:r0_51, ~mu0_2 +# 1158| r0_53(__attribute((vector_size(16))) int) = Add : r0_50, r0_52 +# 1158| r0_54(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1158| mu0_55(__attribute((vector_size(16))) int) = Store : &:r0_54, r0_53 +# 1158| r0_56(glval<__attribute((vector_size(16))) int>) = CopyValue : r0_54 +# 1159| v0_57(void) = NoOp : +# 1153| v0_58(void) = ReturnVoid : +# 1153| v0_59(void) = UnmodeledUse : mu* +# 1153| v0_60(void) = ExitFunction : perf-regression.cpp: # 6| void Big::Big() diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index fe11d99f31f..f3f5101dcb4 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -211,8 +211,10 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| m1_6(char) = Store : &:r1_2, r1_0 -# 70| m1_7(unknown) = Chi : total:m3_0, partial:m1_6 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| m1_7(char) = Store : &:r1_6, r1_0 +# 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7 +# 70| r1_9(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -222,7 +224,7 @@ ssa.cpp: # 68| v2_3(void) = ExitFunction : # 69| Block 3 -# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_7 +# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_8 # 69| m3_1(int) = Phi : from 0:m0_4, from 1:m3_7 # 69| m3_2(char *) = Phi : from 0:m0_6, from 1:m1_5 # 69| r3_3(glval) = VariableAddress[n] : @@ -262,20 +264,23 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 81| r1_3(int) = Constant[4] : -# 81| r1_4(glval) = VariableAddress[y] : -# 81| m1_5(int) = Store : &:r1_4, r1_3 +# 80| r1_3(glval) = CopyValue : r1_1 +# 81| r1_4(int) = Constant[4] : +# 81| r1_5(glval) = VariableAddress[y] : +# 81| m1_6(int) = Store : &:r1_5, r1_4 +# 81| r1_7(glval) = CopyValue : r1_5 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 +# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -323,14 +328,15 @@ ssa.cpp: # 96| m0_9(Point) = Store : &:r0_6, r0_8 # 97| r0_10(glval) = FunctionAddress[Escape] : # 97| r0_11(glval) = VariableAddress[a] : -# 97| r0_12(void *) = Convert : r0_11 -# 97| v0_13(void) = Call : func:r0_10, 0:r0_12 -# 97| m0_14(unknown) = ^CallSideEffect : ~m0_5 -# 97| m0_15(unknown) = Chi : total:m0_5, partial:m0_14 -# 98| v0_16(void) = NoOp : -# 95| v0_17(void) = ReturnVoid : -# 95| v0_18(void) = UnmodeledUse : mu* -# 95| v0_19(void) = ExitFunction : +# 97| r0_12(Point *) = CopyValue : r0_11 +# 97| r0_13(void *) = Convert : r0_12 +# 97| v0_14(void) = Call : func:r0_10, 0:r0_13 +# 97| m0_15(unknown) = ^CallSideEffect : ~m0_5 +# 97| m0_16(unknown) = Chi : total:m0_5, partial:m0_15 +# 98| v0_17(void) = NoOp : +# 95| v0_18(void) = ReturnVoid : +# 95| v0_19(void) = UnmodeledUse : mu* +# 95| v0_20(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -374,14 +380,15 @@ ssa.cpp: # 107| m0_15(int) = Store : &:r0_11, r0_14 # 108| r0_16(glval) = FunctionAddress[Escape] : # 108| r0_17(glval) = VariableAddress[a] : -# 108| r0_18(void *) = Convert : r0_17 -# 108| v0_19(void) = Call : func:r0_16, 0:r0_18 -# 108| m0_20(unknown) = ^CallSideEffect : ~m0_5 -# 108| m0_21(unknown) = Chi : total:m0_5, partial:m0_20 -# 109| v0_22(void) = NoOp : -# 105| v0_23(void) = ReturnVoid : -# 105| v0_24(void) = UnmodeledUse : mu* -# 105| v0_25(void) = ExitFunction : +# 108| r0_18(Point *) = CopyValue : r0_17 +# 108| r0_19(void *) = Convert : r0_18 +# 108| v0_20(void) = Call : func:r0_16, 0:r0_19 +# 108| m0_21(unknown) = ^CallSideEffect : ~m0_5 +# 108| m0_22(unknown) = Chi : total:m0_5, partial:m0_21 +# 109| v0_23(void) = NoOp : +# 105| v0_24(void) = ReturnVoid : +# 105| v0_25(void) = UnmodeledUse : mu* +# 105| v0_26(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -441,14 +448,15 @@ ssa.cpp: # 118| m0_23(Point) = Store : &:r0_20, r0_22 # 119| r0_24(glval) = FunctionAddress[Escape] : # 119| r0_25(glval) = VariableAddress[a] : -# 119| r0_26(void *) = Convert : r0_25 -# 119| v0_27(void) = Call : func:r0_24, 0:r0_26 -# 119| m0_28(unknown) = ^CallSideEffect : ~m0_19 -# 119| m0_29(unknown) = Chi : total:m0_19, partial:m0_28 -# 120| v0_30(void) = NoOp : -# 116| v0_31(void) = ReturnVoid : -# 116| v0_32(void) = UnmodeledUse : mu* -# 116| v0_33(void) = ExitFunction : +# 119| r0_26(Point *) = CopyValue : r0_25 +# 119| r0_27(void *) = Convert : r0_26 +# 119| v0_28(void) = Call : func:r0_24, 0:r0_27 +# 119| m0_29(unknown) = ^CallSideEffect : ~m0_19 +# 119| m0_30(unknown) = Chi : total:m0_19, partial:m0_29 +# 120| v0_31(void) = NoOp : +# 116| v0_32(void) = ReturnVoid : +# 116| v0_33(void) = UnmodeledUse : mu* +# 116| v0_34(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -484,6 +492,7 @@ ssa.cpp: # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| m1_4(int) = Store : &:r1_3, r1_1 # 125| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 125| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -493,6 +502,7 @@ ssa.cpp: # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| m2_4(int) = Store : &:r2_3, r2_1 # 128| m2_5(Point) = Chi : total:m0_18, partial:m2_4 +# 128| r2_6(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -546,6 +556,7 @@ ssa.cpp: # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| m1_4(int) = Store : &:r1_3, r1_1 # 137| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 137| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -553,6 +564,7 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| m2_3(Point) = Store : &:r2_2, r2_1 +# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -602,6 +614,7 @@ ssa.cpp: # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| m1_4(int) = Store : &:r1_3, r1_1 # 148| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 148| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -609,6 +622,7 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| m2_3(Point) = Store : &:r2_2, r2_1 +# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -657,6 +671,7 @@ ssa.cpp: # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| m1_5(int) = Store : &:r1_4, r1_1 # 159| m1_6(Rect) = Chi : total:m0_18, partial:m1_5 +# 159| r1_7(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -664,6 +679,7 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| m2_3(Rect) = Store : &:r2_2, r2_1 +# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -698,19 +714,22 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| m0_17(int) = Store : &:r0_16, r0_14 -# 175| r0_18(glval) = VariableAddress[w] : -# 175| r0_19(glval) = FieldAddress[f] : r0_18 -# 175| r0_20(int) = Load : &:r0_19, m0_17 -# 175| r0_21(glval) = VariableAddress[a] : -# 175| m0_22(int) = Store : &:r0_21, r0_20 -# 176| r0_23(glval) = VariableAddress[w] : -# 176| r0_24(Wrapper) = Load : &:r0_23, ~m0_17 -# 176| r0_25(glval) = VariableAddress[x] : -# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 -# 177| v0_27(void) = NoOp : -# 171| v0_28(void) = ReturnVoid : -# 171| v0_29(void) = UnmodeledUse : mu* -# 171| v0_30(void) = ExitFunction : +# 174| r0_18(glval) = CopyValue : r0_16 +# 175| r0_19(glval) = VariableAddress[w] : +# 175| r0_20(glval) = FieldAddress[f] : r0_19 +# 175| r0_21(int) = Load : &:r0_20, m0_17 +# 175| r0_22(glval) = VariableAddress[a] : +# 175| m0_23(int) = Store : &:r0_22, r0_21 +# 175| r0_24(glval) = CopyValue : r0_22 +# 176| r0_25(glval) = VariableAddress[w] : +# 176| r0_26(Wrapper) = Load : &:r0_25, ~m0_17 +# 176| r0_27(glval) = VariableAddress[x] : +# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 +# 176| r0_29(glval) = CopyValue : r0_27 +# 177| v0_30(void) = NoOp : +# 171| v0_31(void) = ReturnVoid : +# 171| v0_32(void) = UnmodeledUse : mu* +# 171| v0_33(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -791,19 +810,21 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 200| r0_30(glval) = CopyValue : r0_26 +# 201| r0_31(glval) = FunctionAddress[abs] : +# 201| r0_32(glval) = VariableAddress[x] : +# 201| r0_33(int) = Load : &:r0_32, m0_8 +# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 +# 201| r0_35(glval) = VariableAddress[ret] : +# 201| r0_36(int) = Load : &:r0_35, m0_29 +# 201| r0_37(int) = Add : r0_36, r0_34 +# 201| m0_38(int) = Store : &:r0_35, r0_37 +# 201| r0_39(glval) = CopyValue : r0_35 +# 202| r0_40(glval) = VariableAddress[#return] : +# 202| r0_41(glval) = VariableAddress[ret] : +# 202| r0_42(int) = Load : &:r0_41, m0_38 +# 202| m0_43(int) = Store : &:r0_40, r0_42 +# 198| r0_44(glval) = VariableAddress[#return] : +# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 +# 198| v0_46(void) = UnmodeledUse : mu* +# 198| v0_47(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index ce0d9323340..57330c88ce9 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -214,7 +214,9 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| mu1_6(char) = Store : &:r1_2, r1_0 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| mu1_7(char) = Store : &:r1_6, r1_0 +# 70| r1_8(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -263,20 +265,23 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 81| r1_3(int) = Constant[4] : -# 81| r1_4(glval) = VariableAddress[y] : -# 81| m1_5(int) = Store : &:r1_4, r1_3 +# 80| r1_3(glval) = CopyValue : r1_1 +# 81| r1_4(int) = Constant[4] : +# 81| r1_5(glval) = VariableAddress[y] : +# 81| m1_6(int) = Store : &:r1_5, r1_4 +# 81| r1_7(glval) = CopyValue : r1_5 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 +# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -323,13 +328,14 @@ ssa.cpp: # 96| m0_8(Point) = Store : &:r0_5, r0_7 # 97| r0_9(glval) = FunctionAddress[Escape] : # 97| r0_10(glval) = VariableAddress[a] : -# 97| r0_11(void *) = Convert : r0_10 -# 97| v0_12(void) = Call : func:r0_9, 0:r0_11 -# 97| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 98| v0_14(void) = NoOp : -# 95| v0_15(void) = ReturnVoid : -# 95| v0_16(void) = UnmodeledUse : mu* -# 95| v0_17(void) = ExitFunction : +# 97| r0_11(Point *) = CopyValue : r0_10 +# 97| r0_12(void *) = Convert : r0_11 +# 97| v0_13(void) = Call : func:r0_9, 0:r0_12 +# 97| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +# 98| v0_15(void) = NoOp : +# 95| v0_16(void) = ReturnVoid : +# 95| v0_17(void) = UnmodeledUse : mu* +# 95| v0_18(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -372,13 +378,14 @@ ssa.cpp: # 107| m0_14(int) = Store : &:r0_10, r0_13 # 108| r0_15(glval) = FunctionAddress[Escape] : # 108| r0_16(glval) = VariableAddress[a] : -# 108| r0_17(void *) = Convert : r0_16 -# 108| v0_18(void) = Call : func:r0_15, 0:r0_17 -# 108| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 109| v0_20(void) = NoOp : -# 105| v0_21(void) = ReturnVoid : -# 105| v0_22(void) = UnmodeledUse : mu* -# 105| v0_23(void) = ExitFunction : +# 108| r0_17(Point *) = CopyValue : r0_16 +# 108| r0_18(void *) = Convert : r0_17 +# 108| v0_19(void) = Call : func:r0_15, 0:r0_18 +# 108| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 109| v0_21(void) = NoOp : +# 105| v0_22(void) = ReturnVoid : +# 105| v0_23(void) = UnmodeledUse : mu* +# 105| v0_24(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -433,13 +440,14 @@ ssa.cpp: # 118| m0_20(Point) = Store : &:r0_17, r0_19 # 119| r0_21(glval) = FunctionAddress[Escape] : # 119| r0_22(glval) = VariableAddress[a] : -# 119| r0_23(void *) = Convert : r0_22 -# 119| v0_24(void) = Call : func:r0_21, 0:r0_23 -# 119| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 120| v0_26(void) = NoOp : -# 116| v0_27(void) = ReturnVoid : -# 116| v0_28(void) = UnmodeledUse : mu* -# 116| v0_29(void) = ExitFunction : +# 119| r0_23(Point *) = CopyValue : r0_22 +# 119| r0_24(void *) = Convert : r0_23 +# 119| v0_25(void) = Call : func:r0_21, 0:r0_24 +# 119| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 120| v0_27(void) = NoOp : +# 116| v0_28(void) = ReturnVoid : +# 116| v0_29(void) = UnmodeledUse : mu* +# 116| v0_30(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -472,6 +480,7 @@ ssa.cpp: # 125| r1_2(glval) = VariableAddress[a] : # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| mu1_4(int) = Store : &:r1_3, r1_1 +# 125| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -480,6 +489,7 @@ ssa.cpp: # 128| r2_2(glval) = VariableAddress[a] : # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| mu2_4(int) = Store : &:r2_3, r2_1 +# 128| r2_5(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -528,6 +538,7 @@ ssa.cpp: # 137| r1_2(glval) = VariableAddress[a] : # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| mu1_4(int) = Store : &:r1_3, r1_1 +# 137| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -535,6 +546,7 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| mu2_3(Point) = Store : &:r2_2, r2_1 +# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -579,6 +591,7 @@ ssa.cpp: # 148| r1_2(glval) = VariableAddress[a] : # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| mu1_4(int) = Store : &:r1_3, r1_1 +# 148| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -586,6 +599,7 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| mu2_3(Point) = Store : &:r2_2, r2_1 +# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -630,6 +644,7 @@ ssa.cpp: # 159| r1_3(glval) = FieldAddress[topLeft] : r1_2 # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| mu1_5(int) = Store : &:r1_4, r1_1 +# 159| r1_6(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -637,6 +652,7 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| mu2_3(Rect) = Store : &:r2_2, r2_1 +# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -670,19 +686,22 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| mu0_17(int) = Store : &:r0_16, r0_14 -# 175| r0_18(glval) = VariableAddress[w] : -# 175| r0_19(glval) = FieldAddress[f] : r0_18 -# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 175| r0_21(glval) = VariableAddress[a] : -# 175| m0_22(int) = Store : &:r0_21, r0_20 -# 176| r0_23(glval) = VariableAddress[w] : -# 176| r0_24(Wrapper) = Load : &:r0_23, ~mu0_2 -# 176| r0_25(glval) = VariableAddress[x] : -# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 -# 177| v0_27(void) = NoOp : -# 171| v0_28(void) = ReturnVoid : -# 171| v0_29(void) = UnmodeledUse : mu* -# 171| v0_30(void) = ExitFunction : +# 174| r0_18(glval) = CopyValue : r0_16 +# 175| r0_19(glval) = VariableAddress[w] : +# 175| r0_20(glval) = FieldAddress[f] : r0_19 +# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 175| r0_22(glval) = VariableAddress[a] : +# 175| m0_23(int) = Store : &:r0_22, r0_21 +# 175| r0_24(glval) = CopyValue : r0_22 +# 176| r0_25(glval) = VariableAddress[w] : +# 176| r0_26(Wrapper) = Load : &:r0_25, ~mu0_2 +# 176| r0_27(glval) = VariableAddress[x] : +# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 +# 176| r0_29(glval) = CopyValue : r0_27 +# 177| v0_30(void) = NoOp : +# 171| v0_31(void) = ReturnVoid : +# 171| v0_32(void) = UnmodeledUse : mu* +# 171| v0_33(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -757,19 +776,21 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 200| r0_30(glval) = CopyValue : r0_26 +# 201| r0_31(glval) = FunctionAddress[abs] : +# 201| r0_32(glval) = VariableAddress[x] : +# 201| r0_33(int) = Load : &:r0_32, m0_8 +# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 +# 201| r0_35(glval) = VariableAddress[ret] : +# 201| r0_36(int) = Load : &:r0_35, m0_29 +# 201| r0_37(int) = Add : r0_36, r0_34 +# 201| m0_38(int) = Store : &:r0_35, r0_37 +# 201| r0_39(glval) = CopyValue : r0_35 +# 202| r0_40(glval) = VariableAddress[#return] : +# 202| r0_41(glval) = VariableAddress[ret] : +# 202| r0_42(int) = Load : &:r0_41, m0_38 +# 202| m0_43(int) = Store : &:r0_40, r0_42 +# 198| r0_44(glval) = VariableAddress[#return] : +# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 +# 198| v0_46(void) = UnmodeledUse : mu* +# 198| v0_47(void) = ExitFunction : From a34c0d4200667c9a9c5ee6bd769ca4e8cff7311e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 23 Sep 2019 15:39:32 +0200 Subject: [PATCH 003/232] C++: Autoformat TranslatedExpr.qll --- .../code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index e9e7cf59cb0..fb6cc3f8570 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -2556,8 +2556,8 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) { expr instanceof AddressOfExpr or expr instanceof BuiltInOperationBuiltInAddressOf - // No case for ParenthesisExpr to avoid getting too many instructions or + // No case for ParenthesisExpr to avoid getting too many instructions expr instanceof ReferenceDereferenceExpr or expr instanceof ReferenceToExpr From 61b372b062d3f0262cbe90c3cb96de21e9276f28 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Mon, 23 Sep 2019 17:30:05 +0100 Subject: [PATCH 004/232] Add Go to supported languages topic and update release number --- docs/language/global-sphinx-files/global-conf.py | 4 ++-- docs/language/support/versions-compilers.csv | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/language/global-sphinx-files/global-conf.py b/docs/language/global-sphinx-files/global-conf.py index 260783d9117..84912a8c538 100644 --- a/docs/language/global-sphinx-files/global-conf.py +++ b/docs/language/global-sphinx-files/global-conf.py @@ -56,9 +56,9 @@ def setup(sphinx): # built documents. # # The short X.Y version. -version = u'1.22' +version = u'1.22.1' # The full version, including alpha/beta/rc tags. -release = u'1.22' +release = u'1.22.1' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv index 4a59214c47f..b70ac87335f 100644 --- a/docs/language/support/versions-compilers.csv +++ b/docs/language/support/versions-compilers.csv @@ -10,6 +10,7 @@ C#,C# up to 7.3. with .NET up to 4.8 [3]_.,"Microsoft Visual Studio up to 2019, .NET Core up to 2.2","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" COBOL,ANSI 85 or newer [4]_.,Not applicable,"``.cbl``, ``.CBL``, ``.cpy``, ``.CPY``, ``.copy``, ``.COPY``" +Go, "Go up to 1.13", "Go 1.11 or more recent", ``.go`` Java,"Java 6 to 12 [5]_.","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [6]_.",``.java`` From b75bf06649df642ed47b5686ed874c82834ea632 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 24 Sep 2019 13:00:21 +0200 Subject: [PATCH 005/232] C++: Accept test changes in other IR tests --- .../signanalysis/SignAnalysis.expected | 30 ++ .../syntax-zoo/aliased_ssa_sanity.expected | 2 +- .../syntax-zoo/raw_sanity.expected | 21 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 2 +- .../GlobalValueNumbering/ir_gvn.expected | 262 ++++++++++-------- 5 files changed, 192 insertions(+), 125 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected index cdc15c4b45a..4dc280b6ca9 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected @@ -13,6 +13,7 @@ | bounded_bounds.c:16:12:16:12 | Load: x | negative strictlyNegative | | bounded_bounds.c:16:12:16:12 | Store: x | negative strictlyNegative | | inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive | +| inline_assembly.c:10:3:10:7 | CopyValue: ... = ... | positive strictlyPositive | | inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive | | inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive | | inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive | @@ -27,8 +28,10 @@ | minmax.c:18:37:18:37 | Load: x | positive strictlyPositive | | minmax.c:18:40:18:40 | Load: y | positive strictlyPositive | | minmax.c:18:43:18:43 | Load: z | positive strictlyPositive | +| minmax.c:20:2:24:3 | CopyValue: ... = ... | positive | | minmax.c:20:2:24:3 | Store: ... = ... | positive | | minmax.c:20:6:24:3 | CopyValue: (statement expression) | positive | +| minmax.c:22:18:22:22 | CopyValue: ... = ... | positive strictlyPositive | | minmax.c:22:18:22:22 | Store: ... = ... | positive strictlyPositive | | minmax.c:22:22:22:22 | Load: x | positive strictlyPositive | | minmax.c:23:3:23:3 | Load: t | positive | @@ -37,6 +40,7 @@ | minmax.c:26:40:26:40 | Load: y | positive strictlyPositive | | minmax.c:26:43:26:43 | Load: z | positive | | test.c:7:10:7:10 | Phi: p | positive | +| test.c:8:5:8:19 | CopyValue: ... = ... | positive strictlyPositive | | test.c:8:5:8:19 | Store: ... = ... | positive strictlyPositive | | test.c:8:13:8:17 | Load: count | positive | | test.c:8:13:8:19 | Add: ... + ... | positive strictlyPositive | @@ -44,6 +48,7 @@ | test.c:10:10:10:14 | Load: count | positive | | test.c:10:10:10:14 | Store: count | positive | | test.c:15:10:15:10 | Phi: p | positive | +| test.c:16:5:16:26 | CopyValue: ... = ... | positive | | test.c:16:5:16:26 | Store: ... = ... | positive | | test.c:16:13:16:26 | Rem: ... % ... | positive | | test.c:16:14:16:18 | Load: count | positive | @@ -57,6 +62,7 @@ | test.c:24:5:24:11 | Constant: ... ++ | positive strictlyPositive | | test.c:24:5:24:11 | Load: ... ++ | positive | | test.c:24:5:24:11 | Store: ... ++ | positive strictlyPositive | +| test.c:25:5:25:22 | CopyValue: ... = ... | positive | | test.c:25:5:25:22 | Store: ... = ... | positive | | test.c:25:13:25:17 | Load: count | positive strictlyPositive | | test.c:25:13:25:22 | Rem: ... % ... | positive | @@ -67,6 +73,7 @@ | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:19:33:19 | Constant: 2 | positive strictlyPositive | +| test.c:33:22:33:28 | CopyValue: ... = ... | positive strictlyPositive | | test.c:33:22:33:28 | Store: ... = ... | positive strictlyPositive | | test.c:33:26:33:26 | Load: i | positive | | test.c:33:26:33:28 | Add: ... + ... | positive strictlyPositive | @@ -101,6 +108,7 @@ | test.c:51:15:51:17 | Add: ... + ... | positive strictlyPositive | | test.c:51:17:51:17 | Constant: 2 | positive strictlyPositive | | test.c:51:21:51:21 | Constant: 4 | positive strictlyPositive | +| test.c:51:24:51:30 | CopyValue: ... = ... | positive strictlyPositive | | test.c:51:24:51:30 | Store: ... = ... | positive strictlyPositive | | test.c:51:28:51:28 | Load: i | positive | | test.c:51:28:51:30 | Add: ... + ... | positive strictlyPositive | @@ -459,6 +467,7 @@ | test.c:343:5:343:7 | Constant: ... ++ | positive strictlyPositive | | test.c:343:5:343:7 | Load: ... ++ | positive | | test.c:343:5:343:7 | Store: ... ++ | positive strictlyPositive | +| test.c:345:3:345:7 | CopyValue: ... = ... | positive strictlyPositive | | test.c:345:3:345:7 | Store: ... = ... | positive strictlyPositive | | test.c:345:7:345:7 | Load: i | positive strictlyPositive | | test.c:346:7:346:7 | Load: x | positive | @@ -474,6 +483,7 @@ | test.c:356:36:356:37 | Uninitialized: definition of y6 | positive | | test.c:356:40:356:41 | Uninitialized: definition of y7 | positive | | test.c:356:44:356:45 | Uninitialized: definition of y8 | positive | +| test.c:357:3:357:23 | CopyValue: ... = ... | positive | | test.c:357:3:357:23 | Store: ... = ... | positive | | test.c:357:8:357:8 | Load: x | positive | | test.c:357:8:357:23 | Load: ... ? ... : ... | positive | @@ -483,6 +493,7 @@ | test.c:357:12:357:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:357:18:357:18 | Load: x | positive | | test.c:357:22:357:23 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:358:3:358:24 | CopyValue: ... = ... | positive | | test.c:358:3:358:24 | Store: ... = ... | positive | | test.c:358:8:358:8 | Load: x | positive | | test.c:358:8:358:24 | Load: ... ? ... : ... | positive | @@ -494,6 +505,7 @@ | test.c:358:24:358:24 | Load: x | positive | | test.c:365:7:365:7 | Load: x | positive | | test.c:365:11:365:13 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:366:5:366:15 | CopyValue: ... = ... | positive | | test.c:366:5:366:15 | Store: ... = ... | positive | | test.c:366:10:366:10 | Load: x | positive | | test.c:366:10:366:15 | Load: ... ? ... : ... | positive | @@ -501,6 +513,7 @@ | test.c:366:10:366:15 | Store: ... ? ... : ... | positive | | test.c:366:10:366:15 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:366:15:366:15 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:367:5:367:17 | CopyValue: ... = ... | positive | | test.c:367:5:367:17 | Store: ... = ... | positive | | test.c:367:10:367:10 | Load: x | positive | | test.c:367:10:367:17 | Load: ... ? ... : ... | positive | @@ -508,6 +521,7 @@ | test.c:367:10:367:17 | Store: ... ? ... : ... | positive | | test.c:367:10:367:17 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:368:5:368:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive | | test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -515,6 +529,7 @@ | test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive | | test.c:368:13:368:13 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:368:19:368:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:369:5:369:36 | CopyValue: ... = ... | positive strictlyPositive | | test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive | | test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive | @@ -524,6 +539,7 @@ | test.c:369:27:369:29 | Add: ... + ... | positive strictlyPositive | | test.c:369:29:369:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:369:36:369:36 | Constant: 5 | positive strictlyPositive | +| test.c:370:5:370:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive | | test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -533,6 +549,7 @@ | test.c:370:27:370:29 | Add: ... + ... | positive strictlyPositive | | test.c:370:29:370:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:370:36:370:38 | Constant: 500 | positive strictlyPositive | +| test.c:371:5:371:39 | CopyValue: ... = ... | positive strictlyPositive | | test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive | | test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive | @@ -570,6 +587,7 @@ | test.c:378:24:378:25 | Uninitialized: definition of y3 | positive | | test.c:378:28:378:29 | Uninitialized: definition of y4 | positive | | test.c:378:32:378:33 | Uninitialized: definition of y5 | positive | +| test.c:379:3:379:24 | CopyValue: ... = ... | positive strictlyPositive | | test.c:379:3:379:24 | Store: ... = ... | positive strictlyPositive | | test.c:379:8:379:8 | Load: x | positive | | test.c:379:8:379:24 | Load: ... ? ... : ... | positive strictlyPositive | @@ -579,6 +597,7 @@ | test.c:379:12:379:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:379:18:379:18 | Load: x | positive strictlyPositive | | test.c:379:22:379:24 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:380:3:380:25 | CopyValue: ... = ... | positive strictlyPositive | | test.c:380:3:380:25 | Store: ... = ... | positive strictlyPositive | | test.c:380:8:380:8 | Load: x | positive | | test.c:380:8:380:25 | Load: ... ? ... : ... | positive strictlyPositive | @@ -588,14 +607,18 @@ | test.c:380:13:380:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:19:380:21 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:25:380:25 | Load: x | positive strictlyPositive | +| test.c:381:3:381:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:381:3:381:11 | Store: ... = ... | positive strictlyPositive | | test.c:381:8:381:11 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:382:3:382:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:382:3:382:11 | Store: ... = ... | positive strictlyPositive | | test.c:382:8:382:11 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:383:3:383:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:383:3:383:11 | Store: ... = ... | positive strictlyPositive | | test.c:383:8:383:11 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:384:7:384:7 | Load: x | positive | | test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:385:5:385:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive | | test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -603,6 +626,7 @@ | test.c:385:11:385:15 | Sub: ... - ... | positive | | test.c:385:13:385:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:386:5:386:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive | | test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -610,6 +634,7 @@ | test.c:386:11:386:15 | Sub: ... - ... | positive | | test.c:386:13:386:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:386:21:386:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:387:5:387:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive | | test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -644,17 +669,22 @@ | test.c:394:34:394:36 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:395:16:395:17 | Uninitialized: definition of y1 | positive | | test.c:396:16:396:17 | Uninitialized: definition of y2 | positive | +| test.c:397:3:397:15 | CopyValue: ... = ... | positive strictlyPositive | | test.c:397:3:397:15 | Store: ... = ... | positive strictlyPositive | | test.c:397:9:397:11 | Add: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Load: ++ ... | positive | | test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive | +| test.c:397:9:397:14 | CopyValue: ... , ... | positive strictlyPositive | | test.c:397:14:397:14 | Load: y | positive strictlyPositive | +| test.c:398:3:398:23 | CopyValue: ... = ... | positive strictlyPositive | | test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive | | test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive | +| test.c:398:9:398:19 | CopyValue: ... , ... | positive strictlyPositive | +| test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Store: ... += ... | positive strictlyPositive | diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 5e76fb042be..a8f98105b08 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -21,7 +21,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | Chi: call to C | | ms_try_mix.cpp:48:10:48:13 | Chi: call to C | | pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index b9c4bd7eba5..e8b34aff726 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -1,9 +1,10 @@ missingOperand -| condition_decls.cpp:16:6:16:20 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:3:36:3 | Switch: switch (...) ... | Instruction 'Switch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:9:41:23 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:39:48:53 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | +| condition_decls.cpp:16:6:16:20 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | +| condition_decls.cpp:26:10:26:24 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | +| condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | +| condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | +| misc.c:220:3:223:3 | CopyValue: ... = ... | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -47,13 +48,13 @@ instructionWithoutSuccessor | misc.c:222:10:222:10 | Store: 2 | | ms_assume.cpp:20:12:20:12 | Constant: (bool)... | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | +| ms_try_except.cpp:7:13:7:17 | CopyValue: ... = ... | | ms_try_except.cpp:9:19:9:19 | Load: j | -| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | -| ms_try_except.cpp:14:13:14:17 | Store: ... = ... | -| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | +| ms_try_except.cpp:10:13:10:17 | CopyValue: ... = ... | +| ms_try_except.cpp:14:13:14:17 | CopyValue: ... = ... | +| ms_try_except.cpp:17:13:17:17 | CopyValue: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | -| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | +| ms_try_except.cpp:20:9:20:13 | CopyValue: ... = ... | | ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | | ms_try_mix.cpp:18:16:18:19 | CallSideEffect: call to C | @@ -75,7 +76,7 @@ instructionWithoutSuccessor | static_init_templates.cpp:97:27:97:36 | Convert: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index ab5362cb06c..c8cee7b2a7c 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -30,7 +30,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | | ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | | pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 8be4cf4e2c1..4bc9f90cc60 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -40,34 +40,40 @@ test.cpp: # 5| valnum = r0_7 # 5| m0_19(int) = Store : &:r0_18, r0_17 # 5| valnum = r0_17 -# 6| r0_20(glval) = VariableAddress[p0] : +# 5| r0_20(glval) = CopyValue : r0_18 +# 5| valnum = r0_7 +# 6| r0_21(glval) = VariableAddress[p0] : # 6| valnum = r0_3 -# 6| r0_21(int) = Load : &:r0_20, m0_4 +# 6| r0_22(int) = Load : &:r0_21, m0_4 # 6| valnum = m0_4 -# 6| r0_22(glval) = VariableAddress[p1] : +# 6| r0_23(glval) = VariableAddress[p1] : # 6| valnum = r0_5 -# 6| r0_23(int) = Load : &:r0_22, m0_6 +# 6| r0_24(int) = Load : &:r0_23, m0_6 # 6| valnum = m0_6 -# 6| r0_24(int) = Add : r0_21, r0_23 +# 6| r0_25(int) = Add : r0_22, r0_24 # 6| valnum = r0_17 -# 6| r0_25(glval) = VariableAddress[x] : +# 6| r0_26(glval) = VariableAddress[x] : # 6| valnum = r0_7 -# 6| m0_26(int) = Store : &:r0_25, r0_24 +# 6| m0_27(int) = Store : &:r0_26, r0_25 # 6| valnum = r0_17 -# 7| r0_27(glval) = VariableAddress[x] : +# 6| r0_28(glval) = CopyValue : r0_26 +# 6| valnum = r0_7 +# 7| r0_29(glval) = VariableAddress[x] : # 7| valnum = r0_7 -# 7| r0_28(int) = Load : &:r0_27, m0_26 +# 7| r0_30(int) = Load : &:r0_29, m0_27 # 7| valnum = r0_17 -# 7| r0_29(glval) = VariableAddress[y] : +# 7| r0_31(glval) = VariableAddress[y] : # 7| valnum = r0_9 -# 7| m0_30(int) = Store : &:r0_29, r0_28 +# 7| m0_32(int) = Store : &:r0_31, r0_30 # 7| valnum = r0_17 -# 8| v0_31(void) = NoOp : -# 1| r0_32(glval) = VariableAddress[#return] : +# 7| r0_33(glval) = CopyValue : r0_31 +# 7| valnum = r0_9 +# 8| v0_34(void) = NoOp : +# 1| r0_35(glval) = VariableAddress[#return] : # 1| valnum = unique -# 1| v0_33(void) = ReturnValue : &:r0_32 -# 1| v0_34(void) = UnmodeledUse : mu* -# 1| v0_35(void) = ExitFunction : +# 1| v0_36(void) = ReturnValue : &:r0_35 +# 1| v0_37(void) = UnmodeledUse : mu* +# 1| v0_38(void) = ExitFunction : # 12| int test01(int, int) # 12| Block 0 @@ -116,40 +122,46 @@ test.cpp: # 16| valnum = r0_7 # 16| m0_22(int) = Store : &:r0_21, r0_20 # 16| valnum = r0_20 -# 17| r0_23(glval) = VariableAddress[p0] : +# 16| r0_23(glval) = CopyValue : r0_21 +# 16| valnum = r0_7 +# 17| r0_24(glval) = VariableAddress[p0] : # 17| valnum = r0_3 -# 17| r0_24(int) = Load : &:r0_23, m0_4 +# 17| r0_25(int) = Load : &:r0_24, m0_4 # 17| valnum = m0_4 -# 17| r0_25(glval) = VariableAddress[p1] : +# 17| r0_26(glval) = VariableAddress[p1] : # 17| valnum = r0_5 -# 17| r0_26(int) = Load : &:r0_25, m0_6 +# 17| r0_27(int) = Load : &:r0_26, m0_6 # 17| valnum = m0_6 -# 17| r0_27(int) = Add : r0_24, r0_26 +# 17| r0_28(int) = Add : r0_25, r0_27 # 17| valnum = r0_17 -# 17| r0_28(glval) = VariableAddress[global01] : +# 17| r0_29(glval) = VariableAddress[global01] : # 17| valnum = r0_18 -# 17| r0_29(int) = Load : &:r0_28, ~m0_1 +# 17| r0_30(int) = Load : &:r0_29, ~m0_1 # 17| valnum = unique -# 17| r0_30(int) = Add : r0_27, r0_29 -# 17| valnum = r0_30 -# 17| r0_31(glval) = VariableAddress[x] : +# 17| r0_31(int) = Add : r0_28, r0_30 +# 17| valnum = r0_31 +# 17| r0_32(glval) = VariableAddress[x] : # 17| valnum = r0_7 -# 17| m0_32(int) = Store : &:r0_31, r0_30 -# 17| valnum = r0_30 -# 18| r0_33(glval) = VariableAddress[x] : +# 17| m0_33(int) = Store : &:r0_32, r0_31 +# 17| valnum = r0_31 +# 17| r0_34(glval) = CopyValue : r0_32 +# 17| valnum = r0_7 +# 18| r0_35(glval) = VariableAddress[x] : # 18| valnum = r0_7 -# 18| r0_34(int) = Load : &:r0_33, m0_32 -# 18| valnum = r0_30 -# 18| r0_35(glval) = VariableAddress[y] : +# 18| r0_36(int) = Load : &:r0_35, m0_33 +# 18| valnum = r0_31 +# 18| r0_37(glval) = VariableAddress[y] : # 18| valnum = r0_9 -# 18| m0_36(int) = Store : &:r0_35, r0_34 -# 18| valnum = r0_30 -# 19| v0_37(void) = NoOp : -# 12| r0_38(glval) = VariableAddress[#return] : +# 18| m0_38(int) = Store : &:r0_37, r0_36 +# 18| valnum = r0_31 +# 18| r0_39(glval) = CopyValue : r0_37 +# 18| valnum = r0_9 +# 19| v0_40(void) = NoOp : +# 12| r0_41(glval) = VariableAddress[#return] : # 12| valnum = unique -# 12| v0_39(void) = ReturnValue : &:r0_38 -# 12| v0_40(void) = UnmodeledUse : mu* -# 12| v0_41(void) = ExitFunction : +# 12| v0_42(void) = ReturnValue : &:r0_41 +# 12| v0_43(void) = UnmodeledUse : mu* +# 12| v0_44(void) = ExitFunction : # 25| int test02(int, int) # 25| Block 0 @@ -198,47 +210,53 @@ test.cpp: # 29| valnum = r0_7 # 29| m0_22(int) = Store : &:r0_21, r0_20 # 29| valnum = r0_20 -# 30| r0_23(glval) = FunctionAddress[change_global02] : +# 29| r0_23(glval) = CopyValue : r0_21 +# 29| valnum = r0_7 +# 30| r0_24(glval) = FunctionAddress[change_global02] : # 30| valnum = unique -# 30| v0_24(void) = Call : func:r0_23 -# 30| m0_25(unknown) = ^CallSideEffect : ~m0_1 +# 30| v0_25(void) = Call : func:r0_24 +# 30| m0_26(unknown) = ^CallSideEffect : ~m0_1 # 30| valnum = unique -# 30| m0_26(unknown) = Chi : total:m0_1, partial:m0_25 +# 30| m0_27(unknown) = Chi : total:m0_1, partial:m0_26 # 30| valnum = unique -# 31| r0_27(glval) = VariableAddress[p0] : +# 31| r0_28(glval) = VariableAddress[p0] : # 31| valnum = r0_3 -# 31| r0_28(int) = Load : &:r0_27, m0_4 +# 31| r0_29(int) = Load : &:r0_28, m0_4 # 31| valnum = m0_4 -# 31| r0_29(glval) = VariableAddress[p1] : +# 31| r0_30(glval) = VariableAddress[p1] : # 31| valnum = r0_5 -# 31| r0_30(int) = Load : &:r0_29, m0_6 +# 31| r0_31(int) = Load : &:r0_30, m0_6 # 31| valnum = m0_6 -# 31| r0_31(int) = Add : r0_28, r0_30 +# 31| r0_32(int) = Add : r0_29, r0_31 # 31| valnum = r0_17 -# 31| r0_32(glval) = VariableAddress[global02] : +# 31| r0_33(glval) = VariableAddress[global02] : # 31| valnum = r0_18 -# 31| r0_33(int) = Load : &:r0_32, ~m0_26 +# 31| r0_34(int) = Load : &:r0_33, ~m0_27 # 31| valnum = unique -# 31| r0_34(int) = Add : r0_31, r0_33 -# 31| valnum = r0_34 -# 31| r0_35(glval) = VariableAddress[x] : +# 31| r0_35(int) = Add : r0_32, r0_34 +# 31| valnum = r0_35 +# 31| r0_36(glval) = VariableAddress[x] : # 31| valnum = r0_7 -# 31| m0_36(int) = Store : &:r0_35, r0_34 -# 31| valnum = r0_34 -# 32| r0_37(glval) = VariableAddress[x] : +# 31| m0_37(int) = Store : &:r0_36, r0_35 +# 31| valnum = r0_35 +# 31| r0_38(glval) = CopyValue : r0_36 +# 31| valnum = r0_7 +# 32| r0_39(glval) = VariableAddress[x] : # 32| valnum = r0_7 -# 32| r0_38(int) = Load : &:r0_37, m0_36 -# 32| valnum = r0_34 -# 32| r0_39(glval) = VariableAddress[y] : +# 32| r0_40(int) = Load : &:r0_39, m0_37 +# 32| valnum = r0_35 +# 32| r0_41(glval) = VariableAddress[y] : # 32| valnum = r0_9 -# 32| m0_40(int) = Store : &:r0_39, r0_38 -# 32| valnum = r0_34 -# 33| v0_41(void) = NoOp : -# 25| r0_42(glval) = VariableAddress[#return] : +# 32| m0_42(int) = Store : &:r0_41, r0_40 +# 32| valnum = r0_35 +# 32| r0_43(glval) = CopyValue : r0_41 +# 32| valnum = r0_9 +# 33| v0_44(void) = NoOp : +# 25| r0_45(glval) = VariableAddress[#return] : # 25| valnum = unique -# 25| v0_43(void) = ReturnValue : &:r0_42 -# 25| v0_44(void) = UnmodeledUse : mu* -# 25| v0_45(void) = ExitFunction : +# 25| v0_46(void) = ReturnValue : &:r0_45 +# 25| v0_47(void) = UnmodeledUse : mu* +# 25| v0_48(void) = ExitFunction : # 39| int test03(int, int, int*) # 39| Block 0 @@ -291,50 +309,60 @@ test.cpp: # 43| valnum = r0_9 # 43| m0_24(int) = Store : &:r0_23, r0_22 # 43| valnum = r0_22 -# 44| r0_25(int) = Constant[0] : -# 44| valnum = r0_25 -# 44| r0_26(glval) = VariableAddress[p2] : +# 43| r0_25(glval) = CopyValue : r0_23 +# 43| valnum = r0_9 +# 44| r0_26(int) = Constant[0] : +# 44| valnum = r0_26 +# 44| r0_27(glval) = VariableAddress[p2] : # 44| valnum = r0_7 -# 44| r0_27(int *) = Load : &:r0_26, m0_8 +# 44| r0_28(int *) = Load : &:r0_27, m0_8 # 44| valnum = m0_8 -# 44| m0_28(int) = Store : &:r0_27, r0_25 -# 44| valnum = r0_25 -# 44| m0_29(unknown) = Chi : total:m0_1, partial:m0_28 +# 44| r0_29(glval) = CopyValue : r0_28 +# 44| valnum = m0_8 +# 44| m0_30(int) = Store : &:r0_29, r0_26 +# 44| valnum = r0_26 +# 44| m0_31(unknown) = Chi : total:m0_1, partial:m0_30 # 44| valnum = unique -# 45| r0_30(glval) = VariableAddress[p0] : +# 44| r0_32(glval) = CopyValue : r0_29 +# 44| valnum = m0_8 +# 45| r0_33(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_31(int) = Load : &:r0_30, m0_4 +# 45| r0_34(int) = Load : &:r0_33, m0_4 # 45| valnum = m0_4 -# 45| r0_32(glval) = VariableAddress[p1] : +# 45| r0_35(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_33(int) = Load : &:r0_32, m0_6 +# 45| r0_36(int) = Load : &:r0_35, m0_6 # 45| valnum = m0_6 -# 45| r0_34(int) = Add : r0_31, r0_33 -# 45| valnum = r0_19 -# 45| r0_35(glval) = VariableAddress[global03] : -# 45| valnum = r0_20 -# 45| r0_36(int) = Load : &:r0_35, ~m0_29 -# 45| valnum = unique # 45| r0_37(int) = Add : r0_34, r0_36 -# 45| valnum = r0_37 -# 45| r0_38(glval) = VariableAddress[x] : +# 45| valnum = r0_19 +# 45| r0_38(glval) = VariableAddress[global03] : +# 45| valnum = r0_20 +# 45| r0_39(int) = Load : &:r0_38, ~m0_31 +# 45| valnum = unique +# 45| r0_40(int) = Add : r0_37, r0_39 +# 45| valnum = r0_40 +# 45| r0_41(glval) = VariableAddress[x] : # 45| valnum = r0_9 -# 45| m0_39(int) = Store : &:r0_38, r0_37 -# 45| valnum = r0_37 -# 46| r0_40(glval) = VariableAddress[x] : +# 45| m0_42(int) = Store : &:r0_41, r0_40 +# 45| valnum = r0_40 +# 45| r0_43(glval) = CopyValue : r0_41 +# 45| valnum = r0_9 +# 46| r0_44(glval) = VariableAddress[x] : # 46| valnum = r0_9 -# 46| r0_41(int) = Load : &:r0_40, m0_39 -# 46| valnum = r0_37 -# 46| r0_42(glval) = VariableAddress[y] : +# 46| r0_45(int) = Load : &:r0_44, m0_42 +# 46| valnum = r0_40 +# 46| r0_46(glval) = VariableAddress[y] : # 46| valnum = r0_11 -# 46| m0_43(int) = Store : &:r0_42, r0_41 -# 46| valnum = r0_37 -# 47| v0_44(void) = NoOp : -# 39| r0_45(glval) = VariableAddress[#return] : +# 46| m0_47(int) = Store : &:r0_46, r0_45 +# 46| valnum = r0_40 +# 46| r0_48(glval) = CopyValue : r0_46 +# 46| valnum = r0_11 +# 47| v0_49(void) = NoOp : +# 39| r0_50(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_46(void) = ReturnValue : &:r0_45 -# 39| v0_47(void) = UnmodeledUse : mu* -# 39| v0_48(void) = ExitFunction : +# 39| v0_51(void) = ReturnValue : &:r0_50 +# 39| v0_52(void) = UnmodeledUse : mu* +# 39| v0_53(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -391,6 +419,8 @@ test.cpp: # 55| valnum = r0_7 # 55| m2_3(char *) = Store : &:r2_2, r2_1 # 55| valnum = m0_6 +# 55| r2_4(glval) = CopyValue : r2_2 +# 55| valnum = r0_7 #-----| Goto -> Block 3 # 56| Block 3 @@ -572,6 +602,8 @@ test.cpp: # 80| valnum = r0_5 # 80| m1_6(signed short) = Store : &:r1_5, r1_4 # 80| valnum = r1_4 +# 80| r1_7(glval) = CopyValue : r1_5 +# 80| valnum = r0_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -648,10 +680,12 @@ test.cpp: # 88| valnum = r0_9 # 88| m3_4(int) = Store : &:r3_3, r3_2 # 88| valnum = m3_0 -# 89| v3_5(void) = NoOp : -# 84| v3_6(void) = ReturnVoid : -# 84| v3_7(void) = UnmodeledUse : mu* -# 84| v3_8(void) = ExitFunction : +# 88| r3_5(glval) = CopyValue : r3_3 +# 88| valnum = r0_9 +# 89| v3_6(void) = NoOp : +# 84| v3_7(void) = ReturnVoid : +# 84| v3_8(void) = UnmodeledUse : mu* +# 84| v3_9(void) = ExitFunction : # 91| int regression_test00() # 91| Block 0 @@ -668,21 +702,23 @@ test.cpp: # 92| valnum = r0_3 # 92| m0_6(int) = Store : &:r0_5, r0_4 # 92| valnum = r0_4 -# 92| m0_7(int) = Store : &:r0_3, r0_4 +# 92| r0_7(int) = CopyValue : r0_4 # 92| valnum = r0_4 -# 93| r0_8(glval) = VariableAddress[#return] : -# 93| valnum = r0_8 -# 93| r0_9(glval) = VariableAddress[x] : +# 92| m0_8(int) = Store : &:r0_3, r0_7 +# 92| valnum = r0_4 +# 93| r0_9(glval) = VariableAddress[#return] : +# 93| valnum = r0_9 +# 93| r0_10(glval) = VariableAddress[x] : # 93| valnum = r0_3 -# 93| r0_10(int) = Load : &:r0_9, m0_7 +# 93| r0_11(int) = Load : &:r0_10, m0_8 # 93| valnum = r0_4 -# 93| m0_11(int) = Store : &:r0_8, r0_10 +# 93| m0_12(int) = Store : &:r0_9, r0_11 # 93| valnum = r0_4 -# 91| r0_12(glval) = VariableAddress[#return] : -# 91| valnum = r0_8 -# 91| v0_13(void) = ReturnValue : &:r0_12, m0_11 -# 91| v0_14(void) = UnmodeledUse : mu* -# 91| v0_15(void) = ExitFunction : +# 91| r0_13(glval) = VariableAddress[#return] : +# 91| valnum = r0_9 +# 91| v0_14(void) = ReturnValue : &:r0_13, m0_12 +# 91| v0_15(void) = UnmodeledUse : mu* +# 91| v0_16(void) = ExitFunction : # 104| int inheritanceConversions(Derived*) # 104| Block 0 From 9511465f04ef80c6f1b0afe914e54d6b625bdc97 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 26 Sep 2019 11:16:24 +0200 Subject: [PATCH 006/232] Learn QL: Minor formatting fix in python/statements-expressions (cherry picked from commit c47a4e0c44eba9f24ffb5490986188347e1372f5) --- docs/language/learn-ql/python/statements-expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 2d45abde73a..9f1a15a6d1a 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -72,7 +72,7 @@ An ``if`` statement where one branch is composed of just ``pass`` statements cou To find statements like this we can run the following query: -**Find ``if`` statements with empty branches** +**Find 'if' statements with empty branches** .. code-block:: ql From 94d876e8a3664c4fba6f48f7f10f937885900759 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 25 Sep 2019 18:20:48 +0200 Subject: [PATCH 007/232] Learn QL: Fix query link in Python Points-to tutorial (cherry picked from commit c6c565bc373e1353830ea731823feea024b4c4c8) --- docs/language/learn-ql/python/pointsto-type-infer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 6ca1bde67c8..bcbab520477 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -173,7 +173,7 @@ Many of the results shown will have ``cls`` as ``NoneType``. It is more informat not cls.hasAttribute("__iter__") select loop, cls, origin -➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. +➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. Finding calls using call-graph analysis ---------------------------------------------------- From 3a4cef646de30c263d4fdc86c34b377cbe8129db Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Sep 2019 16:04:01 +0100 Subject: [PATCH 008/232] docs: fix some formatting issues --- .../learn-ql/cpp/conversions-classes.rst | 2 +- docs/language/learn-ql/cpp/function-classes.rst | 4 ++++ .../learn-ql/cpp/introduce-libraries-cpp.rst | 4 ++++ .../learn-ql/cpp/zero-space-terminator.rst | 4 ++++ docs/language/learn-ql/csharp/ql-for-csharp.rst | 15 --------------- docs/language/learn-ql/java/call-graph.rst | 2 ++ .../learn-ql/java/expressions-statements.rst | 2 ++ .../learn-ql/java/introduce-libraries-java.rst | 10 +++++++++- .../learn-ql/java/types-class-hierarchy.rst | 2 ++ .../javascript/introduce-libraries-js.rst | 2 +- docs/language/learn-ql/python/functions.rst | 2 ++ .../python/introduce-libraries-python.rst | 16 ++++++++-------- .../learn-ql/python/pointsto-type-infer.rst | 9 +++++---- .../learn-ql/python/statements-expressions.rst | 8 ++++---- 14 files changed, 48 insertions(+), 34 deletions(-) diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 512d967a53f..28032a932d2 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -128,7 +128,7 @@ Unlike the earlier versions of the query, this query would return each side of t Note - In general, QL predicates named ``getAXxx`` exploit the ability to return multiple results (multiple instances of ``Xxx``) whereas plain ``getXxx`` predicates usually return at most one specific instance of ``Xxx``. + In general, QL predicates named ``getAXxx`` exploit the ability to return multiple results (multiple instances of ``Xxx``) whereas plain ``getXxx`` predicates usually return at most one specific instance of ``Xxx``. Classes ------- diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 5dde2546995..4b9db11351b 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -60,6 +60,10 @@ This query returns fewer results. However, if you examine the results then you c For example, there is a more complicated LGTM `query `__ that finds unused static functions. To see the QL code for this query, click **Open in query console** at the top of the page. +.. pull-quote:: + + Tip + You can explore the definition of an element in the standard QL libraries and see what predicates are available. Use the keyboard **F3** button to open the definition of any element. Alternatively, hover over the element and click **Jump to definition** in the tooltip displayed. The library file is opened in a new tab with the definition highlighted. Finding a specific function diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 01f8b244684..5c287bd7115 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -12,6 +12,10 @@ There is an extensive QL library for analyzing C/C++ code. The QL classes in thi The rest of this topic briefly summarizes the most important QL classes and predicates provided by this library. +.. pull-quote:: + + Tip + You can find related classes and features using the query console's auto-complete feature. You can also press **F3** to jump to the definition of any element (QL library files are opened in new tabs in the console). Summary of the library classes diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index f2d0ae36dbd..c5c578633e1 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -87,6 +87,10 @@ Now we can write a query using these classes: Note that there is no need to check whether anything is added to the ``strlen`` expression, as it would be in the corrected C code ``malloc(strlen(string) + 1)``. This is because the corrected code would in fact be an ``AddExpr`` containing a ``StrlenCall``, not an instance of ``StrlenCall`` itself. A side-effect of this approach is that we omit certain unlikely patterns such as ``malloc(strlen(string) + 0``). In practice we can always come back and extend our query to cover this pattern if it is a concern. +.. pull-quote:: + + Tip + For some projects, this query may not return any results. Possibly the project you are querying does not have any problems of this kind, but it is also important to make sure the query itself is working properly. One solution is to set up a test project with examples of correct and incorrect code to run the query against (the C code at the very top of this page makes a good starting point). Another approach is to test each part of the query individually to make sure everything is working. When you have defined the basic query then you can refine the query to include further coding patterns or to exclude false positives: diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index 56d8f7ef017..879d8c15107 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -14,23 +14,8 @@ These topics provide an overview of the QL C# libraries and show examples of how - :doc:`Introducing the C# libraries ` introduces the standard libraries used to write queries for C# code. -.. raw:: html - - - - :doc:`Tutorial: Analyzing data flow in C# ` demonstrates how to write queries using the standard QL for C# data flow and taint tracking libraries. -.. raw:: html - - - -.. raw:: html - - - -.. raw:: html - - Other resources --------------- diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index b0c721b1fd7..3cea5294c0e 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -78,6 +78,8 @@ Given this API, we can easily write a query that finds methods that are not call ➤ `See this in the query console `__. This simple query typically returns a large number of results. +.. pull-quote:: + Note We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding. diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index c8882c41792..0034868f01a 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -18,6 +18,8 @@ Specifically, consider the following code snippet: If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type ``int``), then this loop will never terminate: ``i`` will start at zero, being incremented all the way up to 2\ :sup:`31`\ - 1, which is still smaller than ``l``. When it is incremented once more, an arithmetic overflow occurs, and ``i`` becomes -2\ :sup:`31`\, which also is smaller than ``l``! Eventually, ``i`` will reach zero again, and the cycle repeats. +.. pull-quote:: + More about overflow All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index 32863b099e0..ef20dd47ccf 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -14,6 +14,10 @@ The library is implemented as a set of QL modules, that is, files with the exten The rest of this topic briefly summarizes the most important QL classes and predicates provided by this library. +.. pull-quote:: + + Note + The example queries in this topic illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The tutorial topics show how you can take a simple query and fine-tune it to find precisely the results you're interested in. Summary of the library classes @@ -315,7 +319,11 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle ➤ `See this in the query console `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. - Note that on line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. +.. pull-quote:: + + Note + + On line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. For more information on working with Javadoc, see the :doc:`tutorial on Javadoc `. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index df50e600cf9..9855a0391b2 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -32,6 +32,8 @@ To determine ancestor types (including immediate super types, and also *their* s ➤ `See this in the query console `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. +.. pull-quote:: + Tip If you want to see the location of ``B`` as well as ``A``, you can replace ``B.getASupertype+()`` with ``B.getASupertype*()`` and re-run the query. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 0e3a7e5acdd..0858cbb5f8d 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -224,7 +224,7 @@ The `TopLevel `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class and function are represented by the three classes `Module `__, `Class `__ and `Function `__, which are all subclasses of ``Scope``. - ``Scope`` @@ -110,12 +110,12 @@ Examples Each syntactic element in Python source is recorded in the snapshot. These can be queried via the corresponding class. Let us start with a couple of simple examples. -1. Finding all finally blocks -''''''''''''''''''''''''''''' +1. Finding all ``finally`` blocks +''''''''''''''''''''''''''''''''' For our first example, we can find all ``finally`` blocks by using the ``Try`` class: -**Find all ``finally`` blocks** +**Find all** ``finally`` **blocks** .. code-block:: ql @@ -126,8 +126,8 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c ➤ `See this in the query console `__. Many projects include examples of this pattern. -2. Finding 'except' blocks that do nothing -'''''''''''''''''''''''''''''''''''''''''' +2. Finding ``except`` blocks that do nothing +'''''''''''''''''''''''''''''''''''''''''''' For our second example, we can use a simplified version of a query from the standard query set. We look for all ``except`` blocks that do nothing. @@ -137,7 +137,7 @@ A block that does nothing is one that contains no statements except ``pass`` sta not exists(Stmt s | s = ex.getAStmt() | not s instanceof Pass) -where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass`` statements. Instead of using the double negative, **"no**\ *statements that are*\ **not**\ *pass statements"*, this can also be expressed positively, "all statements must be pass statements." The positive form is expressed in QL using the ``forall`` quantifier: +where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass`` statements. Instead of using the double negative, *no statements that are not pass statements*, this can also be expressed positively, *all statements must be pass statements*. The positive form is expressed in QL using the ``forall`` quantifier: .. code-block:: ql @@ -145,7 +145,7 @@ where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass` Both forms are equivalent. Using the positive QL expression, the whole query looks like this: -**Find pass-only ``except`` blocks** +**Find pass-only** ``except`` **blocks** .. code-block:: ql diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index bcbab520477..1b5817f8534 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -37,7 +37,8 @@ The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flo predicate pointsTo(Context context, Value object, ControlFlowNode origin) ``object`` is an object that the control flow node refers to, and ``origin`` is where the object comes from, which is useful for displaying meaningful results. - The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored. + +The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored. .. pull-quote:: @@ -62,7 +63,7 @@ We want to find ``except`` blocks in a ``try`` statement that are in the wrong o First we can write a query to find ordered pairs of ``except`` blocks for a ``try`` statement. -**Ordered except blocks in same ``try`` statement** +**Ordered except blocks in same** ``try`` **statement** .. code-block:: ql @@ -81,7 +82,7 @@ Here ``ex1`` and ``ex2`` are both ``except`` handlers in the ``try`` statement ` The results of this query need to be filtered to return only results where ``ex1`` is more general than ``ex2``. We can use the fact that an ``except`` block is more general than another block if the class it handles is a superclass of the other. -**More general ``except`` block** +**More general** ``except`` **block** .. code-block:: ql @@ -102,7 +103,7 @@ ensures that ``cls1`` is a ``ClassValue`` that the ``except`` block would handle Combining the parts of the query we get this: -**More general ``except`` block precedes more specific** +**More general** ``except`` **block precedes more specific** .. code-block:: ql diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 9f1a15a6d1a..622733ceb1b 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -143,7 +143,7 @@ Python implementations commonly cache small integers and single character string We can check for these as follows: -**Find comparisons to integer or string literals using ``is``** +**Find comparisons to integer or string literals using** ``is`` .. code-block:: ql @@ -158,6 +158,8 @@ We can check for these as follows: The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal. +.. pull-quote:: + Tip We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``). @@ -253,9 +255,7 @@ checks that the value of the attribute (the expression to the left of the dot in Class and function definitions ------------------------------ -As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()`` - -``FunctionDef``, ``Function`` are handled similarly. +As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()``. ``FunctionDef`` and ``Function`` are handled similarly. Here is the relevant part of the class hierarchy: From ff78feeeeaec99bdf779242c33e25f57c7bcab29 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 30 Sep 2019 11:51:17 +0100 Subject: [PATCH 009/232] docs: version number and small css tweaks --- .../slides-semmle-2/static/theme/css/default.css | 5 +++-- docs/language/ql-training/conf.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 2c05ea5e93b..e3664d42e06 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -485,6 +485,7 @@ ul { margin-left: 2.2em; margin-bottom: 1em; position: relative; + width: 90%; } /* line 300, ../scss/default.scss */ ul li { @@ -1569,7 +1570,7 @@ p.first.admonition-title { text-align: left; font-size: 0.8em; width: 100%; - overflow: scroll; + overflow: auto; border: 1px solid black; } @@ -1608,7 +1609,7 @@ p.first.admonition-title { display: block; position: fixed; top: 0; - right: -1%; + right: 0; font-size: 1.2em; } diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index de712cd06a4..8f8a13569b5 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -86,9 +86,9 @@ htmlhelp_basename = 'QL training' # built documents. # # The short X.Y version. -version = u'1.21' +version = u'1.22' # The full version, including alpha/beta/rc tags. -release = u'1.21' +release = u'1.22' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' From 56ed2f618d932f221976391dd46f754ca208fbe0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 2 Oct 2019 09:05:31 +0100 Subject: [PATCH 010/232] Add alias for easier user-searching --- docs/language/support/versions-compilers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv index b70ac87335f..74f69d662b6 100644 --- a/docs/language/support/versions-compilers.csv +++ b/docs/language/support/versions-compilers.csv @@ -10,7 +10,7 @@ C#,C# up to 7.3. with .NET up to 4.8 [3]_.,"Microsoft Visual Studio up to 2019, .NET Core up to 2.2","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" COBOL,ANSI 85 or newer [4]_.,Not applicable,"``.cbl``, ``.CBL``, ``.cpy``, ``.CPY``, ``.copy``, ``.COPY``" -Go, "Go up to 1.13", "Go 1.11 or more recent", ``.go`` +Go (aka Golang), "Go up to 1.13", "Go 1.11 or more recent", ``.go`` Java,"Java 6 to 12 [5]_.","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [6]_.",``.java`` From 4a8e8fa0de4470aaeed94357f70b54b68c0b84a7 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 4 Oct 2019 09:18:19 +0100 Subject: [PATCH 011/232] docs: semmle logo --- .../static/theme/css/default.css | 18 +-- .../_static-training/title-slide.svg | 149 +----------------- .../ql-training/cpp/bad-overflow-guard.rst | 4 - .../ql-training/cpp/control-flow-cpp.rst | 4 - .../ql-training/cpp/data-flow-cpp.rst | 4 - .../ql-training/cpp/global-data-flow-cpp.rst | 4 - .../language/ql-training/cpp/intro-ql-cpp.rst | 4 - .../cpp/program-representation-cpp.rst | 4 - docs/language/ql-training/cpp/snprintf.rst | 4 - docs/language/ql-training/index.rst | 4 - .../ql-training/java/apache-struts-java.rst | 4 - .../ql-training/java/data-flow-java.rst | 4 - .../java/global-data-flow-java.rst | 4 - .../ql-training/java/intro-ql-java.rst | 4 - .../java/program-representation-java.rst | 4 - .../ql-training/java/query-injection-java.rst | 4 - docs/language/ql-training/template.rst | 4 - 17 files changed, 4 insertions(+), 223 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index e3664d42e06..83d3d94e3aa 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -1301,13 +1301,13 @@ aside.gdbar img { .title-slide hgroup h1 { font-size: 2em; line-height: 1.4; - /*letter-spacing: -3px;*/ color: white; margin: auto; display: block; position: absolute; top: 0; bottom: 10%; + left: 1.25em; height: 0; } /* line 898, ../scss/default.scss */ @@ -1431,31 +1431,19 @@ hgroup .pre { color: #5c31ff; } -/* title slide (deck title, subtitle, semmle logo)*/ +/* title slide (deck title, subtitle)*/ .title-slide { background-image: url("../../title-slide.svg"); background-size: cover; } -.semmle-logo sup { - vertical-align: super; - font-size: 0.3em; - font-weight: 100; -} - -.title-slide .semmle-logo { - color: white; - font-size: 1.2em; - position: absolute; - top: 10%; -} - .title-slide p { color: white; font-size: 1em; position: absolute; bottom: 30%; + left: 2.6em; } .title-slide hgroup .pre { diff --git a/docs/language/ql-training/_static-training/title-slide.svg b/docs/language/ql-training/_static-training/title-slide.svg index 6f9a19f4a1b..13eb2d34fef 100644 --- a/docs/language/ql-training/_static-training/title-slide.svg +++ b/docs/language/ql-training/_static-training/title-slide.svg @@ -1,148 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 12f35440906..3ac9ee55f3b 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -4,10 +4,6 @@ Example: Bad overflow guard QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index ea8e2c1b158..e4d17fff844 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -4,10 +4,6 @@ Analyzing control flow QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Include information slides here .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 36b5eb6b525..6ece12d1525 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -4,10 +4,6 @@ Introduction to data flow Finding string formatting vulnerabilities in C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 6033581ffc3..02c37b5fb4c 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -3,10 +3,6 @@ Introduction to global data flow ================================ QL for C/C++ - -.. container:: semmle-logo - - Semmle :sup:`TM` .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 82eb62a3ba8..fedbed7f0f5 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -4,10 +4,6 @@ Introduction to variant analysis QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 1850e3e5671..4555d918822 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -4,10 +4,6 @@ Program representation QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 77e46933fcb..5f1a27bf8db 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -4,10 +4,6 @@ Exercise: ``snprintf`` overflow QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 0cc4ca9b024..6f3aea9a17a 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,10 +1,6 @@ QL training and variant analysis examples ========================================= -.. container:: semmle-logo - - Semmle :sup:`TM` - .. toctree:: :glob: :maxdepth: 1 diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 7fcd2e003cd..c39652fa2a5 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -8,10 +8,6 @@ Exercise: Apache Struts CVE-2017-9805 -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index be9ba98456e..78e4bf54946 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -2,10 +2,6 @@ Introduction to data flow ========================= -.. container:: semmle-logo - - Semmle :sup:`TM` - Finding SPARQL injection vulnerabilities in Java .. rst-class:: setup diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 665899f8459..6d821d60ea2 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -4,10 +4,6 @@ Introduction to global data flow QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 392c18309cb..611be7dfd6e 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -4,10 +4,6 @@ Introduction to variant analysis QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index d090c30aebe..ddd8103454f 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -4,10 +4,6 @@ Program representation QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index 67f7fe21a76..de5d9623bfc 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -4,10 +4,6 @@ Example: Query injection QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/template.rst b/docs/language/ql-training/template.rst index 0cce4a11435..21c5abef144 100644 --- a/docs/language/ql-training/template.rst +++ b/docs/language/ql-training/template.rst @@ -27,10 +27,6 @@ Template slide deck Second subheading -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Set up slide. Include link to QL4E snapshots required for examples .. rst-class:: setup From 55c26a8880bca000c2253349b08cb298a9fadb49 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 1 Oct 2019 15:11:18 -0700 Subject: [PATCH 012/232] [CPP-434] Initial version of query + test cases. --- .../Arithmetic/SignedComparisons.ql | 33 ++++++++++++++++ .../SignedComparisons/SignedComparisons.cpp | 38 +++++++++++++++++++ .../SignedComparisons/SignedComparisons.qlref | 1 + 3 files changed, 72 insertions(+) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql new file mode 100644 index 00000000000..b6dd8fb1d42 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql @@ -0,0 +1,33 @@ +/** + * @name Undefined result of signed test for overflow + * @description Testing for signed integer overflow by adding a value to + * a variable (or subtracting a value from a variable) and + * then comparing the result to said variable is not defined + * by the C or C++ standards. The comparison may produce an + * unintended result, or may be deleted by the compiler + * entirely. + * @kind problem + * @problem.severity warning + * @precision medium + * @id cpp/signed-overflow-check + * @tags reliability + * security + */ + +import cpp + +from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 +where + ro.getAnOperand() = bao and + (bao instanceof AddExpr or bao instanceof SubExpr) and + bao.getAnOperand() = va1 and + ro.getAnOperand() = va2 and + va1.getTarget() = va2.getTarget() and + /* + * if the addition/subtraction (`bao`) has been promoted to a signed type, + * then the other operand (`va2`) must also be signed and we have a signed + * comparison + */ + + bao.getFullyConverted().getType().(IntegralType).isSigned() +select ro, "Testing for signed overflow/underflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp new file mode 100644 index 00000000000..32d3bab19c7 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp @@ -0,0 +1,38 @@ +// Signed-comparison tests + +/* 1. Signed-signed comparison. The semantics are undefined. */ +bool cannotHoldAnother8(int n1) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + 8 < n1; // BAD +} +bool canHoldPreceding16(int n1) { + return n1 - 16 < n1; +} + +/* 2. Signed comparison with a narrower unsigned type. The narrower + type gets promoted to the (signed) larger type, and so the + semantics are undefined. */ +bool cannotHoldAnotherUShort(int n1, unsigned short delta) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // BAD +} +bool canHoldPrecedingUShort(int n1, unsigned short delta) { + return n1 - delta < n1; +} + +/* 3. Signed comparison with a non-narrower unsigned type. The + signed type gets promoted to (a possibly wider) unsigned type, + and the resulting comparison is unsigned. */ +bool cannotHoldAnotherUInt(int n1, unsigned int delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // GOOD +} +bool canHoldPrecedingUInt(int n1, unsigned int delta) { + return n1 - delta < n1; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref new file mode 100644 index 00000000000..f645e2e2408 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref @@ -0,0 +1 @@ +Likely Bugs/Arithmetic/SignedComparisons.ql From c9a9aff221ce2ecb60d7aef8bfceb6ece52c47df Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 1 Oct 2019 15:13:08 -0700 Subject: [PATCH 013/232] [CPP-434] Expected result. --- .../Arithmetic/SignedComparisons/SignedComparisons.expected | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected new file mode 100644 index 00000000000..bceb4fd0802 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected @@ -0,0 +1,4 @@ +| SignedComparisons.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:11:9:11:20 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:21:12:21:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:24:9:24:23 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | From 8c6caf2b4e79ffe785f79c067619e8e8ae1a87e8 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 12:27:16 -0700 Subject: [PATCH 014/232] [CPP-434] Rename everything to SignedOverflowCheck. Add .qlhelp. Deal with addition only, not subtraction. --- .../Arithmetic/SignedOverflowCheck-bad.cpp | 3 ++ .../Arithmetic/SignedOverflowCheck-good.cpp | 3 ++ .../Arithmetic/SignedOverflowCheck.qhelp | 42 +++++++++++++++++++ ...dComparisons.ql => SignedOverflowCheck.ql} | 15 +++---- .../SignedComparisons.expected | 4 -- .../SignedComparisons/SignedComparisons.qlref | 1 - .../SignedOverflowCheck.cpp} | 9 ---- .../SignedOverflowCheck.expected | 2 + .../SignedOverflowCheck.qlref | 1 + 9 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedComparisons.ql => SignedOverflowCheck.ql} (55%) delete mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected delete mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedComparisons/SignedComparisons.cpp => SignedOverflowCheck/SignedOverflowCheck.cpp} (82%) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp new file mode 100644 index 00000000000..e50273aacde --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp @@ -0,0 +1,3 @@ +bool foo(int n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp new file mode 100644 index 00000000000..2554e0d9371 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp @@ -0,0 +1,3 @@ +bool bar(int n1, unsigned int delta) { + return n1 + delta < n1; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp new file mode 100644 index 00000000000..253950c3bf4 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -0,0 +1,42 @@ + + + +

+Testing for signed integer overflow by adding a +value to a variable and then comparing the result to said variable +is not defined by the C or C++ standards. The comparison may +produce an unintended result, or may be deleted by the compiler +entirely. +

+
+ +

+Make sure that the comparison in question uses unsigned values. +

+
+ +

+In the following example, even though delta has been declared +unsigned short, C/C++ type promotion rules require that its +type is promoted to the larger type used in the addition and comparison, +namely a signed int. As a result, the entire expression is +evaluated using signed values and its value is therefore undefined. +

+ +

+In the next example, a value of type signed int is +getting added to a value ot type unsigned int. Because +the types are of the same size, C/C++ promotion rules dictate that +unsigned int is chosen as the overall type of the addition +operation. The entire expression is evaluated using unsigned +values, which is allowed and defined behavior per the C/C++ standard. +

+ +
+ +
  • Preserving Rules
  • +
  • Understand integer conversion rules
  • +
    +
    diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql similarity index 55% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index b6dd8fb1d42..9414ee773d7 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -1,11 +1,8 @@ /** * @name Undefined result of signed test for overflow - * @description Testing for signed integer overflow by adding a value to - * a variable (or subtracting a value from a variable) and - * then comparing the result to said variable is not defined - * by the C or C++ standards. The comparison may produce an - * unintended result, or may be deleted by the compiler - * entirely. + * @description Testing for oveflow by adding a value to a variable + * to see if it "wraps around" works only for + * `unsigned` integer values. * @kind problem * @problem.severity warning * @precision medium @@ -19,14 +16,14 @@ import cpp from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = bao and - (bao instanceof AddExpr or bao instanceof SubExpr) and + bao instanceof AddExpr and bao.getAnOperand() = va1 and ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and /* * if the addition/subtraction (`bao`) has been promoted to a signed type, - * then the other operand (`va2`) must also be signed and we have a signed - * comparison + * then the other operand (`va2`) must have been likewise promoted and so + * have a signed comparison */ bao.getFullyConverted().getType().(IntegralType).isSigned() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected deleted file mode 100644 index bceb4fd0802..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected +++ /dev/null @@ -1,4 +0,0 @@ -| SignedComparisons.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:11:9:11:20 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:21:12:21:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:24:9:24:23 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref deleted file mode 100644 index f645e2e2408..00000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref +++ /dev/null @@ -1 +0,0 @@ -Likely Bugs/Arithmetic/SignedComparisons.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp similarity index 82% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 32d3bab19c7..4f5ea296d7c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -7,9 +7,6 @@ bool cannotHoldAnother8(int n1) { // msvc 19.22 /O2: not deleted return n1 + 8 < n1; // BAD } -bool canHoldPreceding16(int n1) { - return n1 - 16 < n1; -} /* 2. Signed comparison with a narrower unsigned type. The narrower type gets promoted to the (signed) larger type, and so the @@ -20,9 +17,6 @@ bool cannotHoldAnotherUShort(int n1, unsigned short delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // BAD } -bool canHoldPrecedingUShort(int n1, unsigned short delta) { - return n1 - delta < n1; -} /* 3. Signed comparison with a non-narrower unsigned type. The signed type gets promoted to (a possibly wider) unsigned type, @@ -33,6 +27,3 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // GOOD } -bool canHoldPrecedingUInt(int n1, unsigned int delta) { - return n1 - delta < n1; -} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected new file mode 100644 index 00000000000..5963f1b340f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -0,0 +1,2 @@ +| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref new file mode 100644 index 00000000000..dde64840202 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref @@ -0,0 +1 @@ +Likely Bugs/Arithmetic/SignedOverflowCheck.ql From 16411d1b6e0bd9f57299a9934913d170b2cfd4ee Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 12:32:11 -0700 Subject: [PATCH 015/232] [CPP-434] Remove references to underflow and subtraction. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 9414ee773d7..18c54c01629 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -21,10 +21,10 @@ where ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and /* - * if the addition/subtraction (`bao`) has been promoted to a signed type, + * if the addition (`bao`) has been promoted to a signed type, * then the other operand (`va2`) must have been likewise promoted and so * have a signed comparison */ bao.getFullyConverted().getType().(IntegralType).isSigned() -select ro, "Testing for signed overflow/underflow may produce undefined results." +select ro, "Testing for signed overflow may produce undefined results." From 341dc12fc86713880ba56efd389ce2e74d9ad223 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 15:02:44 -0700 Subject: [PATCH 016/232] [CPP-434] Adjust expected output. --- .../SignedOverflowCheck/SignedOverflowCheck.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 5963f1b340f..4fc4cce41a2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,2 @@ -| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | From 872054a89a8ed4d8687402ca6d4f41344e036d94 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 17:59:19 -0700 Subject: [PATCH 017/232] [CPP-434] Narrow down query. --- .../Arithmetic/SignedOverflowCheck.ql | 14 ++--- .../SignedOverflowCheck.cpp | 52 +++++++++++++++++++ .../SignedOverflowCheck.expected | 1 + 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 18c54c01629..490b1a53a17 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -1,6 +1,6 @@ /** * @name Undefined result of signed test for overflow - * @description Testing for oveflow by adding a value to a variable + * @description Testing for overflow by adding a value to a variable * to see if it "wraps around" works only for * `unsigned` integer values. * @kind problem @@ -13,18 +13,18 @@ import cpp -from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 +from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where - ro.getAnOperand() = bao and - bao instanceof AddExpr and - bao.getAnOperand() = va1 and + ro.getAnOperand() = add and + add.getAnOperand() = va1 and ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and + (not exists(va1.getQualifier()) or va1.getQualifier() = va2.getQualifier()) and /* - * if the addition (`bao`) has been promoted to a signed type, + * if the addition (`add`) has been promoted to a signed type, * then the other operand (`va2`) must have been likewise promoted and so * have a signed comparison */ - bao.getFullyConverted().getType().(IntegralType).isSigned() + add.getExplicitlyConverted().getType().(IntegralType).isSigned() select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 4f5ea296d7c..92edcf1daf2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -27,3 +27,55 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // GOOD } + +bool shortShort1(unsigned short n1, unsigned short delta) { + // clang 8.0.0 -O2: deleted + // gcc 9.2 -O2: deleted + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // BAD +} + +bool shortShort2(unsigned short n1, unsigned short delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return (unsigned short)(n1 + delta) < n1; // GOOD +} + +/* Distinguish `varname` from `ptr->varname` and `obj.varname` */ +struct N { + unsigned short n1; +} n, *np; + +bool shortStruct1(unsigned short n1, unsigned short delta) { + return np->n1 + delta < n1; // GOOD +} + +bool shortStruct1a(unsigned short n1, unsigned short delta) { + return n1 + delta < n.n1; // GOOD +} + +bool shortStruct2(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n.n1; // GOOD +} + +struct se { + short xPos; + short yPos; + short xSize; + short ySize; +}; + +extern se *getSo(void); + +bool func1(se *so) { + se *o = getSo(); + if (so->xPos + so->xSize < o->xPos // GOOD + || so->xPos > o->xPos + o->xSize) { // GOOD + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return false; + } + return true; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 4fc4cce41a2..c1867e71c18 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,3 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From afa34b5054a13843c0425cd4613fd29694fecf27 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 14:07:20 -0700 Subject: [PATCH 018/232] [CPP-434] Improvements to Qhelp; hashCons-ify query. --- .../Arithmetic/SignedOverflowCheck.qhelp | 8 ++++---- .../Arithmetic/SignedOverflowCheck.ql | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 253950c3bf4..0fe57891534 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -5,7 +5,7 @@

    Testing for signed integer overflow by adding a -value to a variable and then comparing the result to said variable +value to a variable and then comparing the result to that variable is not defined by the C or C++ standards. The comparison may produce an unintended result, or may be deleted by the compiler entirely. @@ -27,7 +27,7 @@ evaluated using signed values and its value is therefore undefined.

    In the next example, a value of type signed int is -getting added to a value ot type unsigned int. Because +added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that unsigned int is chosen as the overall type of the addition operation. The entire expression is evaluated using unsigned @@ -36,7 +36,7 @@ values, which is allowed and defined behavior per the C/C++ standard. -

  • Preserving Rules
  • -
  • Understand integer conversion rules
  • +
  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • +
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 490b1a53a17..f01ee5dd607 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -12,19 +12,19 @@ */ import cpp +import semmle.code.cpp.valuenumbering.HashCons + +private predicate sameAccess(VariableAccess va1, VariableAccess va2) { + hashCons(va1) = hashCons(va2) +} from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and - va1.getTarget() = va2.getTarget() and - (not exists(va1.getQualifier()) or va1.getQualifier() = va2.getQualifier()) and - /* - * if the addition (`add`) has been promoted to a signed type, - * then the other operand (`va2`) must have been likewise promoted and so - * have a signed comparison - */ - - add.getExplicitlyConverted().getType().(IntegralType).isSigned() -select ro, "Testing for signed overflow may produce undefined results." + sameAccess(va1, va2) and + add.getExplicitlyConverted().getType().(IntegralType).isSigned() and + va2.getExplicitlyConverted().getType().(IntegralType).isSigned() +select va1, va1.getQualifier().getAQlClass(), va2, va2.getQualifier().getAQlClass(), ro, + "Testing for signed overflow may produce undefined results." From bd87d7bc76134f44b3884adc1220e00ead70a92b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 16:33:05 -0700 Subject: [PATCH 019/232] [CPP-434] Switch to global value numbering (GVN). Improve qlhelp doc. --- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 3 +++ .../Arithmetic/SignedOverflowCheck-good.cpp | 2 +- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 11 ++++++++++- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 9 ++++----- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp new file mode 100644 index 00000000000..293a8c6e49e --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -0,0 +1,3 @@ +bool bar(unsigned short n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp index 2554e0d9371..2670a4371f6 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp @@ -1,3 +1,3 @@ -bool bar(int n1, unsigned int delta) { +bool baz(int n1, unsigned int delta) { return n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 0fe57891534..c3147d23284 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,10 +22,19 @@ In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +evaluated using signed values and its value is therefore undefined.

    +In the following example, even though both n and delta +have been declared unsigned short, C/C++ type promotion rules +require that both parameters be promoted to the next bigger signed +integer type (in this case signed int) before being added together + so as to avoid overflows or underflows. As a result, the entire expression is +evaluated using signed values and its value is therefore undefined. +

    + +

    In the next example, a value of type signed int is added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index f01ee5dd607..21e602e2eb4 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -5,17 +5,17 @@ * `unsigned` integer values. * @kind problem * @problem.severity warning - * @precision medium + * @precision high * @id cpp/signed-overflow-check * @tags reliability * security */ import cpp -import semmle.code.cpp.valuenumbering.HashCons +import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate sameAccess(VariableAccess va1, VariableAccess va2) { - hashCons(va1) = hashCons(va2) + globalValueNumber(va1) = globalValueNumber(va2) } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 @@ -26,5 +26,4 @@ where sameAccess(va1, va2) and add.getExplicitlyConverted().getType().(IntegralType).isSigned() and va2.getExplicitlyConverted().getType().(IntegralType).isSigned() -select va1, va1.getQualifier().getAQlClass(), va2, va2.getQualifier().getAQlClass(), ro, - "Testing for signed overflow may produce undefined results." +select ro, "Testing for signed overflow may produce undefined results." From e617a05a1f12ccb3588524132f8856151ce7cf5d Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 17:20:25 -0700 Subject: [PATCH 020/232] [CPP-434] One bad usage is undetected; adjust test accordingly. --- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 92edcf1daf2..78d228890f0 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD + return n1 + delta < n1; // BAD [NOT DETECTED] } bool shortShort2(unsigned short n1, unsigned short delta) { diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index c1867e71c18..4fc4cce41a2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,3 +1,2 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From 0ccc0057f95314fa179a80216558bb6704eb1a94 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 8 Oct 2019 15:04:11 +0200 Subject: [PATCH 021/232] add Deferred model to Promises.qll --- change-notes/1.23/analysis-javascript.md | 1 + .../ql/src/semmle/javascript/Promises.qll | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 04b5e6cb541..87b12c19230 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -38,3 +38,4 @@ ## Changes to QL libraries * `Expr.getDocumentation()` now handles chain assignments. +* Added `Deferred` as a promise library in Promises.qll diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 858064e85a0..794a866aee2 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -32,6 +32,39 @@ module Bluebird { } } +/** + * Provides classes for working with various Deferred implementations + */ +module Deferred { + private DataFlow::SourceNode deferred() { + exists(VarAccess var, DataFlow::NewNode instantiation | + var.getName() = "Deferred" and + result = DataFlow::exprNode(var).getALocalSource() and + // Sanity check that result really is a Deferred implementation + instantiation = result.getAnInstantiation() and + exists(instantiation.getAMemberCall("resolve")) + ) + } + + /** + * A promise object created by a Deferred constructor + */ + private class DeferredPromiseDefinition extends PromiseDefinition, DataFlow::NewNode { + DeferredPromiseDefinition() { this = deferred().getAnInstantiation() } + + override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } + } + + /** + * A resolved promise created by a `new Deferred().resolve()` call. + */ + class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { + ResolvedDeferredPromiseDefinition() { this = any(DeferredPromiseDefinition def).getAMemberCall("resolve") } + + override DataFlow::Node getValue() { result = getArgument(0) } + } +} + /** * Provides classes for working with the `q` library (https://github.com/kriskowal/q). */ From 411ed702fb1eabc9f308a34abe6105b688d12c36 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 13:50:12 +0200 Subject: [PATCH 022/232] change change-notes --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 87b12c19230..70d903cb944 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -9,6 +9,7 @@ - [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible) * The call graph has been improved to resolve method calls in more cases. This may produce more security alerts. +* Promises derived from a Deferred object are now recognized. ## New queries @@ -38,4 +39,3 @@ ## Changes to QL libraries * `Expr.getDocumentation()` now handles chain assignments. -* Added `Deferred` as a promise library in Promises.qll From c7eb0f17a9e35a0d9e0be951373df7bcad9c4f87 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 13:59:00 +0200 Subject: [PATCH 023/232] add TaintTracking test for new Deferred model --- .../TaintTracking/BasicTaintTracking.expected | 1 + .../ql/test/library-tests/TaintTracking/promise.js | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 2722f67d6fd..77592a2e855 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,6 +69,7 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| promise.js:22:23:22:30 | source() | promise.js:22:7:22:31 | promise ... urce()) | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index cd5351720ba..87e89451d99 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -12,3 +12,12 @@ function closure() { resolver.resolve(source()); sink(resolver.promise); // NOT OK } + +class Deferred { + +} + +function deferred() { + var promise = new Deferred(); + sink(promise.resolve(source())); // NOT OK +} \ No newline at end of file From 4ec825b5b6f3dbb1ba8c5e20bf70963772c9bda0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 16:18:04 +0200 Subject: [PATCH 024/232] made model of Deferred more precise --- .../ql/src/semmle/javascript/Promises.qll | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 794a866aee2..362bb2f5063 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -37,10 +37,23 @@ module Bluebird { */ module Deferred { private DataFlow::SourceNode deferred() { - exists(VarAccess var, DataFlow::NewNode instantiation | - var.getName() = "Deferred" and - result = DataFlow::exprNode(var).getALocalSource() and - // Sanity check that result really is a Deferred implementation + ( + exists(Variable var | + var.getName() = "Deferred" and + (var.getADeclaration() instanceof LocalNamespaceDecl or var.getScope() instanceof GlobalScope) and + result = DataFlow::valueNode(var.getADefinition()) + ) + or + result.(DataFlow::ParameterNode).getName() = "Deferred" + or + exists(Function f | + f.getName() = "Deferred" and + result = DataFlow::valueNode(f) + ) + ) + and + // Sanity check that it is a Deferred implementation + exists(DataFlow::NewNode instantiation | instantiation = result.getAnInstantiation() and exists(instantiation.getAMemberCall("resolve")) ) From 7fc47d496a6cc817761fcfe06acb320dd0931a50 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 9 Oct 2019 16:40:19 -0700 Subject: [PATCH 025/232] [CPP-434] Much improved query (producing only true positives on a run of 75 projects). --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 10 +++------- .../SignedOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../SignedOverflowCheck/SignedOverflowCheck.expected | 1 + 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 21e602e2eb4..96de06c48b4 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -14,16 +14,12 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering -private predicate sameAccess(VariableAccess va1, VariableAccess va2) { - globalValueNumber(va1) = globalValueNumber(va2) -} - from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and - sameAccess(va1, va2) and - add.getExplicitlyConverted().getType().(IntegralType).isSigned() and - va2.getExplicitlyConverted().getType().(IntegralType).isSigned() + globalValueNumber(va1) = globalValueNumber(va2) and + add.getFullyConverted().getType().getUnspecifiedType().(IntegralType).isSigned() and + not add.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 78d228890f0..92edcf1daf2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD [NOT DETECTED] + return n1 + delta < n1; // BAD } bool shortShort2(unsigned short n1, unsigned short delta) { diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 4fc4cce41a2..c1867e71c18 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,3 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From 1ab965761b13be373375ce694d2bb887ed6d4351 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 9 Oct 2019 17:30:30 -0700 Subject: [PATCH 026/232] [CPP-434] Incorporate test from BadAdditionOverflowCheck. --- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 92edcf1daf2..e04a6d25f55 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -79,3 +79,7 @@ bool func1(se *so) { } return true; } + +bool checkOverflow3(unsigned int a, unsigned short b) { + return (a + b < a); // GOOD +} From 0a6b343820e43fd47efa61cf8acec0deab53c458 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Oct 2019 11:50:34 +0200 Subject: [PATCH 027/232] add "class Deferred{...}" as potential Deferred implementation to fix the tests --- javascript/ql/src/semmle/javascript/Promises.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 362bb2f5063..488adebab6e 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -46,10 +46,15 @@ module Deferred { or result.(DataFlow::ParameterNode).getName() = "Deferred" or - exists(Function f | + exists(Function f | f.getName() = "Deferred" and result = DataFlow::valueNode(f) ) + or + exists(ClassDefinition c | + c.getName() = "Deferred" and + result = DataFlow::valueNode(c) + ) ) and // Sanity check that it is a Deferred implementation From 33cd6de7294705a865fd901190b174ec0e268791 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 10 Oct 2019 18:11:35 -0700 Subject: [PATCH 028/232] [CPP-434] Improved query and test suite. --- .../Arithmetic/SignedOverflowCheck.ql | 9 +++++++-- .../SignedOverflowCheck.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 96de06c48b4..2dd4ae40152 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -14,12 +14,17 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private predicate isSignedWithoutUnsignedCast(Expr e) { + e.getType().getUnspecifiedType().(IntegralType).isSigned() and + not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() +} + from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - add.getFullyConverted().getType().getUnspecifiedType().(IntegralType).isSigned() and - not add.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + isSignedWithoutUnsignedCast(add) and + isSignedWithoutUnsignedCast(va2) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index e04a6d25f55..be8dd05f4f0 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -83,3 +83,22 @@ bool func1(se *so) { bool checkOverflow3(unsigned int a, unsigned short b) { return (a + b < a); // GOOD } + +struct C { + unsigned int length; +}; + +int checkOverflow4(unsigned int ioff, C c) { + // not deleted by gcc or clang + if ((int)(ioff + c.length) < (int)ioff) return 0; // GOOD + return 1; +} + +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +int overflow12(int codecdata_length) { + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length) { // GOOD + return -1; + } + return 1; +} From 31009d979d323eb496530ae99c9f719ebed67272 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 11 Oct 2019 12:04:34 +0200 Subject: [PATCH 029/232] add type tracking to detect instances --- .../ql/src/semmle/javascript/Promises.qll | 73 ++++++++++++------- .../library-tests/TaintTracking/promise.js | 2 + 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 488adebab6e..13eb1e8114e 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -36,39 +36,60 @@ module Bluebird { * Provides classes for working with various Deferred implementations */ module Deferred { - private DataFlow::SourceNode deferred() { - ( - exists(Variable var | + class DeferredClass extends DataFlow::SourceNode { + DeferredClass() { + exists(Variable var | var.getName() = "Deferred" and - (var.getADeclaration() instanceof LocalNamespaceDecl or var.getScope() instanceof GlobalScope) and - result = DataFlow::valueNode(var.getADefinition()) - ) - or - result.(DataFlow::ParameterNode).getName() = "Deferred" - or - exists(Function f | - f.getName() = "Deferred" and - result = DataFlow::valueNode(f) + ( + var.getADeclaration() instanceof LocalNamespaceDecl or + var.getScope() instanceof GlobalScope + ) and + this = DataFlow::valueNode(var.getADefinition()) ) or - exists(ClassDefinition c | - c.getName() = "Deferred" and - result = DataFlow::valueNode(c) + this.(DataFlow::ParameterNode).getName() = "Deferred" + or + exists(Function f | + f.getName() = "Deferred" and + this = DataFlow::valueNode(f) ) - ) - and - // Sanity check that it is a Deferred implementation - exists(DataFlow::NewNode instantiation | - instantiation = result.getAnInstantiation() and - exists(instantiation.getAMemberCall("resolve")) - ) + or + exists(ClassDefinition c | + c.getName() = "Deferred" and + this = DataFlow::valueNode(c) + ) + } + } + + class DeferredInstance extends DataFlow::NewNode { + DeferredClass deferredClass; + + DeferredInstance() { this = deferredClass.getAnInstantiation() } + + private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { + t.start() and + result = this + or + exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + } + + DeferredClass getDeferredClass() { result = deferredClass } + + DataFlow::CallNode getPromiseMemberCall(string methodName) { + result = ref(DataFlow::TypeTracker::end()).getAMemberCall(methodName) + } } /** * A promise object created by a Deferred constructor */ - private class DeferredPromiseDefinition extends PromiseDefinition, DataFlow::NewNode { - DeferredPromiseDefinition() { this = deferred().getAnInstantiation() } + private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { + DeferredPromiseDefinition() { + this = any(DeferredClass c | + exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("resolve")) and + exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("reject")) + ).getAnInstantiation() + } override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } } @@ -77,7 +98,9 @@ module Deferred { * A resolved promise created by a `new Deferred().resolve()` call. */ class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { - ResolvedDeferredPromiseDefinition() { this = any(DeferredPromiseDefinition def).getAMemberCall("resolve") } + ResolvedDeferredPromiseDefinition() { + this = any(DeferredPromiseDefinition def).getPromiseMemberCall("resolve") + } override DataFlow::Node getValue() { result = getArgument(0) } } diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index 87e89451d99..d16e57241e8 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -20,4 +20,6 @@ class Deferred { function deferred() { var promise = new Deferred(); sink(promise.resolve(source())); // NOT OK + + new Deferred().reject("foo") // <- a reject has to exist. } \ No newline at end of file From 592cb18bf486ba6f8b37abf291516e365d4f8e25 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 4 Oct 2019 16:28:38 +0200 Subject: [PATCH 030/232] add array callbacks to useOfReturnlessFunction query --- .../ql/src/Expressions/ExprHasNoEffect.ql | 115 +---------------- .../ql/src/Expressions/ExprHasNoEffect.qll | 121 ++++++++++++++++++ .../src/Statements/UseOfReturnlessFunction.ql | 63 ++++++++- 3 files changed, 178 insertions(+), 121 deletions(-) diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 14024ec8f38..929e84616f0 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -13,122 +13,9 @@ */ import javascript -import DOMProperties -import semmle.javascript.frameworks.xUnit -import semmle.javascript.RestrictedLocations import ExprHasNoEffect -/** - * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. - * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. - * - * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries - * no semantic information), and expression statements with an ordinary (non-JSDoc) comment - * attached to them. - */ -predicate isDeclaration(Expr e) { - (e instanceof VarAccess or e instanceof PropAccess) and - exists(e.getParent().(ExprStmt).getDocumentation().getATag()) -} - -/** - * Holds if there exists a getter for a property called `name` anywhere in the program. - */ -predicate isGetterProperty(string name) { - // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... - exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | - // ... where `descriptor` defines a getter - defProp.hasPropertyAttributeWrite("get", _) - or - // ... where `descriptor` may define a getter - exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | - descriptor.isIncomplete(_) - or - // minimal escape analysis for the descriptor - exists(DataFlow::InvokeNode invk | - not invk = defProp and - descriptor.flowsTo(invk.getAnArgument()) - ) - ) - ) - or - // there is an object expression with a getter property `name` - exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) -} - -/** - * A property access that may invoke a getter. - */ -class GetterPropertyAccess extends PropAccess { - override predicate isImpure() { isGetterProperty(getPropertyName()) } -} - -/** - * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where - * `dummy` is some expression whose value is discarded, and which simply - * exists to prevent the call from being interpreted as a direct eval. - */ -predicate isIndirectEval(CallExpr c, Expr dummy) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is - * some expression whose value is discarded, and which simply exists - * to prevent the call from being interpreted as a method call. - */ -predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1) = callee and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if evaluating `e` has no side effects (except potentially allocating - * and initializing a new object). - * - * For calls, we do not check whether their arguments have any side effects: - * even if they do, the call itself is useless and should be flagged by this - * query. - */ -predicate noSideEffects(Expr e) { - e.isPure() - or - // `new Error(...)`, `new SyntaxError(...)`, etc. - forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | - f.(ExternalType).getASupertype*().getName() = "Error" - ) -} from Expr e -where - noSideEffects(e) and - inVoidContext(e) and - // disregard pure expressions wrapped in a void(...) - not e instanceof VoidExpr and - // filter out directives (unknown directives are handled by UnknownDirective.ql) - not exists(Directive d | e = d.getExpr()) and - // or about externs - not e.inExternsFile() and - // don't complain about declarations - not isDeclaration(e) and - // exclude DOM properties, which sometimes have magical auto-update properties - not isDOMProperty(e.(PropAccess).getPropertyName()) and - // exclude xUnit.js annotations - not e instanceof XUnitAnnotation and - // exclude common patterns that are most likely intentional - not isIndirectEval(_, e) and - not isReceiverSuppressingCall(_, e, _) and - // exclude anonymous function expressions as statements; these can only arise - // from a syntax error we already flag - not exists(FunctionExpr fe, ExprStmt es | fe = e | - fe = es.getExpr() and - not exists(fe.getName()) - ) +where hasNoEffect(e) select e.(FirstLineOf), "This expression has no effect." diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 858f719ba0a..822bcbb26fa 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -3,6 +3,9 @@ */ import javascript +import DOMProperties +import semmle.javascript.frameworks.xUnit +import semmle.javascript.RestrictedLocations /** * Holds if `e` appears in a syntactic context where its value is discarded. @@ -37,3 +40,121 @@ predicate inVoidContext(Expr e) { or exists(LogicalBinaryExpr logical | e = logical.getRightOperand() and inVoidContext(logical)) } + + +/** + * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. + * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. + * + * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries + * no semantic information), and expression statements with an ordinary (non-JSDoc) comment + * attached to them. + */ +predicate isDeclaration(Expr e) { + (e instanceof VarAccess or e instanceof PropAccess) and + exists(e.getParent().(ExprStmt).getDocumentation().getATag()) +} + +/** + * Holds if there exists a getter for a property called `name` anywhere in the program. + */ +predicate isGetterProperty(string name) { + // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... + exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | + // ... where `descriptor` defines a getter + defProp.hasPropertyAttributeWrite("get", _) + or + // ... where `descriptor` may define a getter + exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | + descriptor.isIncomplete(_) + or + // minimal escape analysis for the descriptor + exists(DataFlow::InvokeNode invk | + not invk = defProp and + descriptor.flowsTo(invk.getAnArgument()) + ) + ) + ) + or + // there is an object expression with a getter property `name` + exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) +} + +/** + * A property access that may invoke a getter. + */ +class GetterPropertyAccess extends PropAccess { + override predicate isImpure() { isGetterProperty(getPropertyName()) } +} + +/** + * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where + * `dummy` is some expression whose value is discarded, and which simply + * exists to prevent the call from being interpreted as a direct eval. + */ +predicate isIndirectEval(CallExpr c, Expr dummy) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is + * some expression whose value is discarded, and which simply exists + * to prevent the call from being interpreted as a method call. + */ +predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1) = callee and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if evaluating `e` has no side effects (except potentially allocating + * and initializing a new object). + * + * For calls, we do not check whether their arguments have any side effects: + * even if they do, the call itself is useless and should be flagged by this + * query. + */ +predicate noSideEffects(Expr e) { + e.isPure() + or + // `new Error(...)`, `new SyntaxError(...)`, etc. + forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | + f.(ExternalType).getASupertype*().getName() = "Error" + ) +} + +/** + * Holds if the expression `e` should be reported as having no effect. + */ +predicate hasNoEffect(Expr e) { + noSideEffects(e) and + inVoidContext(e) and + // disregard pure expressions wrapped in a void(...) + not e instanceof VoidExpr and + // filter out directives (unknown directives are handled by UnknownDirective.ql) + not exists(Directive d | e = d.getExpr()) and + // or about externs + not e.inExternsFile() and + // don't complain about declarations + not isDeclaration(e) and + // exclude DOM properties, which sometimes have magical auto-update properties + not isDOMProperty(e.(PropAccess).getPropertyName()) and + // exclude xUnit.js annotations + not e instanceof XUnitAnnotation and + // exclude common patterns that are most likely intentional + not isIndirectEval(_, e) and + not isReceiverSuppressingCall(_, e, _) and + // exclude anonymous function expressions as statements; these can only arise + // from a syntax error we already flag + not exists(FunctionExpr fe, ExprStmt es | fe = e | + fe = es.getExpr() and + not exists(fe.getName()) + ) +} \ No newline at end of file diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index c63127b83a3..61a485313e4 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -82,17 +82,66 @@ predicate alwaysThrows(Function f) { ) } -from DataFlow::CallNode call -where +predicate callToVoidFunction(DataFlow::CallNode call, Function func) { not call.isIndefinite(_) and - forex(Function f | f = call.getACallee() | + func = call.getACallee() and + forall(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f) and not alwaysThrows(f) + ) +} + +predicate hasNonVoidCallbackMethod(string name) { + name = "every" or + name = "filter" or + name = "find" or + name = "findIndex" or + name = "flatMap" or + name = "map" or + name = "reduce" or + name = "reduceRight" or + name = "some" or + name = "sort" +} + +DataFlow::SourceNode array(DataFlow::TypeTracker t) { + t.start() and result instanceof DataFlow::ArrayCreationNode + or + exists (DataFlow::TypeTracker t2 | + result = array(t2).track(t2, t) + ) +} + +DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } + +predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { + hasNonVoidCallbackMethod(call.getMethodName()) and + func = call.getAnArgument().getALocalSource().asExpr() and + 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and + returnsVoid(func) and + not isStub(func) and + not alwaysThrows(func) and + ( + call.getReceiver().getALocalSource() = array() + or + call.getCalleeNode() instanceof LodashUnderscore::Member + ) +} + +from DataFlow::CallNode call, Function func, string name, string msg +where + ( + callToVoidFunction(call, func) and + msg = "the $@ does not return anything, yet the return value is used." and + name = "function " + call.getCalleeName() + or + voidArrayCallback(call, func) and + msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + "() is used." and + name = "callback function" ) and - not benignContext(call.asExpr()) and - + // Avoid double reporting from js/useless-expression + not hasNoEffect(func.getBodyStmt(func.getNumBodyStmt() - 1).(ExprStmt).getExpr()) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select - call, "the function $@ does not return anything, yet the return value is used.", call.getACallee(), call.getCalleeName() - + call, msg, func, name From a7c1c34e1e48a311057ae223d545ed59a54439ee Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 11 Oct 2019 17:14:58 +0200 Subject: [PATCH 031/232] fix test output, and add new test for array callbacks --- .../UseOfReturnlessFunction.expected | 11 ++++++----- .../Statements/UseOfReturnlessFunction/tst.js | 7 +++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 500d900ff9e..0dc283d5edc 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,5 +1,6 @@ -| tst.js:20:17:20:33 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:24:13:24:29 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:30:20:30:36 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | bothOnlyHaveSideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | bothOnlyHaveSideEffects | +| tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | +| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 8bb49f7e761..1306c6e7f65 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -68,4 +68,11 @@ var h = returnsValue() || alwaysThrows(); // OK! console.log(h); + + function equals(x, y) { + return x === y; + } + + var foo = [1,2,3].filter(n => {equals(n, 3)}) // NOT OK! + console.log(foo); })(); \ No newline at end of file From 5558922b31f4ad6290109d593f49d228177f27fa Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 11 Oct 2019 17:01:16 -0700 Subject: [PATCH 032/232] [CPP-434] Drop the requirement that RHS not be cast to unsigned, since overflow occurs on LHS. Adjust test case. --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 3 +-- .../SignedOverflowCheck/SignedOverflowCheck.cpp | 10 +++------- .../SignedOverflowCheck/SignedOverflowCheck.expected | 1 + 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 2dd4ae40152..076e47df701 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -25,6 +25,5 @@ where add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - isSignedWithoutUnsignedCast(add) and - isSignedWithoutUnsignedCast(va2) + isSignedWithoutUnsignedCast(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index be8dd05f4f0..4396d857884 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -94,11 +94,7 @@ int checkOverflow4(unsigned int ioff, C c) { return 1; } -#define AV_INPUT_BUFFER_PADDING_SIZE 64 - -int overflow12(int codecdata_length) { - if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length) { // GOOD - return -1; - } - return 1; +int overflow12(int n) { + // not deleted by gcc or clang + return (n + 32 <= (unsigned)n? -1: 1); // BAD } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index c1867e71c18..bc7b98fd3e2 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,3 +1,4 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | From 28056791a57d53a265cf6348d71e93a4aa60a4f8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 14 Oct 2019 14:14:26 +0200 Subject: [PATCH 033/232] add .getALocalSource() when testing for lodash-members --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 +++--- .../UseOfReturnlessFunction.expected | 1 + .../query-tests/Statements/UseOfReturnlessFunction/tst.js | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 61a485313e4..2d70cecb0d3 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -113,8 +113,8 @@ DataFlow::SourceNode array(DataFlow::TypeTracker t) { DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } -predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { - hasNonVoidCallbackMethod(call.getMethodName()) and +predicate voidArrayCallback(DataFlow::CallNode call, Function func) { + hasNonVoidCallbackMethod(call.getCalleeName()) and func = call.getAnArgument().getALocalSource().asExpr() and 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and returnsVoid(func) and @@ -123,7 +123,7 @@ predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { ( call.getReceiver().getALocalSource() = array() or - call.getCalleeNode() instanceof LodashUnderscore::Member + call.getCalleeNode().getALocalSource() instanceof LodashUnderscore::Member ) } diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 0dc283d5edc..98ae4e3696c 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -4,3 +4,4 @@ | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | | tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | +| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 1306c6e7f65..2b523223e91 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -75,4 +75,8 @@ var foo = [1,2,3].filter(n => {equals(n, 3)}) // NOT OK! console.log(foo); + + import { filter } from 'lodash' + var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK! + console.log(bar); })(); \ No newline at end of file From f40c21bf6ea0f9e4bc25e8bfa4897eb6b1950333 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 14 Oct 2019 08:06:02 -0700 Subject: [PATCH 034/232] [CPP-434] Add release note. --- change-notes/1.23/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 5a97e1347bb..24fa06e9bbf 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,6 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | This query checks for when two signed values are added together to test for overflow (`a + b < a`), which is undefined behavior. | ## Changes to existing queries From fb625c12ef7d5d00f33bb88437c3575515301a6b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 16 Oct 2019 14:31:11 -0700 Subject: [PATCH 035/232] [CPP-434] Move SignedOverflowCheck test to BadAdditionOverflowCheck directory; add additional tests. --- .../BadAdditionOverflowCheck.expected | 2 ++ .../SignedOverflowCheck.cpp | 14 ++++++++++++++ .../SignedOverflowCheck.expected | 3 +++ .../SignedOverflowCheck.qlref | 0 4 files changed, 19 insertions(+) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.cpp (86%) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.expected (57%) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.qlref (100%) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected index 9cb1aaa02af..920a1f820f8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected @@ -1 +1,3 @@ +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Bad overflow check. | +| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Bad overflow check. | | test.cpp:3:11:3:19 | ... < ... | Bad overflow check. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp similarity index 86% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 4396d857884..4ef9d83b63d 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -98,3 +98,17 @@ int overflow12(int n) { // not deleted by gcc or clang return (n + 32 <= (unsigned)n? -1: 1); // BAD } + +bool multipleCasts(char x) { + // clang 9.0.0 -O2: deleted + // gcc 9.2 -O2: deleted + // msvc 19.22 /O2: deleted + return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // BAD +} + +bool multipleCasts2(char x) { + // clang 9.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected similarity index 57% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index bc7b98fd3e2..d4fd6334eaa 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -2,3 +2,6 @@ | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | +| test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref similarity index 100% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref From 70441edacf71f7c7a57a367ebb4448b031dfbf35 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 17 Oct 2019 16:41:17 -0700 Subject: [PATCH 036/232] [CPP-434] Additional test case; improve QHelp by including themes from the BadAdditionOverflowCheck QHelp. --- ...k-bad.cpp => SignedOverflowCheck-bad1.cpp} | 0 .../Arithmetic/SignedOverflowCheck-good1.cpp | 3 +++ ...good.cpp => SignedOverflowCheck-good2.cpp} | 0 .../Arithmetic/SignedOverflowCheck.qhelp | 21 ++++++++++++++----- .../SignedOverflowCheck.cpp | 4 ++++ 5 files changed, 23 insertions(+), 5 deletions(-) rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedOverflowCheck-bad.cpp => SignedOverflowCheck-bad1.cpp} (100%) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedOverflowCheck-good.cpp => SignedOverflowCheck-good2.cpp} (100%) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp new file mode 100644 index 00000000000..d79d3ccbe93 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -0,0 +1,3 @@ +bool baf(unsigned short n1, unsigned short delta) { + return n1 + (unsigned)delta < n1; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index c3147d23284..49fc8afb757 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -24,17 +24,28 @@ type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is evaluated using signed values and its value is therefore undefined.

    - +

    In the following example, even though both n and delta have been declared unsigned short, C/C++ type promotion rules require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together - so as to avoid overflows or underflows. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +integer type (in this case signed int) before being added together. +As a result, the entire expression is evaluated using signed values +and its value is therefore undefined. (Note, however, that the addition cannot +overflow since we are adding two "small" unsigned short values.)

    +The following example builds upon the previous one. Again, we have two +unsigned short values getting promoted to a wider type. However, +since delta is explicitly cast to an unsigned type, +n1 (on both sides of the comparison) is promoted to +unsigned as well. Since we are now operating on +unsigned values, the overflow check is defined and supported by +standard C/C++. +

    + +

    In the next example, a value of type signed int is added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that @@ -42,7 +53,7 @@ the types are of the same size, C/C++ promotion rules dictate that operation. The entire expression is evaluated using unsigned values, which is allowed and defined behavior per the C/C++ standard.

    - +
  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 4ef9d83b63d..febb45e8ecc 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -112,3 +112,7 @@ bool multipleCasts2(char x) { // msvc 19.22 /O2: not deleted return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] } + +int does_it_overflow(int n1, unsigned short delta) { + return n1 + (unsigned)delta < n1; // GOOD +} From 6772fa1352ca82568d384566df0d80033176c6f5 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 17 Oct 2019 17:21:14 -0700 Subject: [PATCH 037/232] [CPP-434] Reformat QHelp. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 49fc8afb757..741dda54a82 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -26,10 +26,10 @@ evaluated using signed values and its value is therefore undefined.

    -In the following example, even though both n and delta -have been declared unsigned short, C/C++ type promotion rules +In the following example, even though both n and delta +have been declared unsigned short, C/C++ type promotion rules require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together. +integer type (in this case signed int) before being added together. As a result, the entire expression is evaluated using signed values and its value is therefore undefined. (Note, however, that the addition cannot overflow since we are adding two "small" unsigned short values.) From 2e0244cda62deea17afe438c30e289d5c97913ca Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 21 Oct 2019 20:21:41 +0200 Subject: [PATCH 038/232] address review feedback --- .../ql/src/Expressions/ExprHasNoEffect.ql | 1 + .../ql/src/Expressions/ExprHasNoEffect.qll | 1 - .../src/Statements/UseOfReturnlessFunction.ql | 25 +++++++++++++++---- .../UseOfReturnlessFunction.expected | 8 +++--- .../Statements/UseOfReturnlessFunction/tst.js | 3 +++ 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 929e84616f0..917ab81a3e7 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -14,6 +14,7 @@ import javascript import ExprHasNoEffect +import semmle.javascript.RestrictedLocations from Expr e diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 822bcbb26fa..bee980e5fd8 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -5,7 +5,6 @@ import javascript import DOMProperties import semmle.javascript.frameworks.xUnit -import semmle.javascript.RestrictedLocations /** * Holds if `e` appears in a syntactic context where its value is discarded. diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 2d70cecb0d3..fe03c66cf4a 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -82,8 +82,19 @@ predicate alwaysThrows(Function f) { ) } +/** + * Holds if the last statement in the function is flagged by the js/useless-expression query. + */ +predicate alwaysHasNoEffect(Function f) { + exists(ReachableBasicBlock entry, DataFlow::Node noEffect | + entry = f.getEntryBB() and + hasNoEffect(noEffect.asExpr()) and + entry.dominates(noEffect.getBasicBlock()) + ) +} + predicate callToVoidFunction(DataFlow::CallNode call, Function func) { - not call.isIndefinite(_) and + not call.isIncomplete() and func = call.getACallee() and forall(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f) and not alwaysThrows(f) @@ -113,6 +124,11 @@ DataFlow::SourceNode array(DataFlow::TypeTracker t) { DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } +/** + * Holds if `call` is an Array or Lodash method accepting a callback `func`, + * where the `call` expects a callback that returns an expression, + * but `func` does return a value. + */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and func = call.getAnArgument().getALocalSource().asExpr() and @@ -132,15 +148,14 @@ where ( callToVoidFunction(call, func) and msg = "the $@ does not return anything, yet the return value is used." and - name = "function " + call.getCalleeName() + name = func.describe() or voidArrayCallback(call, func) and - msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + "() is used." and + msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and name = "callback function" ) and not benignContext(call.asExpr()) and - // Avoid double reporting from js/useless-expression - not hasNoEffect(func.getBodyStmt(func.getNumBodyStmt() - 1).(ExprStmt).getExpr()) and + not alwaysHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 98ae4e3696c..f23b702bf20 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,7 +1,7 @@ | tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | -| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | -| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | +| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | +| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 2b523223e91..8a6a44707ed 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -79,4 +79,7 @@ import { filter } from 'lodash' var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK! console.log(bar); + + var baz = [1,2,3].filter(n => {n === 3}) // OK + console.log(baz); })(); \ No newline at end of file From 22925189335f54dbd08c08cf1f4e20d178d94816 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 21 Oct 2019 17:04:46 -0700 Subject: [PATCH 039/232] [CPP-434] Change query so it flags overflows that were cast to `unsigned`. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 4 ++-- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../BadAdditionOverflowCheck/SignedOverflowCheck.expected | 2 ++ .../Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 076e47df701..9ad9fa15727 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -15,8 +15,8 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() and - not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + e.getType().getUnspecifiedType().(IntegralType).isSigned() /*and + not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned()*/ } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index febb45e8ecc..86757984326 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -39,7 +39,7 @@ bool shortShort2(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (unsigned short)(n1 + delta) < n1; // GOOD + return (unsigned short)(n1 + delta) < n1; // BAD: n1 + delta overflow undefined } /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index d4fd6334eaa..9f35d51c4e3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,7 +1,9 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:42:9:42:41 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | | test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | +| test.cpp:8:11:8:37 | ... < ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 4669b709bc4..3c82f602cb9 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -5,7 +5,7 @@ bool checkOverflow1(unsigned short a, unsigned short b) { // Test for BadAdditionOverflowCheck. bool checkOverflow2(unsigned short a, unsigned short b) { - return ((unsigned short)(a + b) < a); // GOOD: explicit cast + return ((unsigned short)(a + b) < a); // BAD: a + b overflow undefined } // Test for PointlessSelfComparison. From 9bc4c2d9a506a53568d1b1b68d1b065de0bbc8cc Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 21 Oct 2019 18:40:20 -0700 Subject: [PATCH 040/232] [CPP-434] Ctrl + Shift + F. --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 9ad9fa15727..387a9397e43 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -15,9 +15,13 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() /*and - not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned()*/ -} + e.getType().getUnspecifiedType().(IntegralType).isSigned() + /* + * and + * not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + */ + + } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where From db22916850202d1e159fc21e651670f501d29bc2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 22 Oct 2019 09:37:19 +0200 Subject: [PATCH 041/232] fix the alwaysHasNoEffect predicate, and rename it to lastStatementHasNoEffect --- .../ql/src/Statements/UseOfReturnlessFunction.ql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index fe03c66cf4a..0f168e263dd 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -85,11 +85,11 @@ predicate alwaysThrows(Function f) { /** * Holds if the last statement in the function is flagged by the js/useless-expression query. */ -predicate alwaysHasNoEffect(Function f) { - exists(ReachableBasicBlock entry, DataFlow::Node noEffect | - entry = f.getEntryBB() and - hasNoEffect(noEffect.asExpr()) and - entry.dominates(noEffect.getBasicBlock()) +predicate lastStatementHasNoEffect(Function f) { + exists(DataFlow::Node noEffect | + noEffect.getContainer() = f and + hasNoEffect(noEffect.asExpr()) and + not exists(noEffect.getASuccessor()) ) } @@ -155,7 +155,7 @@ where name = "callback function" ) and not benignContext(call.asExpr()) and - not alwaysHasNoEffect(func) and + not lastStatementHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select From ad3185c5586efc622cea59956868e729a545ae4a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 22 Oct 2019 10:33:05 +0200 Subject: [PATCH 042/232] simplify lastStatementHasNoEffect and use the control-flow to determine which statement is the last --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 0f168e263dd..2fc3f01a560 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -86,11 +86,7 @@ predicate alwaysThrows(Function f) { * Holds if the last statement in the function is flagged by the js/useless-expression query. */ predicate lastStatementHasNoEffect(Function f) { - exists(DataFlow::Node noEffect | - noEffect.getContainer() = f and - hasNoEffect(noEffect.asExpr()) and - not exists(noEffect.getASuccessor()) - ) + hasNoEffect(f.getExit().getAPredecessor()) } predicate callToVoidFunction(DataFlow::CallNode call, Function func) { From 06f63c54779ddb2232dceccb071d1189a055a585 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 13:06:33 -0700 Subject: [PATCH 043/232] [CPP-434] Incremental changes to SignedOverflowCheck.cpp test suite. --- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 86757984326..af6593dc0c3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -32,14 +32,14 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD + return n1 + delta < n1; // BAD: will always be false } bool shortShort2(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (unsigned short)(n1 + delta) < n1; // BAD: n1 + delta overflow undefined + return (unsigned short)(n1 + delta) < n1; // GOOD } /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ @@ -110,9 +110,14 @@ bool multipleCasts2(char x) { // clang 9.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // BAD } int does_it_overflow(int n1, unsigned short delta) { return n1 + (unsigned)delta < n1; // GOOD } + +int overflow12b(int n) { + // not deleted by gcc or clang + return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD +} From ad5aa182dfb0b4e8a6342c66c527a4265aae6d3b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 15:21:30 -0700 Subject: [PATCH 044/232] [CPP-434] When analyzing overflow, discard any explicit casts. Use the simple range analysis library to detect which additions may in fact overflow. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 15 ++++----------- .../SignedOverflowCheck.cpp | 12 ++++++------ .../SignedOverflowCheck.expected | 7 +------ .../Arithmetic/BadAdditionOverflowCheck/test.cpp | 4 ++-- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 387a9397e43..f1b65dd4a96 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -12,16 +12,8 @@ */ import cpp -import semmle.code.cpp.valuenumbering.GlobalValueNumbering - -private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() - /* - * and - * not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() - */ - - } +private import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where @@ -29,5 +21,6 @@ where add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - isSignedWithoutUnsignedCast(add) + add.getType().getUnspecifiedType().(IntegralType).isSigned() and + exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index af6593dc0c3..72767c54aab 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD: will always be false + return n1 + delta < n1; // GOOD: always false, but will never overflow } bool shortShort2(unsigned short n1, unsigned short delta) { @@ -96,28 +96,28 @@ int checkOverflow4(unsigned int ioff, C c) { int overflow12(int n) { // not deleted by gcc or clang - return (n + 32 <= (unsigned)n? -1: 1); // BAD + return (n + 32 <= (unsigned)n? -1: 1); // BAD: n + 32 can overflow } bool multipleCasts(char x) { // clang 9.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: deleted - return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // BAD + return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow } bool multipleCasts2(char x) { // clang 9.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // BAD + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD: cannot overflow } int does_it_overflow(int n1, unsigned short delta) { - return n1 + (unsigned)delta < n1; // GOOD + return n1 + (unsigned)delta < n1; // GOOD: everything converted to unsigned } int overflow12b(int n) { // not deleted by gcc or clang - return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD + return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index 9f35d51c4e3..eaf6a7ac1e4 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,9 +1,4 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:42:9:42:41 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | -| test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | -| test.cpp:8:11:8:37 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 3c82f602cb9..e36956f9c69 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -1,11 +1,11 @@ // Test for BadAdditionOverflowCheck. bool checkOverflow1(unsigned short a, unsigned short b) { - return (a + b < a); // BAD: a + b is automatically promoted to int. + return (a + b < a); // BAD: comparison always false (due to promotion). } // Test for BadAdditionOverflowCheck. bool checkOverflow2(unsigned short a, unsigned short b) { - return ((unsigned short)(a + b) < a); // BAD: a + b overflow undefined + return ((unsigned short)(a + b) < a); // GOOD } // Test for PointlessSelfComparison. From 6eb0f0709ae6e191a15c831d0708c9f187580d5d Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 17:28:35 -0700 Subject: [PATCH 045/232] [CPP-434] Update Qhelp. --- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 3 ++- .../Arithmetic/SignedOverflowCheck.qhelp | 20 ++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp index 293a8c6e49e..d4d9cd75393 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -1,3 +1,4 @@ bool bar(unsigned short n1, unsigned short delta) { - return n1 + delta < n1; // BAD + // NB: Comparison is always false + return n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 741dda54a82..9b9d358dea2 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,17 +22,19 @@ In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +evaluated using signed integers and may overflow, and hence +is undefined.

    In the following example, even though both n and delta -have been declared unsigned short, C/C++ type promotion rules -require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together. -As a result, the entire expression is evaluated using signed values -and its value is therefore undefined. (Note, however, that the addition cannot -overflow since we are adding two "small" unsigned short values.) +have been declared unsigned short, both are promoted to +signed int prior to addition. Because we started out with the +narrower short type, the addition is guaranteed not to overflow +and is therefore defined. But the fact that n1 + delta never +overflows means that the condition n1 + delta < n1 will never +hold true, which likely is not what the programmer intended. (see also the +BadArithmeticOverflow.Check.ql query).

    @@ -40,7 +42,7 @@ The following example builds upon the previous one. Again, we have two unsigned short values getting promoted to a wider type. However, since delta is explicitly cast to an unsigned type, n1 (on both sides of the comparison) is promoted to -unsigned as well. Since we are now operating on +unsigned int as well. Since we are now operating on unsigned values, the overflow check is defined and supported by standard C/C++.

    @@ -48,7 +50,7 @@ standard C/C++.

    In the next example, a value of type signed int is added to a value of type unsigned int. Because -the types are of the same size, C/C++ promotion rules dictate that +the types are of the same size, C/C++ conversion rules dictate that unsigned int is chosen as the overall type of the addition operation. The entire expression is evaluated using unsigned values, which is allowed and defined behavior per the C/C++ standard. From 7a6ec83572aa387e042328328b2607148dc19410 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 23 Oct 2019 11:50:58 +0200 Subject: [PATCH 046/232] C++: No CopyValue for immediately discarded exprs Expressions like the `e` in `e;` or `e, e2`, whose result is immediately discarded, should not get a synthetic `CopyValue`. This removes a lot of redundancy from the IR. To prevent these expressions from being confused with the expressions from which they get their result, the predicate `getInstructionConvertedResultExpression` now suppresses results for expressions that don't produce their own result. This should fix the mapping between expressions and IR data-flow nodes. --- .../raw/internal/IRConstruction.qll | 11 +- .../raw/internal/TranslatedExpr.qll | 64 +- .../ir/escape/points_to.expected | 19 - .../test/library-tests/ir/ir/raw_ir.expected | 2120 ++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 83 +- .../ir/ssa/unaliased_ssa_ir.expected | 83 +- .../syntax-zoo/aliased_ssa_sanity.expected | 2 +- .../syntax-zoo/raw_sanity.expected | 13 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 2 +- 9 files changed, 1094 insertions(+), 1303 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 314eda43a4c..d0f70f61498 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -49,20 +49,23 @@ private module Cached { Expr getInstructionConvertedResultExpression(Instruction instruction) { exists(TranslatedExpr translatedExpr | translatedExpr = getTranslatedExpr(result) and - instruction = translatedExpr.getResult() + instruction = translatedExpr.getResult() and + // Only associate `instruction` with this expression if the translated + // expression actually produced the instruction; not if it merely + // forwarded the result of another translated expression. + instruction = translatedExpr.getInstruction(_) ) } cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) { - exists(Expr converted, TranslatedExpr translatedExpr | + exists(Expr converted | result = converted.(Conversion).getExpr+() or result = converted | not result instanceof Conversion and - translatedExpr = getTranslatedExpr(converted) and - instruction = translatedExpr.getResult() + converted = getInstructionConvertedResultExpression(instruction) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index fbecb10cd24..7b9417b570d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -2547,27 +2547,45 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { // This should ideally be a dispatch predicate on TranslatedNonConstantExpr, // but it doesn't look monotonic to QL. predicate exprNeedsCopyIfNotLoaded(Expr expr) { - expr instanceof AssignExpr - or - expr instanceof AssignOperation and - not expr.isPRValueCategory() // is C++ - or - expr instanceof PrefixCrementOperation and - not expr.isPRValueCategory() // is C++ - or - expr instanceof PointerDereferenceExpr - or - expr instanceof AddressOfExpr - or - expr instanceof BuiltInOperationBuiltInAddressOf - or - // No case for ParenthesisExpr to avoid getting too many instructions - expr instanceof ReferenceDereferenceExpr - or - expr instanceof ReferenceToExpr - or - expr instanceof CommaExpr - or - expr instanceof ConditionDeclExpr - // TODO: simplify TranslatedStmtExpr too + ( + expr instanceof AssignExpr + or + expr instanceof AssignOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PrefixCrementOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PointerDereferenceExpr + or + expr instanceof AddressOfExpr + or + expr instanceof BuiltInOperationBuiltInAddressOf + or + // No case for ParenthesisExpr to avoid getting too many instructions + expr instanceof ReferenceDereferenceExpr + or + expr instanceof ReferenceToExpr + or + expr instanceof CommaExpr + or + expr instanceof ConditionDeclExpr + // TODO: simplify TranslatedStmtExpr too + ) and + not exprImmediatelyDiscarded(expr) +} + +/** + * Holds if `expr` is immediately discarded. Such expressions do not need a + * `CopyValue` because it's unlikely that anyone is interested in their value. + */ +private predicate exprImmediatelyDiscarded(Expr expr) { + exists(ExprStmt s | + s = expr.getParent() and + not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt()) + ) + or + exists(CommaExpr c | c.getLeftOperand() = expr) + or + exists(ForStmt for | for.getUpdate() = expr) } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index e6fefda7bb5..c58d97f7988 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,24 +1,14 @@ -| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 | -| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | | escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | | escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | | escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | @@ -27,38 +17,31 @@ | escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | @@ -97,9 +80,7 @@ | escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | -| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | | escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 | -| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | | escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 9c80e889a02..d7c144f7181 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -66,11 +66,10 @@ bad_asts.cpp: #-----| r0_10(error) = Load : &:r0_9, ~mu0_2 # 33| r0_11(glval) = VariableAddress[x] : # 33| mu0_12(int) = Store : &:r0_11, r0_10 -# 33| r0_13(glval) = CopyValue : r0_11 -# 34| v0_14(void) = NoOp : -# 30| v0_15(void) = ReturnVoid : -# 30| v0_16(void) = UnmodeledUse : mu* -# 30| v0_17(void) = ExitFunction : +# 34| v0_13(void) = NoOp : +# 30| v0_14(void) = ReturnVoid : +# 30| v0_15(void) = UnmodeledUse : mu* +# 30| v0_16(void) = ExitFunction : clang.cpp: # 5| int* globalIntAddress() @@ -202,20 +201,18 @@ ir.cpp: # 46| r0_15(short) = Convert : r0_14 # 46| r0_16(glval) = VariableAddress[y] : # 46| mu0_17(short) = Store : &:r0_16, r0_15 -# 46| r0_18(glval) = CopyValue : r0_16 -# 47| r0_19(glval) = VariableAddress[x] : -# 47| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 47| r0_21(glval) = VariableAddress[y] : -# 47| r0_22(short) = Load : &:r0_21, ~mu0_2 -# 47| r0_23(int) = Convert : r0_22 -# 47| r0_24(int) = Mul : r0_20, r0_23 -# 47| r0_25(glval) = VariableAddress[x] : -# 47| mu0_26(int) = Store : &:r0_25, r0_24 -# 47| r0_27(glval) = CopyValue : r0_25 -# 48| v0_28(void) = NoOp : -# 43| v0_29(void) = ReturnVoid : -# 43| v0_30(void) = UnmodeledUse : mu* -# 43| v0_31(void) = ExitFunction : +# 47| r0_18(glval) = VariableAddress[x] : +# 47| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 47| r0_20(glval) = VariableAddress[y] : +# 47| r0_21(short) = Load : &:r0_20, ~mu0_2 +# 47| r0_22(int) = Convert : r0_21 +# 47| r0_23(int) = Mul : r0_19, r0_22 +# 47| r0_24(glval) = VariableAddress[x] : +# 47| mu0_25(int) = Store : &:r0_24, r0_23 +# 48| v0_26(void) = NoOp : +# 43| v0_27(void) = ReturnVoid : +# 43| v0_28(void) = UnmodeledUse : mu* +# 43| v0_29(void) = ExitFunction : # 50| void IntegerOps(int, int) # 50| Block 0 @@ -235,185 +232,160 @@ ir.cpp: # 53| r0_13(int) = Add : r0_10, r0_12 # 53| r0_14(glval) = VariableAddress[z] : # 53| mu0_15(int) = Store : &:r0_14, r0_13 -# 53| r0_16(glval) = CopyValue : r0_14 -# 54| r0_17(glval) = VariableAddress[x] : -# 54| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 54| r0_19(glval) = VariableAddress[y] : -# 54| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 54| r0_21(int) = Sub : r0_18, r0_20 -# 54| r0_22(glval) = VariableAddress[z] : -# 54| mu0_23(int) = Store : &:r0_22, r0_21 -# 54| r0_24(glval) = CopyValue : r0_22 -# 55| r0_25(glval) = VariableAddress[x] : +# 54| r0_16(glval) = VariableAddress[x] : +# 54| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 54| r0_18(glval) = VariableAddress[y] : +# 54| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 54| r0_20(int) = Sub : r0_17, r0_19 +# 54| r0_21(glval) = VariableAddress[z] : +# 54| mu0_22(int) = Store : &:r0_21, r0_20 +# 55| r0_23(glval) = VariableAddress[x] : +# 55| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 55| r0_25(glval) = VariableAddress[y] : # 55| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 55| r0_27(glval) = VariableAddress[y] : -# 55| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 55| r0_29(int) = Mul : r0_26, r0_28 -# 55| r0_30(glval) = VariableAddress[z] : -# 55| mu0_31(int) = Store : &:r0_30, r0_29 -# 55| r0_32(glval) = CopyValue : r0_30 -# 56| r0_33(glval) = VariableAddress[x] : -# 56| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 56| r0_35(glval) = VariableAddress[y] : -# 56| r0_36(int) = Load : &:r0_35, ~mu0_2 -# 56| r0_37(int) = Div : r0_34, r0_36 -# 56| r0_38(glval) = VariableAddress[z] : -# 56| mu0_39(int) = Store : &:r0_38, r0_37 -# 56| r0_40(glval) = CopyValue : r0_38 -# 57| r0_41(glval) = VariableAddress[x] : -# 57| r0_42(int) = Load : &:r0_41, ~mu0_2 -# 57| r0_43(glval) = VariableAddress[y] : -# 57| r0_44(int) = Load : &:r0_43, ~mu0_2 -# 57| r0_45(int) = Rem : r0_42, r0_44 -# 57| r0_46(glval) = VariableAddress[z] : -# 57| mu0_47(int) = Store : &:r0_46, r0_45 -# 57| r0_48(glval) = CopyValue : r0_46 -# 59| r0_49(glval) = VariableAddress[x] : -# 59| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 59| r0_51(glval) = VariableAddress[y] : -# 59| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 59| r0_53(int) = BitAnd : r0_50, r0_52 -# 59| r0_54(glval) = VariableAddress[z] : -# 59| mu0_55(int) = Store : &:r0_54, r0_53 -# 59| r0_56(glval) = CopyValue : r0_54 -# 60| r0_57(glval) = VariableAddress[x] : -# 60| r0_58(int) = Load : &:r0_57, ~mu0_2 -# 60| r0_59(glval) = VariableAddress[y] : -# 60| r0_60(int) = Load : &:r0_59, ~mu0_2 -# 60| r0_61(int) = BitOr : r0_58, r0_60 -# 60| r0_62(glval) = VariableAddress[z] : -# 60| mu0_63(int) = Store : &:r0_62, r0_61 -# 60| r0_64(glval) = CopyValue : r0_62 -# 61| r0_65(glval) = VariableAddress[x] : -# 61| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 61| r0_67(glval) = VariableAddress[y] : -# 61| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 61| r0_69(int) = BitXor : r0_66, r0_68 -# 61| r0_70(glval) = VariableAddress[z] : -# 61| mu0_71(int) = Store : &:r0_70, r0_69 -# 61| r0_72(glval) = CopyValue : r0_70 -# 63| r0_73(glval) = VariableAddress[x] : -# 63| r0_74(int) = Load : &:r0_73, ~mu0_2 -# 63| r0_75(glval) = VariableAddress[y] : -# 63| r0_76(int) = Load : &:r0_75, ~mu0_2 -# 63| r0_77(int) = ShiftLeft : r0_74, r0_76 -# 63| r0_78(glval) = VariableAddress[z] : -# 63| mu0_79(int) = Store : &:r0_78, r0_77 -# 63| r0_80(glval) = CopyValue : r0_78 -# 64| r0_81(glval) = VariableAddress[x] : -# 64| r0_82(int) = Load : &:r0_81, ~mu0_2 -# 64| r0_83(glval) = VariableAddress[y] : -# 64| r0_84(int) = Load : &:r0_83, ~mu0_2 -# 64| r0_85(int) = ShiftRight : r0_82, r0_84 -# 64| r0_86(glval) = VariableAddress[z] : -# 64| mu0_87(int) = Store : &:r0_86, r0_85 -# 64| r0_88(glval) = CopyValue : r0_86 -# 66| r0_89(glval) = VariableAddress[x] : -# 66| r0_90(int) = Load : &:r0_89, ~mu0_2 -# 66| r0_91(glval) = VariableAddress[z] : -# 66| mu0_92(int) = Store : &:r0_91, r0_90 -# 66| r0_93(glval) = CopyValue : r0_91 -# 68| r0_94(glval) = VariableAddress[x] : -# 68| r0_95(int) = Load : &:r0_94, ~mu0_2 -# 68| r0_96(glval) = VariableAddress[z] : -# 68| r0_97(int) = Load : &:r0_96, ~mu0_2 -# 68| r0_98(int) = Add : r0_97, r0_95 -# 68| mu0_99(int) = Store : &:r0_96, r0_98 -# 68| r0_100(glval) = CopyValue : r0_96 -# 69| r0_101(glval) = VariableAddress[x] : -# 69| r0_102(int) = Load : &:r0_101, ~mu0_2 -# 69| r0_103(glval) = VariableAddress[z] : -# 69| r0_104(int) = Load : &:r0_103, ~mu0_2 -# 69| r0_105(int) = Sub : r0_104, r0_102 -# 69| mu0_106(int) = Store : &:r0_103, r0_105 -# 69| r0_107(glval) = CopyValue : r0_103 -# 70| r0_108(glval) = VariableAddress[x] : -# 70| r0_109(int) = Load : &:r0_108, ~mu0_2 -# 70| r0_110(glval) = VariableAddress[z] : -# 70| r0_111(int) = Load : &:r0_110, ~mu0_2 -# 70| r0_112(int) = Mul : r0_111, r0_109 -# 70| mu0_113(int) = Store : &:r0_110, r0_112 -# 70| r0_114(glval) = CopyValue : r0_110 -# 71| r0_115(glval) = VariableAddress[x] : -# 71| r0_116(int) = Load : &:r0_115, ~mu0_2 -# 71| r0_117(glval) = VariableAddress[z] : -# 71| r0_118(int) = Load : &:r0_117, ~mu0_2 -# 71| r0_119(int) = Div : r0_118, r0_116 -# 71| mu0_120(int) = Store : &:r0_117, r0_119 -# 71| r0_121(glval) = CopyValue : r0_117 -# 72| r0_122(glval) = VariableAddress[x] : -# 72| r0_123(int) = Load : &:r0_122, ~mu0_2 -# 72| r0_124(glval) = VariableAddress[z] : -# 72| r0_125(int) = Load : &:r0_124, ~mu0_2 -# 72| r0_126(int) = Rem : r0_125, r0_123 -# 72| mu0_127(int) = Store : &:r0_124, r0_126 -# 72| r0_128(glval) = CopyValue : r0_124 -# 74| r0_129(glval) = VariableAddress[x] : -# 74| r0_130(int) = Load : &:r0_129, ~mu0_2 -# 74| r0_131(glval) = VariableAddress[z] : -# 74| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 74| r0_133(int) = BitAnd : r0_132, r0_130 -# 74| mu0_134(int) = Store : &:r0_131, r0_133 -# 74| r0_135(glval) = CopyValue : r0_131 -# 75| r0_136(glval) = VariableAddress[x] : -# 75| r0_137(int) = Load : &:r0_136, ~mu0_2 -# 75| r0_138(glval) = VariableAddress[z] : -# 75| r0_139(int) = Load : &:r0_138, ~mu0_2 -# 75| r0_140(int) = BitOr : r0_139, r0_137 -# 75| mu0_141(int) = Store : &:r0_138, r0_140 -# 75| r0_142(glval) = CopyValue : r0_138 -# 76| r0_143(glval) = VariableAddress[x] : -# 76| r0_144(int) = Load : &:r0_143, ~mu0_2 -# 76| r0_145(glval) = VariableAddress[z] : -# 76| r0_146(int) = Load : &:r0_145, ~mu0_2 -# 76| r0_147(int) = BitXor : r0_146, r0_144 -# 76| mu0_148(int) = Store : &:r0_145, r0_147 -# 76| r0_149(glval) = CopyValue : r0_145 -# 78| r0_150(glval) = VariableAddress[x] : -# 78| r0_151(int) = Load : &:r0_150, ~mu0_2 -# 78| r0_152(glval) = VariableAddress[z] : -# 78| r0_153(int) = Load : &:r0_152, ~mu0_2 -# 78| r0_154(int) = ShiftLeft : r0_153, r0_151 -# 78| mu0_155(int) = Store : &:r0_152, r0_154 -# 78| r0_156(glval) = CopyValue : r0_152 -# 79| r0_157(glval) = VariableAddress[x] : -# 79| r0_158(int) = Load : &:r0_157, ~mu0_2 -# 79| r0_159(glval) = VariableAddress[z] : -# 79| r0_160(int) = Load : &:r0_159, ~mu0_2 -# 79| r0_161(int) = ShiftRight : r0_160, r0_158 -# 79| mu0_162(int) = Store : &:r0_159, r0_161 -# 79| r0_163(glval) = CopyValue : r0_159 -# 81| r0_164(glval) = VariableAddress[x] : -# 81| r0_165(int) = Load : &:r0_164, ~mu0_2 -# 81| r0_166(int) = CopyValue : r0_165 -# 81| r0_167(glval) = VariableAddress[z] : -# 81| mu0_168(int) = Store : &:r0_167, r0_166 -# 81| r0_169(glval) = CopyValue : r0_167 -# 82| r0_170(glval) = VariableAddress[x] : -# 82| r0_171(int) = Load : &:r0_170, ~mu0_2 -# 82| r0_172(int) = Negate : r0_171 -# 82| r0_173(glval) = VariableAddress[z] : -# 82| mu0_174(int) = Store : &:r0_173, r0_172 -# 82| r0_175(glval) = CopyValue : r0_173 -# 83| r0_176(glval) = VariableAddress[x] : -# 83| r0_177(int) = Load : &:r0_176, ~mu0_2 -# 83| r0_178(int) = BitComplement : r0_177 -# 83| r0_179(glval) = VariableAddress[z] : -# 83| mu0_180(int) = Store : &:r0_179, r0_178 -# 83| r0_181(glval) = CopyValue : r0_179 -# 84| r0_182(glval) = VariableAddress[x] : -# 84| r0_183(int) = Load : &:r0_182, ~mu0_2 -# 84| r0_184(int) = Constant[0] : -# 84| r0_185(bool) = CompareNE : r0_183, r0_184 -# 84| r0_186(bool) = LogicalNot : r0_185 -# 84| r0_187(int) = Convert : r0_186 -# 84| r0_188(glval) = VariableAddress[z] : -# 84| mu0_189(int) = Store : &:r0_188, r0_187 -# 84| r0_190(glval) = CopyValue : r0_188 -# 85| v0_191(void) = NoOp : -# 50| v0_192(void) = ReturnVoid : -# 50| v0_193(void) = UnmodeledUse : mu* -# 50| v0_194(void) = ExitFunction : +# 55| r0_27(int) = Mul : r0_24, r0_26 +# 55| r0_28(glval) = VariableAddress[z] : +# 55| mu0_29(int) = Store : &:r0_28, r0_27 +# 56| r0_30(glval) = VariableAddress[x] : +# 56| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 56| r0_32(glval) = VariableAddress[y] : +# 56| r0_33(int) = Load : &:r0_32, ~mu0_2 +# 56| r0_34(int) = Div : r0_31, r0_33 +# 56| r0_35(glval) = VariableAddress[z] : +# 56| mu0_36(int) = Store : &:r0_35, r0_34 +# 57| r0_37(glval) = VariableAddress[x] : +# 57| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 57| r0_39(glval) = VariableAddress[y] : +# 57| r0_40(int) = Load : &:r0_39, ~mu0_2 +# 57| r0_41(int) = Rem : r0_38, r0_40 +# 57| r0_42(glval) = VariableAddress[z] : +# 57| mu0_43(int) = Store : &:r0_42, r0_41 +# 59| r0_44(glval) = VariableAddress[x] : +# 59| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 59| r0_46(glval) = VariableAddress[y] : +# 59| r0_47(int) = Load : &:r0_46, ~mu0_2 +# 59| r0_48(int) = BitAnd : r0_45, r0_47 +# 59| r0_49(glval) = VariableAddress[z] : +# 59| mu0_50(int) = Store : &:r0_49, r0_48 +# 60| r0_51(glval) = VariableAddress[x] : +# 60| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 60| r0_53(glval) = VariableAddress[y] : +# 60| r0_54(int) = Load : &:r0_53, ~mu0_2 +# 60| r0_55(int) = BitOr : r0_52, r0_54 +# 60| r0_56(glval) = VariableAddress[z] : +# 60| mu0_57(int) = Store : &:r0_56, r0_55 +# 61| r0_58(glval) = VariableAddress[x] : +# 61| r0_59(int) = Load : &:r0_58, ~mu0_2 +# 61| r0_60(glval) = VariableAddress[y] : +# 61| r0_61(int) = Load : &:r0_60, ~mu0_2 +# 61| r0_62(int) = BitXor : r0_59, r0_61 +# 61| r0_63(glval) = VariableAddress[z] : +# 61| mu0_64(int) = Store : &:r0_63, r0_62 +# 63| r0_65(glval) = VariableAddress[x] : +# 63| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 63| r0_67(glval) = VariableAddress[y] : +# 63| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 63| r0_69(int) = ShiftLeft : r0_66, r0_68 +# 63| r0_70(glval) = VariableAddress[z] : +# 63| mu0_71(int) = Store : &:r0_70, r0_69 +# 64| r0_72(glval) = VariableAddress[x] : +# 64| r0_73(int) = Load : &:r0_72, ~mu0_2 +# 64| r0_74(glval) = VariableAddress[y] : +# 64| r0_75(int) = Load : &:r0_74, ~mu0_2 +# 64| r0_76(int) = ShiftRight : r0_73, r0_75 +# 64| r0_77(glval) = VariableAddress[z] : +# 64| mu0_78(int) = Store : &:r0_77, r0_76 +# 66| r0_79(glval) = VariableAddress[x] : +# 66| r0_80(int) = Load : &:r0_79, ~mu0_2 +# 66| r0_81(glval) = VariableAddress[z] : +# 66| mu0_82(int) = Store : &:r0_81, r0_80 +# 68| r0_83(glval) = VariableAddress[x] : +# 68| r0_84(int) = Load : &:r0_83, ~mu0_2 +# 68| r0_85(glval) = VariableAddress[z] : +# 68| r0_86(int) = Load : &:r0_85, ~mu0_2 +# 68| r0_87(int) = Add : r0_86, r0_84 +# 68| mu0_88(int) = Store : &:r0_85, r0_87 +# 69| r0_89(glval) = VariableAddress[x] : +# 69| r0_90(int) = Load : &:r0_89, ~mu0_2 +# 69| r0_91(glval) = VariableAddress[z] : +# 69| r0_92(int) = Load : &:r0_91, ~mu0_2 +# 69| r0_93(int) = Sub : r0_92, r0_90 +# 69| mu0_94(int) = Store : &:r0_91, r0_93 +# 70| r0_95(glval) = VariableAddress[x] : +# 70| r0_96(int) = Load : &:r0_95, ~mu0_2 +# 70| r0_97(glval) = VariableAddress[z] : +# 70| r0_98(int) = Load : &:r0_97, ~mu0_2 +# 70| r0_99(int) = Mul : r0_98, r0_96 +# 70| mu0_100(int) = Store : &:r0_97, r0_99 +# 71| r0_101(glval) = VariableAddress[x] : +# 71| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 71| r0_103(glval) = VariableAddress[z] : +# 71| r0_104(int) = Load : &:r0_103, ~mu0_2 +# 71| r0_105(int) = Div : r0_104, r0_102 +# 71| mu0_106(int) = Store : &:r0_103, r0_105 +# 72| r0_107(glval) = VariableAddress[x] : +# 72| r0_108(int) = Load : &:r0_107, ~mu0_2 +# 72| r0_109(glval) = VariableAddress[z] : +# 72| r0_110(int) = Load : &:r0_109, ~mu0_2 +# 72| r0_111(int) = Rem : r0_110, r0_108 +# 72| mu0_112(int) = Store : &:r0_109, r0_111 +# 74| r0_113(glval) = VariableAddress[x] : +# 74| r0_114(int) = Load : &:r0_113, ~mu0_2 +# 74| r0_115(glval) = VariableAddress[z] : +# 74| r0_116(int) = Load : &:r0_115, ~mu0_2 +# 74| r0_117(int) = BitAnd : r0_116, r0_114 +# 74| mu0_118(int) = Store : &:r0_115, r0_117 +# 75| r0_119(glval) = VariableAddress[x] : +# 75| r0_120(int) = Load : &:r0_119, ~mu0_2 +# 75| r0_121(glval) = VariableAddress[z] : +# 75| r0_122(int) = Load : &:r0_121, ~mu0_2 +# 75| r0_123(int) = BitOr : r0_122, r0_120 +# 75| mu0_124(int) = Store : &:r0_121, r0_123 +# 76| r0_125(glval) = VariableAddress[x] : +# 76| r0_126(int) = Load : &:r0_125, ~mu0_2 +# 76| r0_127(glval) = VariableAddress[z] : +# 76| r0_128(int) = Load : &:r0_127, ~mu0_2 +# 76| r0_129(int) = BitXor : r0_128, r0_126 +# 76| mu0_130(int) = Store : &:r0_127, r0_129 +# 78| r0_131(glval) = VariableAddress[x] : +# 78| r0_132(int) = Load : &:r0_131, ~mu0_2 +# 78| r0_133(glval) = VariableAddress[z] : +# 78| r0_134(int) = Load : &:r0_133, ~mu0_2 +# 78| r0_135(int) = ShiftLeft : r0_134, r0_132 +# 78| mu0_136(int) = Store : &:r0_133, r0_135 +# 79| r0_137(glval) = VariableAddress[x] : +# 79| r0_138(int) = Load : &:r0_137, ~mu0_2 +# 79| r0_139(glval) = VariableAddress[z] : +# 79| r0_140(int) = Load : &:r0_139, ~mu0_2 +# 79| r0_141(int) = ShiftRight : r0_140, r0_138 +# 79| mu0_142(int) = Store : &:r0_139, r0_141 +# 81| r0_143(glval) = VariableAddress[x] : +# 81| r0_144(int) = Load : &:r0_143, ~mu0_2 +# 81| r0_145(int) = CopyValue : r0_144 +# 81| r0_146(glval) = VariableAddress[z] : +# 81| mu0_147(int) = Store : &:r0_146, r0_145 +# 82| r0_148(glval) = VariableAddress[x] : +# 82| r0_149(int) = Load : &:r0_148, ~mu0_2 +# 82| r0_150(int) = Negate : r0_149 +# 82| r0_151(glval) = VariableAddress[z] : +# 82| mu0_152(int) = Store : &:r0_151, r0_150 +# 83| r0_153(glval) = VariableAddress[x] : +# 83| r0_154(int) = Load : &:r0_153, ~mu0_2 +# 83| r0_155(int) = BitComplement : r0_154 +# 83| r0_156(glval) = VariableAddress[z] : +# 83| mu0_157(int) = Store : &:r0_156, r0_155 +# 84| r0_158(glval) = VariableAddress[x] : +# 84| r0_159(int) = Load : &:r0_158, ~mu0_2 +# 84| r0_160(int) = Constant[0] : +# 84| r0_161(bool) = CompareNE : r0_159, r0_160 +# 84| r0_162(bool) = LogicalNot : r0_161 +# 84| r0_163(int) = Convert : r0_162 +# 84| r0_164(glval) = VariableAddress[z] : +# 84| mu0_165(int) = Store : &:r0_164, r0_163 +# 85| v0_166(void) = NoOp : +# 50| v0_167(void) = ReturnVoid : +# 50| v0_168(void) = UnmodeledUse : mu* +# 50| v0_169(void) = ExitFunction : # 87| void IntegerCompare(int, int) # 87| Block 0 @@ -433,51 +405,45 @@ ir.cpp: # 90| r0_13(bool) = CompareEQ : r0_10, r0_12 # 90| r0_14(glval) = VariableAddress[b] : # 90| mu0_15(bool) = Store : &:r0_14, r0_13 -# 90| r0_16(glval) = CopyValue : r0_14 -# 91| r0_17(glval) = VariableAddress[x] : -# 91| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 91| r0_19(glval) = VariableAddress[y] : -# 91| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 91| r0_21(bool) = CompareNE : r0_18, r0_20 -# 91| r0_22(glval) = VariableAddress[b] : -# 91| mu0_23(bool) = Store : &:r0_22, r0_21 -# 91| r0_24(glval) = CopyValue : r0_22 -# 92| r0_25(glval) = VariableAddress[x] : +# 91| r0_16(glval) = VariableAddress[x] : +# 91| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 91| r0_18(glval) = VariableAddress[y] : +# 91| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 91| r0_20(bool) = CompareNE : r0_17, r0_19 +# 91| r0_21(glval) = VariableAddress[b] : +# 91| mu0_22(bool) = Store : &:r0_21, r0_20 +# 92| r0_23(glval) = VariableAddress[x] : +# 92| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 92| r0_25(glval) = VariableAddress[y] : # 92| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 92| r0_27(glval) = VariableAddress[y] : -# 92| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 92| r0_29(bool) = CompareLT : r0_26, r0_28 -# 92| r0_30(glval) = VariableAddress[b] : -# 92| mu0_31(bool) = Store : &:r0_30, r0_29 -# 92| r0_32(glval) = CopyValue : r0_30 -# 93| r0_33(glval) = VariableAddress[x] : -# 93| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 93| r0_35(glval) = VariableAddress[y] : -# 93| r0_36(int) = Load : &:r0_35, ~mu0_2 -# 93| r0_37(bool) = CompareGT : r0_34, r0_36 -# 93| r0_38(glval) = VariableAddress[b] : -# 93| mu0_39(bool) = Store : &:r0_38, r0_37 -# 93| r0_40(glval) = CopyValue : r0_38 -# 94| r0_41(glval) = VariableAddress[x] : -# 94| r0_42(int) = Load : &:r0_41, ~mu0_2 -# 94| r0_43(glval) = VariableAddress[y] : -# 94| r0_44(int) = Load : &:r0_43, ~mu0_2 -# 94| r0_45(bool) = CompareLE : r0_42, r0_44 -# 94| r0_46(glval) = VariableAddress[b] : -# 94| mu0_47(bool) = Store : &:r0_46, r0_45 -# 94| r0_48(glval) = CopyValue : r0_46 -# 95| r0_49(glval) = VariableAddress[x] : -# 95| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 95| r0_51(glval) = VariableAddress[y] : -# 95| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 95| r0_53(bool) = CompareGE : r0_50, r0_52 -# 95| r0_54(glval) = VariableAddress[b] : -# 95| mu0_55(bool) = Store : &:r0_54, r0_53 -# 95| r0_56(glval) = CopyValue : r0_54 -# 96| v0_57(void) = NoOp : -# 87| v0_58(void) = ReturnVoid : -# 87| v0_59(void) = UnmodeledUse : mu* -# 87| v0_60(void) = ExitFunction : +# 92| r0_27(bool) = CompareLT : r0_24, r0_26 +# 92| r0_28(glval) = VariableAddress[b] : +# 92| mu0_29(bool) = Store : &:r0_28, r0_27 +# 93| r0_30(glval) = VariableAddress[x] : +# 93| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 93| r0_32(glval) = VariableAddress[y] : +# 93| r0_33(int) = Load : &:r0_32, ~mu0_2 +# 93| r0_34(bool) = CompareGT : r0_31, r0_33 +# 93| r0_35(glval) = VariableAddress[b] : +# 93| mu0_36(bool) = Store : &:r0_35, r0_34 +# 94| r0_37(glval) = VariableAddress[x] : +# 94| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 94| r0_39(glval) = VariableAddress[y] : +# 94| r0_40(int) = Load : &:r0_39, ~mu0_2 +# 94| r0_41(bool) = CompareLE : r0_38, r0_40 +# 94| r0_42(glval) = VariableAddress[b] : +# 94| mu0_43(bool) = Store : &:r0_42, r0_41 +# 95| r0_44(glval) = VariableAddress[x] : +# 95| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 95| r0_46(glval) = VariableAddress[y] : +# 95| r0_47(int) = Load : &:r0_46, ~mu0_2 +# 95| r0_48(bool) = CompareGE : r0_45, r0_47 +# 95| r0_49(glval) = VariableAddress[b] : +# 95| mu0_50(bool) = Store : &:r0_49, r0_48 +# 96| v0_51(void) = NoOp : +# 87| v0_52(void) = ReturnVoid : +# 87| v0_53(void) = UnmodeledUse : mu* +# 87| v0_54(void) = ExitFunction : # 98| void IntegerCrement(int) # 98| Block 0 @@ -495,35 +461,31 @@ ir.cpp: # 101| mu0_11(int) = Store : &:r0_7, r0_10 # 101| r0_12(glval) = VariableAddress[y] : # 101| mu0_13(int) = Store : &:r0_12, r0_10 -# 101| r0_14(glval) = CopyValue : r0_12 -# 102| r0_15(glval) = VariableAddress[x] : -# 102| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 102| r0_17(int) = Constant[1] : -# 102| r0_18(int) = Sub : r0_16, r0_17 -# 102| mu0_19(int) = Store : &:r0_15, r0_18 -# 102| r0_20(glval) = VariableAddress[y] : -# 102| mu0_21(int) = Store : &:r0_20, r0_18 -# 102| r0_22(glval) = CopyValue : r0_20 -# 103| r0_23(glval) = VariableAddress[x] : -# 103| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 103| r0_25(int) = Constant[1] : -# 103| r0_26(int) = Add : r0_24, r0_25 -# 103| mu0_27(int) = Store : &:r0_23, r0_26 -# 103| r0_28(glval) = VariableAddress[y] : -# 103| mu0_29(int) = Store : &:r0_28, r0_24 -# 103| r0_30(glval) = CopyValue : r0_28 -# 104| r0_31(glval) = VariableAddress[x] : -# 104| r0_32(int) = Load : &:r0_31, ~mu0_2 -# 104| r0_33(int) = Constant[1] : -# 104| r0_34(int) = Sub : r0_32, r0_33 -# 104| mu0_35(int) = Store : &:r0_31, r0_34 -# 104| r0_36(glval) = VariableAddress[y] : -# 104| mu0_37(int) = Store : &:r0_36, r0_32 -# 104| r0_38(glval) = CopyValue : r0_36 -# 105| v0_39(void) = NoOp : -# 98| v0_40(void) = ReturnVoid : -# 98| v0_41(void) = UnmodeledUse : mu* -# 98| v0_42(void) = ExitFunction : +# 102| r0_14(glval) = VariableAddress[x] : +# 102| r0_15(int) = Load : &:r0_14, ~mu0_2 +# 102| r0_16(int) = Constant[1] : +# 102| r0_17(int) = Sub : r0_15, r0_16 +# 102| mu0_18(int) = Store : &:r0_14, r0_17 +# 102| r0_19(glval) = VariableAddress[y] : +# 102| mu0_20(int) = Store : &:r0_19, r0_17 +# 103| r0_21(glval) = VariableAddress[x] : +# 103| r0_22(int) = Load : &:r0_21, ~mu0_2 +# 103| r0_23(int) = Constant[1] : +# 103| r0_24(int) = Add : r0_22, r0_23 +# 103| mu0_25(int) = Store : &:r0_21, r0_24 +# 103| r0_26(glval) = VariableAddress[y] : +# 103| mu0_27(int) = Store : &:r0_26, r0_22 +# 104| r0_28(glval) = VariableAddress[x] : +# 104| r0_29(int) = Load : &:r0_28, ~mu0_2 +# 104| r0_30(int) = Constant[1] : +# 104| r0_31(int) = Sub : r0_29, r0_30 +# 104| mu0_32(int) = Store : &:r0_28, r0_31 +# 104| r0_33(glval) = VariableAddress[y] : +# 104| mu0_34(int) = Store : &:r0_33, r0_29 +# 105| v0_35(void) = NoOp : +# 98| v0_36(void) = ReturnVoid : +# 98| v0_37(void) = UnmodeledUse : mu* +# 98| v0_38(void) = ExitFunction : # 107| void IntegerCrement_LValue(int) # 107| Block 0 @@ -543,21 +505,19 @@ ir.cpp: # 110| r0_13(int *) = CopyValue : r0_12 # 110| r0_14(glval) = VariableAddress[p] : # 110| mu0_15(int *) = Store : &:r0_14, r0_13 -# 110| r0_16(glval) = CopyValue : r0_14 -# 111| r0_17(glval) = VariableAddress[x] : -# 111| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 111| r0_19(int) = Constant[1] : -# 111| r0_20(int) = Sub : r0_18, r0_19 -# 111| mu0_21(int) = Store : &:r0_17, r0_20 -# 111| r0_22(glval) = CopyValue : r0_17 -# 111| r0_23(int *) = CopyValue : r0_22 -# 111| r0_24(glval) = VariableAddress[p] : -# 111| mu0_25(int *) = Store : &:r0_24, r0_23 -# 111| r0_26(glval) = CopyValue : r0_24 -# 112| v0_27(void) = NoOp : -# 107| v0_28(void) = ReturnVoid : -# 107| v0_29(void) = UnmodeledUse : mu* -# 107| v0_30(void) = ExitFunction : +# 111| r0_16(glval) = VariableAddress[x] : +# 111| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 111| r0_18(int) = Constant[1] : +# 111| r0_19(int) = Sub : r0_17, r0_18 +# 111| mu0_20(int) = Store : &:r0_16, r0_19 +# 111| r0_21(glval) = CopyValue : r0_16 +# 111| r0_22(int *) = CopyValue : r0_21 +# 111| r0_23(glval) = VariableAddress[p] : +# 111| mu0_24(int *) = Store : &:r0_23, r0_22 +# 112| v0_25(void) = NoOp : +# 107| v0_26(void) = ReturnVoid : +# 107| v0_27(void) = UnmodeledUse : mu* +# 107| v0_28(void) = ExitFunction : # 114| void FloatOps(double, double) # 114| Block 0 @@ -577,80 +537,69 @@ ir.cpp: # 117| r0_13(double) = Add : r0_10, r0_12 # 117| r0_14(glval) = VariableAddress[z] : # 117| mu0_15(double) = Store : &:r0_14, r0_13 -# 117| r0_16(glval) = CopyValue : r0_14 -# 118| r0_17(glval) = VariableAddress[x] : -# 118| r0_18(double) = Load : &:r0_17, ~mu0_2 -# 118| r0_19(glval) = VariableAddress[y] : -# 118| r0_20(double) = Load : &:r0_19, ~mu0_2 -# 118| r0_21(double) = Sub : r0_18, r0_20 -# 118| r0_22(glval) = VariableAddress[z] : -# 118| mu0_23(double) = Store : &:r0_22, r0_21 -# 118| r0_24(glval) = CopyValue : r0_22 -# 119| r0_25(glval) = VariableAddress[x] : +# 118| r0_16(glval) = VariableAddress[x] : +# 118| r0_17(double) = Load : &:r0_16, ~mu0_2 +# 118| r0_18(glval) = VariableAddress[y] : +# 118| r0_19(double) = Load : &:r0_18, ~mu0_2 +# 118| r0_20(double) = Sub : r0_17, r0_19 +# 118| r0_21(glval) = VariableAddress[z] : +# 118| mu0_22(double) = Store : &:r0_21, r0_20 +# 119| r0_23(glval) = VariableAddress[x] : +# 119| r0_24(double) = Load : &:r0_23, ~mu0_2 +# 119| r0_25(glval) = VariableAddress[y] : # 119| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 119| r0_27(glval) = VariableAddress[y] : -# 119| r0_28(double) = Load : &:r0_27, ~mu0_2 -# 119| r0_29(double) = Mul : r0_26, r0_28 -# 119| r0_30(glval) = VariableAddress[z] : -# 119| mu0_31(double) = Store : &:r0_30, r0_29 -# 119| r0_32(glval) = CopyValue : r0_30 -# 120| r0_33(glval) = VariableAddress[x] : -# 120| r0_34(double) = Load : &:r0_33, ~mu0_2 -# 120| r0_35(glval) = VariableAddress[y] : -# 120| r0_36(double) = Load : &:r0_35, ~mu0_2 -# 120| r0_37(double) = Div : r0_34, r0_36 -# 120| r0_38(glval) = VariableAddress[z] : -# 120| mu0_39(double) = Store : &:r0_38, r0_37 -# 120| r0_40(glval) = CopyValue : r0_38 -# 122| r0_41(glval) = VariableAddress[x] : -# 122| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 122| r0_43(glval) = VariableAddress[z] : -# 122| mu0_44(double) = Store : &:r0_43, r0_42 -# 122| r0_45(glval) = CopyValue : r0_43 -# 124| r0_46(glval) = VariableAddress[x] : -# 124| r0_47(double) = Load : &:r0_46, ~mu0_2 -# 124| r0_48(glval) = VariableAddress[z] : -# 124| r0_49(double) = Load : &:r0_48, ~mu0_2 -# 124| r0_50(double) = Add : r0_49, r0_47 -# 124| mu0_51(double) = Store : &:r0_48, r0_50 -# 124| r0_52(glval) = CopyValue : r0_48 -# 125| r0_53(glval) = VariableAddress[x] : -# 125| r0_54(double) = Load : &:r0_53, ~mu0_2 -# 125| r0_55(glval) = VariableAddress[z] : -# 125| r0_56(double) = Load : &:r0_55, ~mu0_2 -# 125| r0_57(double) = Sub : r0_56, r0_54 -# 125| mu0_58(double) = Store : &:r0_55, r0_57 -# 125| r0_59(glval) = CopyValue : r0_55 -# 126| r0_60(glval) = VariableAddress[x] : -# 126| r0_61(double) = Load : &:r0_60, ~mu0_2 -# 126| r0_62(glval) = VariableAddress[z] : -# 126| r0_63(double) = Load : &:r0_62, ~mu0_2 -# 126| r0_64(double) = Mul : r0_63, r0_61 -# 126| mu0_65(double) = Store : &:r0_62, r0_64 -# 126| r0_66(glval) = CopyValue : r0_62 -# 127| r0_67(glval) = VariableAddress[x] : -# 127| r0_68(double) = Load : &:r0_67, ~mu0_2 -# 127| r0_69(glval) = VariableAddress[z] : -# 127| r0_70(double) = Load : &:r0_69, ~mu0_2 -# 127| r0_71(double) = Div : r0_70, r0_68 -# 127| mu0_72(double) = Store : &:r0_69, r0_71 -# 127| r0_73(glval) = CopyValue : r0_69 -# 129| r0_74(glval) = VariableAddress[x] : -# 129| r0_75(double) = Load : &:r0_74, ~mu0_2 -# 129| r0_76(double) = CopyValue : r0_75 -# 129| r0_77(glval) = VariableAddress[z] : -# 129| mu0_78(double) = Store : &:r0_77, r0_76 -# 129| r0_79(glval) = CopyValue : r0_77 -# 130| r0_80(glval) = VariableAddress[x] : -# 130| r0_81(double) = Load : &:r0_80, ~mu0_2 -# 130| r0_82(double) = Negate : r0_81 -# 130| r0_83(glval) = VariableAddress[z] : -# 130| mu0_84(double) = Store : &:r0_83, r0_82 -# 130| r0_85(glval) = CopyValue : r0_83 -# 131| v0_86(void) = NoOp : -# 114| v0_87(void) = ReturnVoid : -# 114| v0_88(void) = UnmodeledUse : mu* -# 114| v0_89(void) = ExitFunction : +# 119| r0_27(double) = Mul : r0_24, r0_26 +# 119| r0_28(glval) = VariableAddress[z] : +# 119| mu0_29(double) = Store : &:r0_28, r0_27 +# 120| r0_30(glval) = VariableAddress[x] : +# 120| r0_31(double) = Load : &:r0_30, ~mu0_2 +# 120| r0_32(glval) = VariableAddress[y] : +# 120| r0_33(double) = Load : &:r0_32, ~mu0_2 +# 120| r0_34(double) = Div : r0_31, r0_33 +# 120| r0_35(glval) = VariableAddress[z] : +# 120| mu0_36(double) = Store : &:r0_35, r0_34 +# 122| r0_37(glval) = VariableAddress[x] : +# 122| r0_38(double) = Load : &:r0_37, ~mu0_2 +# 122| r0_39(glval) = VariableAddress[z] : +# 122| mu0_40(double) = Store : &:r0_39, r0_38 +# 124| r0_41(glval) = VariableAddress[x] : +# 124| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 124| r0_43(glval) = VariableAddress[z] : +# 124| r0_44(double) = Load : &:r0_43, ~mu0_2 +# 124| r0_45(double) = Add : r0_44, r0_42 +# 124| mu0_46(double) = Store : &:r0_43, r0_45 +# 125| r0_47(glval) = VariableAddress[x] : +# 125| r0_48(double) = Load : &:r0_47, ~mu0_2 +# 125| r0_49(glval) = VariableAddress[z] : +# 125| r0_50(double) = Load : &:r0_49, ~mu0_2 +# 125| r0_51(double) = Sub : r0_50, r0_48 +# 125| mu0_52(double) = Store : &:r0_49, r0_51 +# 126| r0_53(glval) = VariableAddress[x] : +# 126| r0_54(double) = Load : &:r0_53, ~mu0_2 +# 126| r0_55(glval) = VariableAddress[z] : +# 126| r0_56(double) = Load : &:r0_55, ~mu0_2 +# 126| r0_57(double) = Mul : r0_56, r0_54 +# 126| mu0_58(double) = Store : &:r0_55, r0_57 +# 127| r0_59(glval) = VariableAddress[x] : +# 127| r0_60(double) = Load : &:r0_59, ~mu0_2 +# 127| r0_61(glval) = VariableAddress[z] : +# 127| r0_62(double) = Load : &:r0_61, ~mu0_2 +# 127| r0_63(double) = Div : r0_62, r0_60 +# 127| mu0_64(double) = Store : &:r0_61, r0_63 +# 129| r0_65(glval) = VariableAddress[x] : +# 129| r0_66(double) = Load : &:r0_65, ~mu0_2 +# 129| r0_67(double) = CopyValue : r0_66 +# 129| r0_68(glval) = VariableAddress[z] : +# 129| mu0_69(double) = Store : &:r0_68, r0_67 +# 130| r0_70(glval) = VariableAddress[x] : +# 130| r0_71(double) = Load : &:r0_70, ~mu0_2 +# 130| r0_72(double) = Negate : r0_71 +# 130| r0_73(glval) = VariableAddress[z] : +# 130| mu0_74(double) = Store : &:r0_73, r0_72 +# 131| v0_75(void) = NoOp : +# 114| v0_76(void) = ReturnVoid : +# 114| v0_77(void) = UnmodeledUse : mu* +# 114| v0_78(void) = ExitFunction : # 133| void FloatCompare(double, double) # 133| Block 0 @@ -670,51 +619,45 @@ ir.cpp: # 136| r0_13(bool) = CompareEQ : r0_10, r0_12 # 136| r0_14(glval) = VariableAddress[b] : # 136| mu0_15(bool) = Store : &:r0_14, r0_13 -# 136| r0_16(glval) = CopyValue : r0_14 -# 137| r0_17(glval) = VariableAddress[x] : -# 137| r0_18(double) = Load : &:r0_17, ~mu0_2 -# 137| r0_19(glval) = VariableAddress[y] : -# 137| r0_20(double) = Load : &:r0_19, ~mu0_2 -# 137| r0_21(bool) = CompareNE : r0_18, r0_20 -# 137| r0_22(glval) = VariableAddress[b] : -# 137| mu0_23(bool) = Store : &:r0_22, r0_21 -# 137| r0_24(glval) = CopyValue : r0_22 -# 138| r0_25(glval) = VariableAddress[x] : +# 137| r0_16(glval) = VariableAddress[x] : +# 137| r0_17(double) = Load : &:r0_16, ~mu0_2 +# 137| r0_18(glval) = VariableAddress[y] : +# 137| r0_19(double) = Load : &:r0_18, ~mu0_2 +# 137| r0_20(bool) = CompareNE : r0_17, r0_19 +# 137| r0_21(glval) = VariableAddress[b] : +# 137| mu0_22(bool) = Store : &:r0_21, r0_20 +# 138| r0_23(glval) = VariableAddress[x] : +# 138| r0_24(double) = Load : &:r0_23, ~mu0_2 +# 138| r0_25(glval) = VariableAddress[y] : # 138| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 138| r0_27(glval) = VariableAddress[y] : -# 138| r0_28(double) = Load : &:r0_27, ~mu0_2 -# 138| r0_29(bool) = CompareLT : r0_26, r0_28 -# 138| r0_30(glval) = VariableAddress[b] : -# 138| mu0_31(bool) = Store : &:r0_30, r0_29 -# 138| r0_32(glval) = CopyValue : r0_30 -# 139| r0_33(glval) = VariableAddress[x] : -# 139| r0_34(double) = Load : &:r0_33, ~mu0_2 -# 139| r0_35(glval) = VariableAddress[y] : -# 139| r0_36(double) = Load : &:r0_35, ~mu0_2 -# 139| r0_37(bool) = CompareGT : r0_34, r0_36 -# 139| r0_38(glval) = VariableAddress[b] : -# 139| mu0_39(bool) = Store : &:r0_38, r0_37 -# 139| r0_40(glval) = CopyValue : r0_38 -# 140| r0_41(glval) = VariableAddress[x] : -# 140| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 140| r0_43(glval) = VariableAddress[y] : -# 140| r0_44(double) = Load : &:r0_43, ~mu0_2 -# 140| r0_45(bool) = CompareLE : r0_42, r0_44 -# 140| r0_46(glval) = VariableAddress[b] : -# 140| mu0_47(bool) = Store : &:r0_46, r0_45 -# 140| r0_48(glval) = CopyValue : r0_46 -# 141| r0_49(glval) = VariableAddress[x] : -# 141| r0_50(double) = Load : &:r0_49, ~mu0_2 -# 141| r0_51(glval) = VariableAddress[y] : -# 141| r0_52(double) = Load : &:r0_51, ~mu0_2 -# 141| r0_53(bool) = CompareGE : r0_50, r0_52 -# 141| r0_54(glval) = VariableAddress[b] : -# 141| mu0_55(bool) = Store : &:r0_54, r0_53 -# 141| r0_56(glval) = CopyValue : r0_54 -# 142| v0_57(void) = NoOp : -# 133| v0_58(void) = ReturnVoid : -# 133| v0_59(void) = UnmodeledUse : mu* -# 133| v0_60(void) = ExitFunction : +# 138| r0_27(bool) = CompareLT : r0_24, r0_26 +# 138| r0_28(glval) = VariableAddress[b] : +# 138| mu0_29(bool) = Store : &:r0_28, r0_27 +# 139| r0_30(glval) = VariableAddress[x] : +# 139| r0_31(double) = Load : &:r0_30, ~mu0_2 +# 139| r0_32(glval) = VariableAddress[y] : +# 139| r0_33(double) = Load : &:r0_32, ~mu0_2 +# 139| r0_34(bool) = CompareGT : r0_31, r0_33 +# 139| r0_35(glval) = VariableAddress[b] : +# 139| mu0_36(bool) = Store : &:r0_35, r0_34 +# 140| r0_37(glval) = VariableAddress[x] : +# 140| r0_38(double) = Load : &:r0_37, ~mu0_2 +# 140| r0_39(glval) = VariableAddress[y] : +# 140| r0_40(double) = Load : &:r0_39, ~mu0_2 +# 140| r0_41(bool) = CompareLE : r0_38, r0_40 +# 140| r0_42(glval) = VariableAddress[b] : +# 140| mu0_43(bool) = Store : &:r0_42, r0_41 +# 141| r0_44(glval) = VariableAddress[x] : +# 141| r0_45(double) = Load : &:r0_44, ~mu0_2 +# 141| r0_46(glval) = VariableAddress[y] : +# 141| r0_47(double) = Load : &:r0_46, ~mu0_2 +# 141| r0_48(bool) = CompareGE : r0_45, r0_47 +# 141| r0_49(glval) = VariableAddress[b] : +# 141| mu0_50(bool) = Store : &:r0_49, r0_48 +# 142| v0_51(void) = NoOp : +# 133| v0_52(void) = ReturnVoid : +# 133| v0_53(void) = UnmodeledUse : mu* +# 133| v0_54(void) = ExitFunction : # 144| void FloatCrement(float) # 144| Block 0 @@ -732,35 +675,31 @@ ir.cpp: # 147| mu0_11(float) = Store : &:r0_7, r0_10 # 147| r0_12(glval) = VariableAddress[y] : # 147| mu0_13(float) = Store : &:r0_12, r0_10 -# 147| r0_14(glval) = CopyValue : r0_12 -# 148| r0_15(glval) = VariableAddress[x] : -# 148| r0_16(float) = Load : &:r0_15, ~mu0_2 -# 148| r0_17(float) = Constant[1.0] : -# 148| r0_18(float) = Sub : r0_16, r0_17 -# 148| mu0_19(float) = Store : &:r0_15, r0_18 -# 148| r0_20(glval) = VariableAddress[y] : -# 148| mu0_21(float) = Store : &:r0_20, r0_18 -# 148| r0_22(glval) = CopyValue : r0_20 -# 149| r0_23(glval) = VariableAddress[x] : -# 149| r0_24(float) = Load : &:r0_23, ~mu0_2 -# 149| r0_25(float) = Constant[1.0] : -# 149| r0_26(float) = Add : r0_24, r0_25 -# 149| mu0_27(float) = Store : &:r0_23, r0_26 -# 149| r0_28(glval) = VariableAddress[y] : -# 149| mu0_29(float) = Store : &:r0_28, r0_24 -# 149| r0_30(glval) = CopyValue : r0_28 -# 150| r0_31(glval) = VariableAddress[x] : -# 150| r0_32(float) = Load : &:r0_31, ~mu0_2 -# 150| r0_33(float) = Constant[1.0] : -# 150| r0_34(float) = Sub : r0_32, r0_33 -# 150| mu0_35(float) = Store : &:r0_31, r0_34 -# 150| r0_36(glval) = VariableAddress[y] : -# 150| mu0_37(float) = Store : &:r0_36, r0_32 -# 150| r0_38(glval) = CopyValue : r0_36 -# 151| v0_39(void) = NoOp : -# 144| v0_40(void) = ReturnVoid : -# 144| v0_41(void) = UnmodeledUse : mu* -# 144| v0_42(void) = ExitFunction : +# 148| r0_14(glval) = VariableAddress[x] : +# 148| r0_15(float) = Load : &:r0_14, ~mu0_2 +# 148| r0_16(float) = Constant[1.0] : +# 148| r0_17(float) = Sub : r0_15, r0_16 +# 148| mu0_18(float) = Store : &:r0_14, r0_17 +# 148| r0_19(glval) = VariableAddress[y] : +# 148| mu0_20(float) = Store : &:r0_19, r0_17 +# 149| r0_21(glval) = VariableAddress[x] : +# 149| r0_22(float) = Load : &:r0_21, ~mu0_2 +# 149| r0_23(float) = Constant[1.0] : +# 149| r0_24(float) = Add : r0_22, r0_23 +# 149| mu0_25(float) = Store : &:r0_21, r0_24 +# 149| r0_26(glval) = VariableAddress[y] : +# 149| mu0_27(float) = Store : &:r0_26, r0_22 +# 150| r0_28(glval) = VariableAddress[x] : +# 150| r0_29(float) = Load : &:r0_28, ~mu0_2 +# 150| r0_30(float) = Constant[1.0] : +# 150| r0_31(float) = Sub : r0_29, r0_30 +# 150| mu0_32(float) = Store : &:r0_28, r0_31 +# 150| r0_33(glval) = VariableAddress[y] : +# 150| mu0_34(float) = Store : &:r0_33, r0_29 +# 151| v0_35(void) = NoOp : +# 144| v0_36(void) = ReturnVoid : +# 144| v0_37(void) = UnmodeledUse : mu* +# 144| v0_38(void) = ExitFunction : # 153| void PointerOps(int*, int) # 153| Block 0 @@ -782,70 +721,61 @@ ir.cpp: # 157| r0_15(int *) = PointerAdd[4] : r0_12, r0_14 # 157| r0_16(glval) = VariableAddress[q] : # 157| mu0_17(int *) = Store : &:r0_16, r0_15 -# 157| r0_18(glval) = CopyValue : r0_16 -# 158| r0_19(glval) = VariableAddress[i] : -# 158| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 158| r0_21(glval) = VariableAddress[p] : -# 158| r0_22(int *) = Load : &:r0_21, ~mu0_2 -# 158| r0_23(int *) = PointerAdd[4] : r0_22, r0_20 -# 158| r0_24(glval) = VariableAddress[q] : -# 158| mu0_25(int *) = Store : &:r0_24, r0_23 -# 158| r0_26(glval) = CopyValue : r0_24 -# 159| r0_27(glval) = VariableAddress[p] : -# 159| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 159| r0_29(glval) = VariableAddress[i] : -# 159| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 159| r0_31(int *) = PointerSub[4] : r0_28, r0_30 -# 159| r0_32(glval) = VariableAddress[q] : -# 159| mu0_33(int *) = Store : &:r0_32, r0_31 -# 159| r0_34(glval) = CopyValue : r0_32 -# 160| r0_35(glval) = VariableAddress[p] : -# 160| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 160| r0_37(glval) = VariableAddress[q] : -# 160| r0_38(int *) = Load : &:r0_37, ~mu0_2 -# 160| r0_39(long) = PointerDiff[4] : r0_36, r0_38 -# 160| r0_40(int) = Convert : r0_39 -# 160| r0_41(glval) = VariableAddress[i] : -# 160| mu0_42(int) = Store : &:r0_41, r0_40 -# 160| r0_43(glval) = CopyValue : r0_41 -# 162| r0_44(glval) = VariableAddress[p] : -# 162| r0_45(int *) = Load : &:r0_44, ~mu0_2 -# 162| r0_46(glval) = VariableAddress[q] : -# 162| mu0_47(int *) = Store : &:r0_46, r0_45 -# 162| r0_48(glval) = CopyValue : r0_46 -# 164| r0_49(glval) = VariableAddress[i] : -# 164| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 164| r0_51(glval) = VariableAddress[q] : -# 164| r0_52(int *) = Load : &:r0_51, ~mu0_2 -# 164| r0_53(int *) = PointerAdd[4] : r0_52, r0_50 -# 164| mu0_54(int *) = Store : &:r0_51, r0_53 -# 164| r0_55(glval) = CopyValue : r0_51 -# 165| r0_56(glval) = VariableAddress[i] : -# 165| r0_57(int) = Load : &:r0_56, ~mu0_2 -# 165| r0_58(glval) = VariableAddress[q] : -# 165| r0_59(int *) = Load : &:r0_58, ~mu0_2 -# 165| r0_60(int *) = PointerSub[4] : r0_59, r0_57 -# 165| mu0_61(int *) = Store : &:r0_58, r0_60 -# 165| r0_62(glval) = CopyValue : r0_58 -# 167| r0_63(glval) = VariableAddress[p] : -# 167| r0_64(int *) = Load : &:r0_63, ~mu0_2 -# 167| r0_65(int *) = Constant[0] : -# 167| r0_66(bool) = CompareNE : r0_64, r0_65 -# 167| r0_67(glval) = VariableAddress[b] : -# 167| mu0_68(bool) = Store : &:r0_67, r0_66 -# 167| r0_69(glval) = CopyValue : r0_67 -# 168| r0_70(glval) = VariableAddress[p] : -# 168| r0_71(int *) = Load : &:r0_70, ~mu0_2 -# 168| r0_72(int *) = Constant[0] : -# 168| r0_73(bool) = CompareNE : r0_71, r0_72 -# 168| r0_74(bool) = LogicalNot : r0_73 -# 168| r0_75(glval) = VariableAddress[b] : -# 168| mu0_76(bool) = Store : &:r0_75, r0_74 -# 168| r0_77(glval) = CopyValue : r0_75 -# 169| v0_78(void) = NoOp : -# 153| v0_79(void) = ReturnVoid : -# 153| v0_80(void) = UnmodeledUse : mu* -# 153| v0_81(void) = ExitFunction : +# 158| r0_18(glval) = VariableAddress[i] : +# 158| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 158| r0_20(glval) = VariableAddress[p] : +# 158| r0_21(int *) = Load : &:r0_20, ~mu0_2 +# 158| r0_22(int *) = PointerAdd[4] : r0_21, r0_19 +# 158| r0_23(glval) = VariableAddress[q] : +# 158| mu0_24(int *) = Store : &:r0_23, r0_22 +# 159| r0_25(glval) = VariableAddress[p] : +# 159| r0_26(int *) = Load : &:r0_25, ~mu0_2 +# 159| r0_27(glval) = VariableAddress[i] : +# 159| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 159| r0_29(int *) = PointerSub[4] : r0_26, r0_28 +# 159| r0_30(glval) = VariableAddress[q] : +# 159| mu0_31(int *) = Store : &:r0_30, r0_29 +# 160| r0_32(glval) = VariableAddress[p] : +# 160| r0_33(int *) = Load : &:r0_32, ~mu0_2 +# 160| r0_34(glval) = VariableAddress[q] : +# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 +# 160| r0_36(long) = PointerDiff[4] : r0_33, r0_35 +# 160| r0_37(int) = Convert : r0_36 +# 160| r0_38(glval) = VariableAddress[i] : +# 160| mu0_39(int) = Store : &:r0_38, r0_37 +# 162| r0_40(glval) = VariableAddress[p] : +# 162| r0_41(int *) = Load : &:r0_40, ~mu0_2 +# 162| r0_42(glval) = VariableAddress[q] : +# 162| mu0_43(int *) = Store : &:r0_42, r0_41 +# 164| r0_44(glval) = VariableAddress[i] : +# 164| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 164| r0_46(glval) = VariableAddress[q] : +# 164| r0_47(int *) = Load : &:r0_46, ~mu0_2 +# 164| r0_48(int *) = PointerAdd[4] : r0_47, r0_45 +# 164| mu0_49(int *) = Store : &:r0_46, r0_48 +# 165| r0_50(glval) = VariableAddress[i] : +# 165| r0_51(int) = Load : &:r0_50, ~mu0_2 +# 165| r0_52(glval) = VariableAddress[q] : +# 165| r0_53(int *) = Load : &:r0_52, ~mu0_2 +# 165| r0_54(int *) = PointerSub[4] : r0_53, r0_51 +# 165| mu0_55(int *) = Store : &:r0_52, r0_54 +# 167| r0_56(glval) = VariableAddress[p] : +# 167| r0_57(int *) = Load : &:r0_56, ~mu0_2 +# 167| r0_58(int *) = Constant[0] : +# 167| r0_59(bool) = CompareNE : r0_57, r0_58 +# 167| r0_60(glval) = VariableAddress[b] : +# 167| mu0_61(bool) = Store : &:r0_60, r0_59 +# 168| r0_62(glval) = VariableAddress[p] : +# 168| r0_63(int *) = Load : &:r0_62, ~mu0_2 +# 168| r0_64(int *) = Constant[0] : +# 168| r0_65(bool) = CompareNE : r0_63, r0_64 +# 168| r0_66(bool) = LogicalNot : r0_65 +# 168| r0_67(glval) = VariableAddress[b] : +# 168| mu0_68(bool) = Store : &:r0_67, r0_66 +# 169| v0_69(void) = NoOp : +# 153| v0_70(void) = ReturnVoid : +# 153| v0_71(void) = UnmodeledUse : mu* +# 153| v0_72(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 @@ -866,76 +796,68 @@ ir.cpp: # 174| r0_14(int) = Load : &:r0_13, ~mu0_2 # 174| r0_15(glval) = VariableAddress[x] : # 174| mu0_16(int) = Store : &:r0_15, r0_14 -# 174| r0_17(glval) = CopyValue : r0_15 -# 175| r0_18(glval) = VariableAddress[p] : -# 175| r0_19(int *) = Load : &:r0_18, ~mu0_2 -# 175| r0_20(glval) = VariableAddress[i] : -# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 -# 175| r0_22(glval) = PointerAdd[4] : r0_19, r0_21 -# 175| r0_23(int) = Load : &:r0_22, ~mu0_2 -# 175| r0_24(glval) = VariableAddress[x] : -# 175| mu0_25(int) = Store : &:r0_24, r0_23 -# 175| r0_26(glval) = CopyValue : r0_24 -# 177| r0_27(glval) = VariableAddress[x] : -# 177| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 177| r0_29(glval) = VariableAddress[p] : -# 177| r0_30(int *) = Load : &:r0_29, ~mu0_2 -# 177| r0_31(glval) = VariableAddress[i] : -# 177| r0_32(int) = Load : &:r0_31, ~mu0_2 -# 177| r0_33(glval) = PointerAdd[4] : r0_30, r0_32 -# 177| mu0_34(int) = Store : &:r0_33, r0_28 -# 177| r0_35(glval) = CopyValue : r0_33 -# 178| r0_36(glval) = VariableAddress[x] : -# 178| r0_37(int) = Load : &:r0_36, ~mu0_2 -# 178| r0_38(glval) = VariableAddress[p] : -# 178| r0_39(int *) = Load : &:r0_38, ~mu0_2 -# 178| r0_40(glval) = VariableAddress[i] : -# 178| r0_41(int) = Load : &:r0_40, ~mu0_2 -# 178| r0_42(glval) = PointerAdd[4] : r0_39, r0_41 -# 178| mu0_43(int) = Store : &:r0_42, r0_37 -# 178| r0_44(glval) = CopyValue : r0_42 -# 180| r0_45(glval) = VariableAddress[a] : -# 180| mu0_46(int[10]) = Uninitialized[a] : &:r0_45 -# 181| r0_47(glval) = VariableAddress[a] : -# 181| r0_48(int *) = Convert : r0_47 -# 181| r0_49(glval) = VariableAddress[i] : -# 181| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 181| r0_51(glval) = PointerAdd[4] : r0_48, r0_50 -# 181| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 181| r0_53(glval) = VariableAddress[x] : -# 181| mu0_54(int) = Store : &:r0_53, r0_52 -# 181| r0_55(glval) = CopyValue : r0_53 -# 182| r0_56(glval) = VariableAddress[a] : -# 182| r0_57(int *) = Convert : r0_56 -# 182| r0_58(glval) = VariableAddress[i] : -# 182| r0_59(int) = Load : &:r0_58, ~mu0_2 -# 182| r0_60(glval) = PointerAdd[4] : r0_57, r0_59 -# 182| r0_61(int) = Load : &:r0_60, ~mu0_2 -# 182| r0_62(glval) = VariableAddress[x] : -# 182| mu0_63(int) = Store : &:r0_62, r0_61 -# 182| r0_64(glval) = CopyValue : r0_62 -# 183| r0_65(glval) = VariableAddress[x] : -# 183| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 183| r0_67(glval) = VariableAddress[a] : -# 183| r0_68(int *) = Convert : r0_67 -# 183| r0_69(glval) = VariableAddress[i] : -# 183| r0_70(int) = Load : &:r0_69, ~mu0_2 -# 183| r0_71(glval) = PointerAdd[4] : r0_68, r0_70 -# 183| mu0_72(int) = Store : &:r0_71, r0_66 -# 183| r0_73(glval) = CopyValue : r0_71 -# 184| r0_74(glval) = VariableAddress[x] : -# 184| r0_75(int) = Load : &:r0_74, ~mu0_2 -# 184| r0_76(glval) = VariableAddress[a] : -# 184| r0_77(int *) = Convert : r0_76 -# 184| r0_78(glval) = VariableAddress[i] : -# 184| r0_79(int) = Load : &:r0_78, ~mu0_2 -# 184| r0_80(glval) = PointerAdd[4] : r0_77, r0_79 -# 184| mu0_81(int) = Store : &:r0_80, r0_75 -# 184| r0_82(glval) = CopyValue : r0_80 -# 185| v0_83(void) = NoOp : -# 171| v0_84(void) = ReturnVoid : -# 171| v0_85(void) = UnmodeledUse : mu* -# 171| v0_86(void) = ExitFunction : +# 175| r0_17(glval) = VariableAddress[p] : +# 175| r0_18(int *) = Load : &:r0_17, ~mu0_2 +# 175| r0_19(glval) = VariableAddress[i] : +# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 175| r0_21(glval) = PointerAdd[4] : r0_18, r0_20 +# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 +# 175| r0_23(glval) = VariableAddress[x] : +# 175| mu0_24(int) = Store : &:r0_23, r0_22 +# 177| r0_25(glval) = VariableAddress[x] : +# 177| r0_26(int) = Load : &:r0_25, ~mu0_2 +# 177| r0_27(glval) = VariableAddress[p] : +# 177| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 177| r0_29(glval) = VariableAddress[i] : +# 177| r0_30(int) = Load : &:r0_29, ~mu0_2 +# 177| r0_31(glval) = PointerAdd[4] : r0_28, r0_30 +# 177| mu0_32(int) = Store : &:r0_31, r0_26 +# 178| r0_33(glval) = VariableAddress[x] : +# 178| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 178| r0_35(glval) = VariableAddress[p] : +# 178| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 178| r0_37(glval) = VariableAddress[i] : +# 178| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 178| r0_39(glval) = PointerAdd[4] : r0_36, r0_38 +# 178| mu0_40(int) = Store : &:r0_39, r0_34 +# 180| r0_41(glval) = VariableAddress[a] : +# 180| mu0_42(int[10]) = Uninitialized[a] : &:r0_41 +# 181| r0_43(glval) = VariableAddress[a] : +# 181| r0_44(int *) = Convert : r0_43 +# 181| r0_45(glval) = VariableAddress[i] : +# 181| r0_46(int) = Load : &:r0_45, ~mu0_2 +# 181| r0_47(glval) = PointerAdd[4] : r0_44, r0_46 +# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 +# 181| r0_49(glval) = VariableAddress[x] : +# 181| mu0_50(int) = Store : &:r0_49, r0_48 +# 182| r0_51(glval) = VariableAddress[a] : +# 182| r0_52(int *) = Convert : r0_51 +# 182| r0_53(glval) = VariableAddress[i] : +# 182| r0_54(int) = Load : &:r0_53, ~mu0_2 +# 182| r0_55(glval) = PointerAdd[4] : r0_52, r0_54 +# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 +# 182| r0_57(glval) = VariableAddress[x] : +# 182| mu0_58(int) = Store : &:r0_57, r0_56 +# 183| r0_59(glval) = VariableAddress[x] : +# 183| r0_60(int) = Load : &:r0_59, ~mu0_2 +# 183| r0_61(glval) = VariableAddress[a] : +# 183| r0_62(int *) = Convert : r0_61 +# 183| r0_63(glval) = VariableAddress[i] : +# 183| r0_64(int) = Load : &:r0_63, ~mu0_2 +# 183| r0_65(glval) = PointerAdd[4] : r0_62, r0_64 +# 183| mu0_66(int) = Store : &:r0_65, r0_60 +# 184| r0_67(glval) = VariableAddress[x] : +# 184| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 184| r0_69(glval) = VariableAddress[a] : +# 184| r0_70(int *) = Convert : r0_69 +# 184| r0_71(glval) = VariableAddress[i] : +# 184| r0_72(int) = Load : &:r0_71, ~mu0_2 +# 184| r0_73(glval) = PointerAdd[4] : r0_70, r0_72 +# 184| mu0_74(int) = Store : &:r0_73, r0_68 +# 185| v0_75(void) = NoOp : +# 171| v0_76(void) = ReturnVoid : +# 171| v0_77(void) = UnmodeledUse : mu* +# 171| v0_78(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -988,51 +910,45 @@ ir.cpp: # 196| r0_13(bool) = CompareEQ : r0_10, r0_12 # 196| r0_14(glval) = VariableAddress[b] : # 196| mu0_15(bool) = Store : &:r0_14, r0_13 -# 196| r0_16(glval) = CopyValue : r0_14 -# 197| r0_17(glval) = VariableAddress[p] : -# 197| r0_18(int *) = Load : &:r0_17, ~mu0_2 -# 197| r0_19(glval) = VariableAddress[q] : -# 197| r0_20(int *) = Load : &:r0_19, ~mu0_2 -# 197| r0_21(bool) = CompareNE : r0_18, r0_20 -# 197| r0_22(glval) = VariableAddress[b] : -# 197| mu0_23(bool) = Store : &:r0_22, r0_21 -# 197| r0_24(glval) = CopyValue : r0_22 -# 198| r0_25(glval) = VariableAddress[p] : +# 197| r0_16(glval) = VariableAddress[p] : +# 197| r0_17(int *) = Load : &:r0_16, ~mu0_2 +# 197| r0_18(glval) = VariableAddress[q] : +# 197| r0_19(int *) = Load : &:r0_18, ~mu0_2 +# 197| r0_20(bool) = CompareNE : r0_17, r0_19 +# 197| r0_21(glval) = VariableAddress[b] : +# 197| mu0_22(bool) = Store : &:r0_21, r0_20 +# 198| r0_23(glval) = VariableAddress[p] : +# 198| r0_24(int *) = Load : &:r0_23, ~mu0_2 +# 198| r0_25(glval) = VariableAddress[q] : # 198| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 198| r0_27(glval) = VariableAddress[q] : -# 198| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 198| r0_29(bool) = CompareLT : r0_26, r0_28 -# 198| r0_30(glval) = VariableAddress[b] : -# 198| mu0_31(bool) = Store : &:r0_30, r0_29 -# 198| r0_32(glval) = CopyValue : r0_30 -# 199| r0_33(glval) = VariableAddress[p] : -# 199| r0_34(int *) = Load : &:r0_33, ~mu0_2 -# 199| r0_35(glval) = VariableAddress[q] : -# 199| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 199| r0_37(bool) = CompareGT : r0_34, r0_36 -# 199| r0_38(glval) = VariableAddress[b] : -# 199| mu0_39(bool) = Store : &:r0_38, r0_37 -# 199| r0_40(glval) = CopyValue : r0_38 -# 200| r0_41(glval) = VariableAddress[p] : -# 200| r0_42(int *) = Load : &:r0_41, ~mu0_2 -# 200| r0_43(glval) = VariableAddress[q] : -# 200| r0_44(int *) = Load : &:r0_43, ~mu0_2 -# 200| r0_45(bool) = CompareLE : r0_42, r0_44 -# 200| r0_46(glval) = VariableAddress[b] : -# 200| mu0_47(bool) = Store : &:r0_46, r0_45 -# 200| r0_48(glval) = CopyValue : r0_46 -# 201| r0_49(glval) = VariableAddress[p] : -# 201| r0_50(int *) = Load : &:r0_49, ~mu0_2 -# 201| r0_51(glval) = VariableAddress[q] : -# 201| r0_52(int *) = Load : &:r0_51, ~mu0_2 -# 201| r0_53(bool) = CompareGE : r0_50, r0_52 -# 201| r0_54(glval) = VariableAddress[b] : -# 201| mu0_55(bool) = Store : &:r0_54, r0_53 -# 201| r0_56(glval) = CopyValue : r0_54 -# 202| v0_57(void) = NoOp : -# 193| v0_58(void) = ReturnVoid : -# 193| v0_59(void) = UnmodeledUse : mu* -# 193| v0_60(void) = ExitFunction : +# 198| r0_27(bool) = CompareLT : r0_24, r0_26 +# 198| r0_28(glval) = VariableAddress[b] : +# 198| mu0_29(bool) = Store : &:r0_28, r0_27 +# 199| r0_30(glval) = VariableAddress[p] : +# 199| r0_31(int *) = Load : &:r0_30, ~mu0_2 +# 199| r0_32(glval) = VariableAddress[q] : +# 199| r0_33(int *) = Load : &:r0_32, ~mu0_2 +# 199| r0_34(bool) = CompareGT : r0_31, r0_33 +# 199| r0_35(glval) = VariableAddress[b] : +# 199| mu0_36(bool) = Store : &:r0_35, r0_34 +# 200| r0_37(glval) = VariableAddress[p] : +# 200| r0_38(int *) = Load : &:r0_37, ~mu0_2 +# 200| r0_39(glval) = VariableAddress[q] : +# 200| r0_40(int *) = Load : &:r0_39, ~mu0_2 +# 200| r0_41(bool) = CompareLE : r0_38, r0_40 +# 200| r0_42(glval) = VariableAddress[b] : +# 200| mu0_43(bool) = Store : &:r0_42, r0_41 +# 201| r0_44(glval) = VariableAddress[p] : +# 201| r0_45(int *) = Load : &:r0_44, ~mu0_2 +# 201| r0_46(glval) = VariableAddress[q] : +# 201| r0_47(int *) = Load : &:r0_46, ~mu0_2 +# 201| r0_48(bool) = CompareGE : r0_45, r0_47 +# 201| r0_49(glval) = VariableAddress[b] : +# 201| mu0_50(bool) = Store : &:r0_49, r0_48 +# 202| v0_51(void) = NoOp : +# 193| v0_52(void) = ReturnVoid : +# 193| v0_53(void) = UnmodeledUse : mu* +# 193| v0_54(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 @@ -1050,35 +966,31 @@ ir.cpp: # 207| mu0_11(int *) = Store : &:r0_7, r0_10 # 207| r0_12(glval) = VariableAddress[q] : # 207| mu0_13(int *) = Store : &:r0_12, r0_10 -# 207| r0_14(glval) = CopyValue : r0_12 -# 208| r0_15(glval) = VariableAddress[p] : -# 208| r0_16(int *) = Load : &:r0_15, ~mu0_2 -# 208| r0_17(int) = Constant[1] : -# 208| r0_18(int *) = PointerSub[4] : r0_16, r0_17 -# 208| mu0_19(int *) = Store : &:r0_15, r0_18 -# 208| r0_20(glval) = VariableAddress[q] : -# 208| mu0_21(int *) = Store : &:r0_20, r0_18 -# 208| r0_22(glval) = CopyValue : r0_20 -# 209| r0_23(glval) = VariableAddress[p] : -# 209| r0_24(int *) = Load : &:r0_23, ~mu0_2 -# 209| r0_25(int) = Constant[1] : -# 209| r0_26(int *) = PointerAdd[4] : r0_24, r0_25 -# 209| mu0_27(int *) = Store : &:r0_23, r0_26 -# 209| r0_28(glval) = VariableAddress[q] : -# 209| mu0_29(int *) = Store : &:r0_28, r0_24 -# 209| r0_30(glval) = CopyValue : r0_28 -# 210| r0_31(glval) = VariableAddress[p] : -# 210| r0_32(int *) = Load : &:r0_31, ~mu0_2 -# 210| r0_33(int) = Constant[1] : -# 210| r0_34(int *) = PointerSub[4] : r0_32, r0_33 -# 210| mu0_35(int *) = Store : &:r0_31, r0_34 -# 210| r0_36(glval) = VariableAddress[q] : -# 210| mu0_37(int *) = Store : &:r0_36, r0_32 -# 210| r0_38(glval) = CopyValue : r0_36 -# 211| v0_39(void) = NoOp : -# 204| v0_40(void) = ReturnVoid : -# 204| v0_41(void) = UnmodeledUse : mu* -# 204| v0_42(void) = ExitFunction : +# 208| r0_14(glval) = VariableAddress[p] : +# 208| r0_15(int *) = Load : &:r0_14, ~mu0_2 +# 208| r0_16(int) = Constant[1] : +# 208| r0_17(int *) = PointerSub[4] : r0_15, r0_16 +# 208| mu0_18(int *) = Store : &:r0_14, r0_17 +# 208| r0_19(glval) = VariableAddress[q] : +# 208| mu0_20(int *) = Store : &:r0_19, r0_17 +# 209| r0_21(glval) = VariableAddress[p] : +# 209| r0_22(int *) = Load : &:r0_21, ~mu0_2 +# 209| r0_23(int) = Constant[1] : +# 209| r0_24(int *) = PointerAdd[4] : r0_22, r0_23 +# 209| mu0_25(int *) = Store : &:r0_21, r0_24 +# 209| r0_26(glval) = VariableAddress[q] : +# 209| mu0_27(int *) = Store : &:r0_26, r0_22 +# 210| r0_28(glval) = VariableAddress[p] : +# 210| r0_29(int *) = Load : &:r0_28, ~mu0_2 +# 210| r0_30(int) = Constant[1] : +# 210| r0_31(int *) = PointerSub[4] : r0_29, r0_30 +# 210| mu0_32(int *) = Store : &:r0_28, r0_31 +# 210| r0_33(glval) = VariableAddress[q] : +# 210| mu0_34(int *) = Store : &:r0_33, r0_29 +# 211| v0_35(void) = NoOp : +# 204| v0_36(void) = ReturnVoid : +# 204| v0_37(void) = UnmodeledUse : mu* +# 204| v0_38(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -1093,40 +1005,36 @@ ir.cpp: # 216| r0_8(int) = Load : &:r0_7, ~mu0_2 # 216| r0_9(int) = Add : r0_8, r0_6 # 216| mu0_10(int) = Store : &:r0_7, r0_9 -# 216| r0_11(glval) = CopyValue : r0_7 -# 219| r0_12(glval) = VariableAddress[y] : -# 219| r0_13(short) = Constant[5] : -# 219| mu0_14(short) = Store : &:r0_12, r0_13 -# 220| r0_15(glval) = VariableAddress[x] : -# 220| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 220| r0_17(glval) = VariableAddress[y] : -# 220| r0_18(short) = Load : &:r0_17, ~mu0_2 -# 220| r0_19(int) = Convert : r0_18 -# 220| r0_20(int) = Add : r0_19, r0_16 -# 220| r0_21(short) = Convert : r0_20 -# 220| mu0_22(short) = Store : &:r0_17, r0_21 -# 220| r0_23(glval) = CopyValue : r0_17 -# 223| r0_24(int) = Constant[1] : -# 223| r0_25(glval) = VariableAddress[y] : -# 223| r0_26(short) = Load : &:r0_25, ~mu0_2 -# 223| r0_27(short) = ShiftLeft : r0_26, r0_24 -# 223| mu0_28(short) = Store : &:r0_25, r0_27 -# 223| r0_29(glval) = CopyValue : r0_25 -# 226| r0_30(glval) = VariableAddress[z] : -# 226| r0_31(long) = Constant[7] : -# 226| mu0_32(long) = Store : &:r0_30, r0_31 -# 227| r0_33(float) = Constant[2.0] : -# 227| r0_34(glval) = VariableAddress[z] : -# 227| r0_35(long) = Load : &:r0_34, ~mu0_2 -# 227| r0_36(float) = Convert : r0_35 -# 227| r0_37(float) = Add : r0_36, r0_33 -# 227| r0_38(long) = Convert : r0_37 -# 227| mu0_39(long) = Store : &:r0_34, r0_38 -# 227| r0_40(glval) = CopyValue : r0_34 -# 228| v0_41(void) = NoOp : -# 213| v0_42(void) = ReturnVoid : -# 213| v0_43(void) = UnmodeledUse : mu* -# 213| v0_44(void) = ExitFunction : +# 219| r0_11(glval) = VariableAddress[y] : +# 219| r0_12(short) = Constant[5] : +# 219| mu0_13(short) = Store : &:r0_11, r0_12 +# 220| r0_14(glval) = VariableAddress[x] : +# 220| r0_15(int) = Load : &:r0_14, ~mu0_2 +# 220| r0_16(glval) = VariableAddress[y] : +# 220| r0_17(short) = Load : &:r0_16, ~mu0_2 +# 220| r0_18(int) = Convert : r0_17 +# 220| r0_19(int) = Add : r0_18, r0_15 +# 220| r0_20(short) = Convert : r0_19 +# 220| mu0_21(short) = Store : &:r0_16, r0_20 +# 223| r0_22(int) = Constant[1] : +# 223| r0_23(glval) = VariableAddress[y] : +# 223| r0_24(short) = Load : &:r0_23, ~mu0_2 +# 223| r0_25(short) = ShiftLeft : r0_24, r0_22 +# 223| mu0_26(short) = Store : &:r0_23, r0_25 +# 226| r0_27(glval) = VariableAddress[z] : +# 226| r0_28(long) = Constant[7] : +# 226| mu0_29(long) = Store : &:r0_27, r0_28 +# 227| r0_30(float) = Constant[2.0] : +# 227| r0_31(glval) = VariableAddress[z] : +# 227| r0_32(long) = Load : &:r0_31, ~mu0_2 +# 227| r0_33(float) = Convert : r0_32 +# 227| r0_34(float) = Add : r0_33, r0_30 +# 227| r0_35(long) = Convert : r0_34 +# 227| mu0_36(long) = Store : &:r0_31, r0_35 +# 228| v0_37(void) = NoOp : +# 213| v0_38(void) = ReturnVoid : +# 213| v0_39(void) = UnmodeledUse : mu* +# 213| v0_40(void) = ExitFunction : # 230| void UninitializedVariables() # 230| Block 0 @@ -1194,7 +1102,6 @@ ir.cpp: # 244| r2_1(int) = Load : &:r2_0, ~mu0_2 # 244| r2_2(glval) = VariableAddress[x] : # 244| mu2_3(int) = Store : &:r2_2, r2_1 -# 244| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 247| Block 3 @@ -1210,14 +1117,12 @@ ir.cpp: # 248| r4_0(int) = Constant[2] : # 248| r4_1(glval) = VariableAddress[x] : # 248| mu4_2(int) = Store : &:r4_1, r4_0 -# 248| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 250| Block 5 # 250| r5_0(int) = Constant[7] : # 250| r5_1(glval) = VariableAddress[x] : # 250| mu5_2(int) = Store : &:r5_1, r5_0 -# 250| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 251| Block 6 @@ -1245,7 +1150,6 @@ ir.cpp: # 255| r1_2(int) = Load : &:r1_1, ~mu0_2 # 255| r1_3(int) = Sub : r1_2, r1_0 # 255| mu1_4(int) = Store : &:r1_1, r1_3 -# 255| r1_5(glval) = CopyValue : r1_1 #-----| Goto (back edge) -> Block 3 # 257| Block 2 @@ -1278,12 +1182,11 @@ ir.cpp: # 261| r1_2(int) = Load : &:r1_1, ~mu0_2 # 261| r1_3(int) = Sub : r1_2, r1_0 # 261| mu1_4(int) = Store : &:r1_1, r1_3 -# 261| r1_5(glval) = CopyValue : r1_1 -# 262| r1_6(glval) = VariableAddress[n] : -# 262| r1_7(int) = Load : &:r1_6, ~mu0_2 -# 262| r1_8(int) = Constant[0] : -# 262| r1_9(bool) = CompareGT : r1_7, r1_8 -# 262| v1_10(void) = ConditionalBranch : r1_9 +# 262| r1_5(glval) = VariableAddress[n] : +# 262| r1_6(int) = Load : &:r1_5, ~mu0_2 +# 262| r1_7(int) = Constant[0] : +# 262| r1_8(bool) = CompareGT : r1_6, r1_7 +# 262| v1_9(void) = ConditionalBranch : r1_8 #-----| False -> Block 2 #-----| True (back edge) -> Block 1 @@ -1381,7 +1284,6 @@ ir.cpp: # 287| r2_3(int) = Load : &:r2_2, ~mu0_2 # 287| r2_4(int) = Add : r2_3, r2_1 # 287| mu2_5(int) = Store : &:r2_2, r2_4 -# 287| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 292| void For_InitCondition() @@ -1435,7 +1337,6 @@ ir.cpp: # 299| r2_3(int) = Load : &:r2_2, ~mu0_2 # 299| r2_4(int) = Add : r2_3, r2_1 # 299| mu2_5(int) = Store : &:r2_2, r2_4 -# 299| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 304| void For_ConditionUpdate() @@ -1464,7 +1365,6 @@ ir.cpp: # 306| r2_3(int) = Load : &:r2_2, ~mu0_2 # 306| r2_4(int) = Add : r2_3, r2_1 # 306| mu2_5(int) = Store : &:r2_2, r2_4 -# 306| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 309| Block 3 @@ -1499,7 +1399,6 @@ ir.cpp: # 312| r2_3(int) = Load : &:r2_2, ~mu0_2 # 312| r2_4(int) = Add : r2_3, r2_1 # 312| mu2_5(int) = Store : &:r2_2, r2_4 -# 312| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 315| Block 3 @@ -1533,7 +1432,6 @@ ir.cpp: # 318| r2_2(int) = Load : &:r2_1, ~mu0_2 # 318| r2_3(int) = Add : r2_2, r2_0 # 318| mu2_4(int) = Store : &:r2_1, r2_3 -# 318| r2_5(glval) = CopyValue : r2_1 #-----| Goto (back edge) -> Block 1 # 319| Block 3 @@ -1595,7 +1493,6 @@ ir.cpp: # 326| r4_3(int) = Load : &:r4_2, ~mu0_2 # 326| r4_4(int) = Add : r4_3, r4_1 # 326| mu4_5(int) = Store : &:r4_2, r4_4 -# 326| r4_6(glval) = CopyValue : r4_2 #-----| Goto (back edge) -> Block 1 # 331| Block 5 @@ -1658,16 +1555,15 @@ ir.cpp: # 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 # 342| r0_8(glval) = CopyValue : r0_7 # 342| mu0_9(int) = Store : &:r0_8, r0_5 -# 342| r0_10(glval) = CopyValue : r0_8 -# 343| r0_11(glval) = VariableAddress[#return] : -# 343| r0_12(glval) = VariableAddress[p] : -# 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 -# 343| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 343| mu0_15(int) = Store : &:r0_11, r0_14 -# 341| r0_16(glval) = VariableAddress[#return] : -# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 -# 341| v0_18(void) = UnmodeledUse : mu* -# 341| v0_19(void) = ExitFunction : +# 343| r0_10(glval) = VariableAddress[#return] : +# 343| r0_11(glval) = VariableAddress[p] : +# 343| r0_12(int *) = Load : &:r0_11, ~mu0_2 +# 343| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 343| mu0_14(int) = Store : &:r0_10, r0_13 +# 341| r0_15(glval) = VariableAddress[#return] : +# 341| v0_16(void) = ReturnValue : &:r0_15, ~mu0_2 +# 341| v0_17(void) = UnmodeledUse : mu* +# 341| v0_18(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -1711,7 +1607,6 @@ ir.cpp: # 356| r3_2(int) = Load : &:r3_1, ~mu0_2 # 356| r3_3(int) = Sub : r3_2, r3_0 # 356| mu3_4(int) = Store : &:r3_1, r3_3 -# 356| r3_5(glval) = CopyValue : r3_1 #-----| Goto (back edge) -> Block 5 # 357| Block 4 @@ -1758,7 +1653,6 @@ ir.cpp: # 365| r3_2(int) = Load : &:r3_1, ~mu0_2 # 365| r3_3(int) = Sub : r3_2, r3_0 # 365| mu3_4(int) = Store : &:r3_1, r3_3 -# 365| r3_5(glval) = CopyValue : r3_1 #-----| Goto -> Block 4 # 361| Block 4 @@ -1863,7 +1757,6 @@ ir.cpp: # 387| r1_0(int) = Constant[1234] : # 387| r1_1(glval) = VariableAddress[y] : # 387| mu1_2(int) = Store : &:r1_1, r1_0 -# 387| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 389| Block 2 @@ -1871,8 +1764,7 @@ ir.cpp: # 390| r2_1(int) = Constant[-1] : # 390| r2_2(glval) = VariableAddress[y] : # 390| mu2_3(int) = Store : &:r2_2, r2_1 -# 390| r2_4(glval) = CopyValue : r2_2 -# 391| v2_5(void) = NoOp : +# 391| v2_4(void) = NoOp : #-----| Goto -> Block 9 # 393| Block 3 @@ -1884,8 +1776,7 @@ ir.cpp: # 395| r4_1(int) = Constant[1] : # 395| r4_2(glval) = VariableAddress[y] : # 395| mu4_3(int) = Store : &:r4_2, r4_1 -# 395| r4_4(glval) = CopyValue : r4_2 -# 396| v4_5(void) = NoOp : +# 396| v4_4(void) = NoOp : #-----| Goto -> Block 9 # 398| Block 5 @@ -1893,7 +1784,6 @@ ir.cpp: # 399| r5_1(int) = Constant[3] : # 399| r5_2(glval) = VariableAddress[y] : # 399| mu5_3(int) = Store : &:r5_2, r5_1 -# 399| r5_4(glval) = CopyValue : r5_2 #-----| Goto -> Block 6 # 400| Block 6 @@ -1901,8 +1791,7 @@ ir.cpp: # 401| r6_1(int) = Constant[4] : # 401| r6_2(glval) = VariableAddress[y] : # 401| mu6_3(int) = Store : &:r6_2, r6_1 -# 401| r6_4(glval) = CopyValue : r6_2 -# 402| v6_5(void) = NoOp : +# 402| v6_4(void) = NoOp : #-----| Goto -> Block 9 # 404| Block 7 @@ -1910,15 +1799,13 @@ ir.cpp: # 405| r7_1(int) = Constant[0] : # 405| r7_2(glval) = VariableAddress[y] : # 405| mu7_3(int) = Store : &:r7_2, r7_1 -# 405| r7_4(glval) = CopyValue : r7_2 -# 406| v7_5(void) = NoOp : +# 406| v7_4(void) = NoOp : #-----| Goto -> Block 9 # 408| Block 8 # 408| r8_0(int) = Constant[5678] : # 408| r8_1(glval) = VariableAddress[y] : # 408| mu8_2(int) = Store : &:r8_1, r8_0 -# 408| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 9 # 409| Block 9 @@ -1955,23 +1842,21 @@ ir.cpp: # 428| r0_6(glval) = VariableAddress[pt] : # 428| r0_7(glval) = FieldAddress[x] : r0_6 # 428| mu0_8(int) = Store : &:r0_7, r0_5 -# 428| r0_9(glval) = CopyValue : r0_7 -# 429| r0_10(glval) = VariableAddress[pt] : -# 429| r0_11(glval) = FieldAddress[x] : r0_10 -# 429| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 429| r0_13(glval) = VariableAddress[pt] : -# 429| r0_14(glval) = FieldAddress[y] : r0_13 -# 429| mu0_15(int) = Store : &:r0_14, r0_12 -# 429| r0_16(glval) = CopyValue : r0_14 -# 430| r0_17(glval) = VariableAddress[p] : -# 430| r0_18(glval) = VariableAddress[pt] : -# 430| r0_19(glval) = FieldAddress[y] : r0_18 -# 430| r0_20(int *) = CopyValue : r0_19 -# 430| mu0_21(int *) = Store : &:r0_17, r0_20 -# 431| v0_22(void) = NoOp : -# 426| v0_23(void) = ReturnVoid : -# 426| v0_24(void) = UnmodeledUse : mu* -# 426| v0_25(void) = ExitFunction : +# 429| r0_9(glval) = VariableAddress[pt] : +# 429| r0_10(glval) = FieldAddress[x] : r0_9 +# 429| r0_11(int) = Load : &:r0_10, ~mu0_2 +# 429| r0_12(glval) = VariableAddress[pt] : +# 429| r0_13(glval) = FieldAddress[y] : r0_12 +# 429| mu0_14(int) = Store : &:r0_13, r0_11 +# 430| r0_15(glval) = VariableAddress[p] : +# 430| r0_16(glval) = VariableAddress[pt] : +# 430| r0_17(glval) = FieldAddress[y] : r0_16 +# 430| r0_18(int *) = CopyValue : r0_17 +# 430| mu0_19(int *) = Store : &:r0_15, r0_18 +# 431| v0_20(void) = NoOp : +# 426| v0_21(void) = ReturnVoid : +# 426| v0_22(void) = UnmodeledUse : mu* +# 426| v0_23(void) = ExitFunction : # 433| void LogicalOr(bool, bool) # 433| Block 0 @@ -2001,7 +1886,6 @@ ir.cpp: # 436| r2_0(int) = Constant[7] : # 436| r2_1(glval) = VariableAddress[x] : # 436| mu2_2(int) = Store : &:r2_1, r2_0 -# 436| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 439| Block 3 @@ -2022,14 +1906,12 @@ ir.cpp: # 440| r5_0(int) = Constant[1] : # 440| r5_1(glval) = VariableAddress[x] : # 440| mu5_2(int) = Store : &:r5_1, r5_0 -# 440| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 443| Block 6 # 443| r6_0(int) = Constant[5] : # 443| r6_1(glval) = VariableAddress[x] : # 443| mu6_2(int) = Store : &:r6_1, r6_0 -# 443| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 445| Block 7 @@ -2066,7 +1948,6 @@ ir.cpp: # 450| r2_0(int) = Constant[7] : # 450| r2_1(glval) = VariableAddress[x] : # 450| mu2_2(int) = Store : &:r2_1, r2_0 -# 450| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 453| Block 3 @@ -2087,14 +1968,12 @@ ir.cpp: # 454| r5_0(int) = Constant[1] : # 454| r5_1(glval) = VariableAddress[x] : # 454| mu5_2(int) = Store : &:r5_1, r5_0 -# 454| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 457| Block 6 # 457| r6_0(int) = Constant[5] : # 457| r6_1(glval) = VariableAddress[x] : # 457| mu6_2(int) = Store : &:r6_1, r6_0 -# 457| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 459| Block 7 @@ -2124,7 +2003,6 @@ ir.cpp: # 464| r1_0(int) = Constant[1] : # 464| r1_1(glval) = VariableAddress[x] : # 464| mu1_2(int) = Store : &:r1_1, r1_0 -# 464| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 467| Block 2 @@ -2145,14 +2023,12 @@ ir.cpp: # 468| r4_0(int) = Constant[2] : # 468| r4_1(glval) = VariableAddress[x] : # 468| mu4_2(int) = Store : &:r4_1, r4_0 -# 468| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 471| Block 5 # 471| r5_0(int) = Constant[3] : # 471| r5_1(glval) = VariableAddress[x] : # 471| mu5_2(int) = Store : &:r5_1, r5_0 -# 471| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 473| Block 6 @@ -2196,10 +2072,9 @@ ir.cpp: # 478| r3_1(bool) = Load : &:r3_0, ~mu0_2 # 478| r3_2(glval) = VariableAddress[x] : # 478| mu3_3(bool) = Store : &:r3_2, r3_1 -# 478| r3_4(glval) = CopyValue : r3_2 -# 479| r3_5(glval) = VariableAddress[a] : -# 479| r3_6(bool) = Load : &:r3_5, ~mu0_2 -# 479| v3_7(void) = ConditionalBranch : r3_6 +# 479| r3_4(glval) = VariableAddress[a] : +# 479| r3_5(bool) = Load : &:r3_4, ~mu0_2 +# 479| v3_6(void) = ConditionalBranch : r3_5 #-----| False -> Block 9 #-----| True -> Block 8 @@ -2228,11 +2103,10 @@ ir.cpp: # 479| r7_2(bool) = LogicalNot : r7_1 # 479| r7_3(glval) = VariableAddress[x] : # 479| mu7_4(bool) = Store : &:r7_3, r7_2 -# 479| r7_5(glval) = CopyValue : r7_3 -# 480| v7_6(void) = NoOp : -# 475| v7_7(void) = ReturnVoid : -# 475| v7_8(void) = UnmodeledUse : mu* -# 475| v7_9(void) = ExitFunction : +# 480| v7_5(void) = NoOp : +# 475| v7_6(void) = ReturnVoid : +# 475| v7_7(void) = UnmodeledUse : mu* +# 475| v7_8(void) = ExitFunction : # 479| Block 8 # 479| r8_0(glval) = VariableAddress[#temp479:11] : @@ -2258,10 +2132,9 @@ ir.cpp: # 477| r11_1(bool) = Load : &:r11_0, ~mu0_2 # 477| r11_2(glval) = VariableAddress[x] : # 477| mu11_3(bool) = Store : &:r11_2, r11_1 -# 477| r11_4(glval) = CopyValue : r11_2 -# 478| r11_5(glval) = VariableAddress[a] : -# 478| r11_6(bool) = Load : &:r11_5, ~mu0_2 -# 478| v11_7(void) = ConditionalBranch : r11_6 +# 478| r11_4(glval) = VariableAddress[a] : +# 478| r11_5(bool) = Load : &:r11_4, ~mu0_2 +# 478| v11_6(void) = ConditionalBranch : r11_5 #-----| False -> Block 5 #-----| True -> Block 4 @@ -2334,11 +2207,10 @@ ir.cpp: # 489| r1_0(glval) = VariableAddress[#temp489:6] : # 489| r1_1(glval) = Load : &:r1_0, ~mu0_2 # 489| mu1_2(int) = Store : &:r1_1, r0_9 -# 489| r1_3(glval) = CopyValue : r1_1 -# 490| v1_4(void) = NoOp : -# 486| v1_5(void) = ReturnVoid : -# 486| v1_6(void) = UnmodeledUse : mu* -# 486| v1_7(void) = ExitFunction : +# 490| v1_3(void) = NoOp : +# 486| v1_4(void) = ReturnVoid : +# 486| v1_5(void) = UnmodeledUse : mu* +# 486| v1_6(void) = ExitFunction : # 489| Block 2 # 489| r2_0(glval) = VariableAddress[x] : @@ -2397,15 +2269,13 @@ ir.cpp: # 499| r0_9(int *) = Constant[0] : # 499| r0_10(glval) = VariableAddress[p] : # 499| mu0_11(int *) = Store : &:r0_10, r0_9 -# 499| r0_12(glval) = CopyValue : r0_10 -# 500| r0_13(int *) = Constant[0] : -# 500| r0_14(glval) = VariableAddress[q] : -# 500| mu0_15(int *) = Store : &:r0_14, r0_13 -# 500| r0_16(glval) = CopyValue : r0_14 -# 501| v0_17(void) = NoOp : -# 496| v0_18(void) = ReturnVoid : -# 496| v0_19(void) = UnmodeledUse : mu* -# 496| v0_20(void) = ExitFunction : +# 500| r0_12(int *) = Constant[0] : +# 500| r0_13(glval) = VariableAddress[q] : +# 500| mu0_14(int *) = Store : &:r0_13, r0_12 +# 501| v0_15(void) = NoOp : +# 496| v0_16(void) = ReturnVoid : +# 496| v0_17(void) = UnmodeledUse : mu* +# 496| v0_18(void) = ExitFunction : # 503| void InitList(int, float) # 503| Block 0 @@ -2633,8 +2503,7 @@ ir.cpp: # 540| r3_1(int) = Load : &:r3_0, ~mu0_2 # 540| r3_2(glval) = VariableAddress[y] : # 540| mu3_3(int) = Store : &:r3_2, r3_1 -# 540| r3_4(glval) = CopyValue : r3_2 -# 541| v3_5(void) = NoOp : +# 541| v3_4(void) = NoOp : #-----| Goto -> Block 1 # 543| int EarlyReturnValue(int, int) @@ -2837,24 +2706,21 @@ ir.cpp: # 592| r0_7(..(*)(..)) = CopyValue : r0_6 # 592| r0_8(glval<..(*)(..)>) = VariableAddress[pfn] : # 592| mu0_9(..(*)(..)) = Store : &:r0_8, r0_7 -# 592| r0_10(glval<..(*)(..)>) = CopyValue : r0_8 -# 593| r0_11(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : -# 593| r0_12(..(*)(..)) = CopyValue : r0_11 -# 593| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : -# 593| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 -# 593| r0_15(glval<..(*)(..)>) = CopyValue : r0_13 -# 594| r0_16(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_10(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_11(..(*)(..)) = CopyValue : r0_10 +# 593| r0_12(glval<..(*)(..)>) = VariableAddress[pfn] : +# 593| mu0_13(..(*)(..)) = Store : &:r0_12, r0_11 +# 594| r0_14(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 594| r0_15(..(*)(..)) = CopyValue : r0_14 +# 594| r0_16(..(*)(..)) = CopyValue : r0_15 # 594| r0_17(..(*)(..)) = CopyValue : r0_16 # 594| r0_18(..(*)(..)) = CopyValue : r0_17 -# 594| r0_19(..(*)(..)) = CopyValue : r0_18 -# 594| r0_20(..(*)(..)) = CopyValue : r0_19 -# 594| r0_21(glval<..(*)(..)>) = VariableAddress[pfn] : -# 594| mu0_22(..(*)(..)) = Store : &:r0_21, r0_20 -# 594| r0_23(glval<..(*)(..)>) = CopyValue : r0_21 -# 595| v0_24(void) = NoOp : -# 590| v0_25(void) = ReturnVoid : -# 590| v0_26(void) = UnmodeledUse : mu* -# 590| v0_27(void) = ExitFunction : +# 594| r0_19(glval<..(*)(..)>) = VariableAddress[pfn] : +# 594| mu0_20(..(*)(..)) = Store : &:r0_19, r0_18 +# 595| v0_21(void) = NoOp : +# 590| v0_22(void) = ReturnVoid : +# 590| v0_23(void) = UnmodeledUse : mu* +# 590| v0_24(void) = ExitFunction : # 615| void DeclareObject() # 615| Block 0 @@ -2991,43 +2857,37 @@ ir.cpp: # 643| r0_5(C *) = CopyValue : r0_3 # 643| r0_6(glval) = FieldAddress[m_a] : r0_5 # 643| mu0_7(int) = Store : &:r0_6, r0_4 -# 643| r0_8(glval) = CopyValue : r0_6 -# 644| r0_9(int) = Constant[1] : -# 644| r0_10(C *) = CopyValue : r0_3 -# 644| r0_11(glval) = CopyValue : r0_10 -# 644| r0_12(glval) = FieldAddress[m_a] : r0_11 -# 644| mu0_13(int) = Store : &:r0_12, r0_9 -# 644| r0_14(glval) = CopyValue : r0_12 -# 645| r0_15(int) = Constant[2] : -#-----| r0_16(C *) = CopyValue : r0_3 -# 645| r0_17(glval) = FieldAddress[m_a] : r0_16 -# 645| mu0_18(int) = Store : &:r0_17, r0_15 -# 645| r0_19(glval) = CopyValue : r0_17 -# 646| r0_20(glval) = VariableAddress[x] : -# 646| mu0_21(int) = Uninitialized[x] : &:r0_20 -# 647| r0_22(C *) = CopyValue : r0_3 -# 647| r0_23(glval) = FieldAddress[m_a] : r0_22 -# 647| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 647| r0_25(glval) = VariableAddress[x] : -# 647| mu0_26(int) = Store : &:r0_25, r0_24 -# 647| r0_27(glval) = CopyValue : r0_25 -# 648| r0_28(C *) = CopyValue : r0_3 -# 648| r0_29(glval) = CopyValue : r0_28 -# 648| r0_30(glval) = FieldAddress[m_a] : r0_29 -# 648| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 648| r0_32(glval) = VariableAddress[x] : -# 648| mu0_33(int) = Store : &:r0_32, r0_31 -# 648| r0_34(glval) = CopyValue : r0_32 -#-----| r0_35(C *) = CopyValue : r0_3 -# 649| r0_36(glval) = FieldAddress[m_a] : r0_35 -# 649| r0_37(int) = Load : &:r0_36, ~mu0_2 -# 649| r0_38(glval) = VariableAddress[x] : -# 649| mu0_39(int) = Store : &:r0_38, r0_37 -# 649| r0_40(glval) = CopyValue : r0_38 -# 650| v0_41(void) = NoOp : -# 642| v0_42(void) = ReturnVoid : -# 642| v0_43(void) = UnmodeledUse : mu* -# 642| v0_44(void) = ExitFunction : +# 644| r0_8(int) = Constant[1] : +# 644| r0_9(C *) = CopyValue : r0_3 +# 644| r0_10(glval) = CopyValue : r0_9 +# 644| r0_11(glval) = FieldAddress[m_a] : r0_10 +# 644| mu0_12(int) = Store : &:r0_11, r0_8 +# 645| r0_13(int) = Constant[2] : +#-----| r0_14(C *) = CopyValue : r0_3 +# 645| r0_15(glval) = FieldAddress[m_a] : r0_14 +# 645| mu0_16(int) = Store : &:r0_15, r0_13 +# 646| r0_17(glval) = VariableAddress[x] : +# 646| mu0_18(int) = Uninitialized[x] : &:r0_17 +# 647| r0_19(C *) = CopyValue : r0_3 +# 647| r0_20(glval) = FieldAddress[m_a] : r0_19 +# 647| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 647| r0_22(glval) = VariableAddress[x] : +# 647| mu0_23(int) = Store : &:r0_22, r0_21 +# 648| r0_24(C *) = CopyValue : r0_3 +# 648| r0_25(glval) = CopyValue : r0_24 +# 648| r0_26(glval) = FieldAddress[m_a] : r0_25 +# 648| r0_27(int) = Load : &:r0_26, ~mu0_2 +# 648| r0_28(glval) = VariableAddress[x] : +# 648| mu0_29(int) = Store : &:r0_28, r0_27 +#-----| r0_30(C *) = CopyValue : r0_3 +# 649| r0_31(glval) = FieldAddress[m_a] : r0_30 +# 649| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 649| r0_33(glval) = VariableAddress[x] : +# 649| mu0_34(int) = Store : &:r0_33, r0_32 +# 650| v0_35(void) = NoOp : +# 642| v0_36(void) = ReturnVoid : +# 642| v0_37(void) = UnmodeledUse : mu* +# 642| v0_38(void) = ExitFunction : # 652| void C::MethodCalls() # 652| Block 0 @@ -3363,7 +3223,6 @@ ir.cpp: # 731| r6_4(int) = Load : &:r6_3, ~mu0_2 # 731| r6_5(glval) = VariableAddress[x] : # 731| mu6_6(int) = Store : &:r6_5, r6_4 -# 731| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 731| Block 7 @@ -3382,7 +3241,6 @@ ir.cpp: # 733| r8_0(int) = Constant[7] : # 733| r8_1(glval) = VariableAddress[x] : # 733| mu8_2(int) = Store : &:r8_1, r8_0 -# 733| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 14 # 735| Block 9 @@ -3898,219 +3756,203 @@ ir.cpp: # 811| r0_79(Base *) = ConvertToBase[Middle : Base] : r0_78 # 811| r0_80(glval) = VariableAddress[pb] : # 811| mu0_81(Base *) = Store : &:r0_80, r0_79 -# 811| r0_82(glval) = CopyValue : r0_80 -# 812| r0_83(glval) = VariableAddress[pm] : -# 812| r0_84(Middle *) = Load : &:r0_83, ~mu0_2 -# 812| r0_85(Base *) = ConvertToBase[Middle : Base] : r0_84 -# 812| r0_86(glval) = VariableAddress[pb] : -# 812| mu0_87(Base *) = Store : &:r0_86, r0_85 -# 812| r0_88(glval) = CopyValue : r0_86 -# 813| r0_89(glval) = VariableAddress[pm] : -# 813| r0_90(Middle *) = Load : &:r0_89, ~mu0_2 -# 813| r0_91(Base *) = ConvertToBase[Middle : Base] : r0_90 -# 813| r0_92(glval) = VariableAddress[pb] : -# 813| mu0_93(Base *) = Store : &:r0_92, r0_91 -# 813| r0_94(glval) = CopyValue : r0_92 -# 814| r0_95(glval) = VariableAddress[pm] : -# 814| r0_96(Middle *) = Load : &:r0_95, ~mu0_2 -# 814| r0_97(Base *) = Convert : r0_96 -# 814| r0_98(glval) = VariableAddress[pb] : -# 814| mu0_99(Base *) = Store : &:r0_98, r0_97 -# 814| r0_100(glval) = CopyValue : r0_98 -# 816| r0_101(glval) = VariableAddress[m] : -# 816| r0_102(glval) = FunctionAddress[operator=] : -# 816| r0_103(glval) = VariableAddress[b] : -# 816| r0_104(glval) = ConvertToDerived[Middle : Base] : r0_103 -# 816| r0_105(glval) = Convert : r0_104 -# 816| r0_106(Middle &) = CopyValue : r0_105 -# 816| r0_107(Middle &) = Call : func:r0_102, this:r0_101, 0:r0_106 -# 816| mu0_108(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_109(void) = ^IndirectReadSideEffect[-1] : &:r0_101, ~mu0_2 -# 816| v0_110(void) = ^IndirectReadSideEffect[0] : &:r0_106, ~mu0_2 -# 816| mu0_111(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_101 -# 816| mu0_112(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_106 -# 816| r0_113(glval) = CopyValue : r0_107 -# 817| r0_114(glval) = VariableAddress[m] : -# 817| r0_115(glval) = FunctionAddress[operator=] : -# 817| r0_116(glval) = VariableAddress[b] : -# 817| r0_117(glval) = ConvertToDerived[Middle : Base] : r0_116 -# 817| r0_118(glval) = Convert : r0_117 -# 817| r0_119(Middle &) = CopyValue : r0_118 -# 817| r0_120(Middle &) = Call : func:r0_115, this:r0_114, 0:r0_119 -# 817| mu0_121(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_122(void) = ^IndirectReadSideEffect[-1] : &:r0_114, ~mu0_2 -# 817| v0_123(void) = ^IndirectReadSideEffect[0] : &:r0_119, ~mu0_2 -# 817| mu0_124(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_114 -# 817| mu0_125(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_119 -# 817| r0_126(glval) = CopyValue : r0_120 -# 818| r0_127(glval) = VariableAddress[pb] : -# 818| r0_128(Base *) = Load : &:r0_127, ~mu0_2 -# 818| r0_129(Middle *) = ConvertToDerived[Middle : Base] : r0_128 -# 818| r0_130(glval) = VariableAddress[pm] : -# 818| mu0_131(Middle *) = Store : &:r0_130, r0_129 -# 818| r0_132(glval) = CopyValue : r0_130 -# 819| r0_133(glval) = VariableAddress[pb] : -# 819| r0_134(Base *) = Load : &:r0_133, ~mu0_2 -# 819| r0_135(Middle *) = ConvertToDerived[Middle : Base] : r0_134 -# 819| r0_136(glval) = VariableAddress[pm] : -# 819| mu0_137(Middle *) = Store : &:r0_136, r0_135 -# 819| r0_138(glval) = CopyValue : r0_136 -# 820| r0_139(glval) = VariableAddress[pb] : -# 820| r0_140(Base *) = Load : &:r0_139, ~mu0_2 -# 820| r0_141(Middle *) = Convert : r0_140 -# 820| r0_142(glval) = VariableAddress[pm] : -# 820| mu0_143(Middle *) = Store : &:r0_142, r0_141 -# 820| r0_144(glval) = CopyValue : r0_142 -# 822| r0_145(glval) = VariableAddress[b] : -# 822| r0_146(glval) = FunctionAddress[operator=] : -# 822| r0_147(glval) = VariableAddress[d] : -# 822| r0_148(glval) = ConvertToBase[Derived : Middle] : r0_147 -# 822| r0_149(glval) = ConvertToBase[Middle : Base] : r0_148 -# 822| r0_150(Base &) = CopyValue : r0_149 -# 822| r0_151(Base &) = Call : func:r0_146, this:r0_145, 0:r0_150 -# 822| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_145, ~mu0_2 -# 822| v0_154(void) = ^IndirectReadSideEffect[0] : &:r0_150, ~mu0_2 -# 822| mu0_155(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_145 -# 822| mu0_156(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_150 -# 822| r0_157(glval) = CopyValue : r0_151 -# 823| r0_158(glval) = VariableAddress[b] : -# 823| r0_159(glval) = FunctionAddress[operator=] : -# 823| r0_160(glval) = FunctionAddress[Base] : -# 823| r0_161(glval) = VariableAddress[d] : -# 823| r0_162(glval) = ConvertToBase[Derived : Middle] : r0_161 -# 823| r0_163(glval) = ConvertToBase[Middle : Base] : r0_162 -# 823| r0_164(Base &) = CopyValue : r0_163 -# 823| v0_165(void) = Call : func:r0_160, 0:r0_164 -# 823| mu0_166(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_167(void) = ^IndirectReadSideEffect[0] : &:r0_164, ~mu0_2 -# 823| mu0_168(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_164 -# 823| r0_169(glval) = Convert : v0_165 -# 823| r0_170(Base &) = CopyValue : r0_169 -# 823| r0_171(Base &) = Call : func:r0_159, this:r0_158, 0:r0_170 -# 823| mu0_172(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_173(void) = ^IndirectReadSideEffect[-1] : &:r0_158, ~mu0_2 -# 823| v0_174(void) = ^IndirectReadSideEffect[0] : &:r0_170, ~mu0_2 -# 823| mu0_175(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_158 -# 823| mu0_176(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_170 -# 823| r0_177(glval) = CopyValue : r0_171 -# 824| r0_178(glval) = VariableAddress[b] : -# 824| r0_179(glval) = FunctionAddress[operator=] : -# 824| r0_180(glval) = FunctionAddress[Base] : -# 824| r0_181(glval) = VariableAddress[d] : -# 824| r0_182(glval) = ConvertToBase[Derived : Middle] : r0_181 -# 824| r0_183(glval) = ConvertToBase[Middle : Base] : r0_182 -# 824| r0_184(Base &) = CopyValue : r0_183 -# 824| v0_185(void) = Call : func:r0_180, 0:r0_184 -# 824| mu0_186(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_187(void) = ^IndirectReadSideEffect[0] : &:r0_184, ~mu0_2 -# 824| mu0_188(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_184 -# 824| r0_189(glval) = Convert : v0_185 -# 824| r0_190(Base &) = CopyValue : r0_189 -# 824| r0_191(Base &) = Call : func:r0_179, this:r0_178, 0:r0_190 -# 824| mu0_192(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_193(void) = ^IndirectReadSideEffect[-1] : &:r0_178, ~mu0_2 -# 824| v0_194(void) = ^IndirectReadSideEffect[0] : &:r0_190, ~mu0_2 -# 824| mu0_195(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_178 -# 824| mu0_196(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_190 -# 824| r0_197(glval) = CopyValue : r0_191 -# 825| r0_198(glval) = VariableAddress[pd] : -# 825| r0_199(Derived *) = Load : &:r0_198, ~mu0_2 -# 825| r0_200(Middle *) = ConvertToBase[Derived : Middle] : r0_199 -# 825| r0_201(Base *) = ConvertToBase[Middle : Base] : r0_200 -# 825| r0_202(glval) = VariableAddress[pb] : -# 825| mu0_203(Base *) = Store : &:r0_202, r0_201 -# 825| r0_204(glval) = CopyValue : r0_202 -# 826| r0_205(glval) = VariableAddress[pd] : -# 826| r0_206(Derived *) = Load : &:r0_205, ~mu0_2 -# 826| r0_207(Middle *) = ConvertToBase[Derived : Middle] : r0_206 -# 826| r0_208(Base *) = ConvertToBase[Middle : Base] : r0_207 -# 826| r0_209(glval) = VariableAddress[pb] : -# 826| mu0_210(Base *) = Store : &:r0_209, r0_208 -# 826| r0_211(glval) = CopyValue : r0_209 -# 827| r0_212(glval) = VariableAddress[pd] : -# 827| r0_213(Derived *) = Load : &:r0_212, ~mu0_2 -# 827| r0_214(Middle *) = ConvertToBase[Derived : Middle] : r0_213 -# 827| r0_215(Base *) = ConvertToBase[Middle : Base] : r0_214 -# 827| r0_216(glval) = VariableAddress[pb] : -# 827| mu0_217(Base *) = Store : &:r0_216, r0_215 -# 827| r0_218(glval) = CopyValue : r0_216 -# 828| r0_219(glval) = VariableAddress[pd] : -# 828| r0_220(Derived *) = Load : &:r0_219, ~mu0_2 -# 828| r0_221(Base *) = Convert : r0_220 -# 828| r0_222(glval) = VariableAddress[pb] : -# 828| mu0_223(Base *) = Store : &:r0_222, r0_221 -# 828| r0_224(glval) = CopyValue : r0_222 -# 830| r0_225(glval) = VariableAddress[d] : -# 830| r0_226(glval) = FunctionAddress[operator=] : -# 830| r0_227(glval) = VariableAddress[b] : -# 830| r0_228(glval) = ConvertToDerived[Middle : Base] : r0_227 -# 830| r0_229(glval) = ConvertToDerived[Derived : Middle] : r0_228 -# 830| r0_230(glval) = Convert : r0_229 -# 830| r0_231(Derived &) = CopyValue : r0_230 -# 830| r0_232(Derived &) = Call : func:r0_226, this:r0_225, 0:r0_231 -# 830| mu0_233(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_234(void) = ^IndirectReadSideEffect[-1] : &:r0_225, ~mu0_2 -# 830| v0_235(void) = ^IndirectReadSideEffect[0] : &:r0_231, ~mu0_2 -# 830| mu0_236(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_225 -# 830| mu0_237(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_231 -# 830| r0_238(glval) = CopyValue : r0_232 -# 831| r0_239(glval) = VariableAddress[d] : -# 831| r0_240(glval) = FunctionAddress[operator=] : -# 831| r0_241(glval) = VariableAddress[b] : -# 831| r0_242(glval) = ConvertToDerived[Middle : Base] : r0_241 -# 831| r0_243(glval) = ConvertToDerived[Derived : Middle] : r0_242 -# 831| r0_244(glval) = Convert : r0_243 -# 831| r0_245(Derived &) = CopyValue : r0_244 -# 831| r0_246(Derived &) = Call : func:r0_240, this:r0_239, 0:r0_245 -# 831| mu0_247(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_248(void) = ^IndirectReadSideEffect[-1] : &:r0_239, ~mu0_2 -# 831| v0_249(void) = ^IndirectReadSideEffect[0] : &:r0_245, ~mu0_2 -# 831| mu0_250(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_239 -# 831| mu0_251(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_245 -# 831| r0_252(glval) = CopyValue : r0_246 -# 832| r0_253(glval) = VariableAddress[pb] : -# 832| r0_254(Base *) = Load : &:r0_253, ~mu0_2 -# 832| r0_255(Middle *) = ConvertToDerived[Middle : Base] : r0_254 -# 832| r0_256(Derived *) = ConvertToDerived[Derived : Middle] : r0_255 -# 832| r0_257(glval) = VariableAddress[pd] : -# 832| mu0_258(Derived *) = Store : &:r0_257, r0_256 -# 832| r0_259(glval) = CopyValue : r0_257 -# 833| r0_260(glval) = VariableAddress[pb] : -# 833| r0_261(Base *) = Load : &:r0_260, ~mu0_2 -# 833| r0_262(Middle *) = ConvertToDerived[Middle : Base] : r0_261 -# 833| r0_263(Derived *) = ConvertToDerived[Derived : Middle] : r0_262 -# 833| r0_264(glval) = VariableAddress[pd] : -# 833| mu0_265(Derived *) = Store : &:r0_264, r0_263 -# 833| r0_266(glval) = CopyValue : r0_264 -# 834| r0_267(glval) = VariableAddress[pb] : -# 834| r0_268(Base *) = Load : &:r0_267, ~mu0_2 -# 834| r0_269(Derived *) = Convert : r0_268 -# 834| r0_270(glval) = VariableAddress[pd] : -# 834| mu0_271(Derived *) = Store : &:r0_270, r0_269 -# 834| r0_272(glval) = CopyValue : r0_270 -# 836| r0_273(glval) = VariableAddress[pmv] : -# 836| r0_274(MiddleVB1 *) = Constant[0] : -# 836| mu0_275(MiddleVB1 *) = Store : &:r0_273, r0_274 -# 837| r0_276(glval) = VariableAddress[pdv] : -# 837| r0_277(DerivedVB *) = Constant[0] : -# 837| mu0_278(DerivedVB *) = Store : &:r0_276, r0_277 -# 838| r0_279(glval) = VariableAddress[pmv] : -# 838| r0_280(MiddleVB1 *) = Load : &:r0_279, ~mu0_2 -# 838| r0_281(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_280 -# 838| r0_282(glval) = VariableAddress[pb] : -# 838| mu0_283(Base *) = Store : &:r0_282, r0_281 -# 838| r0_284(glval) = CopyValue : r0_282 -# 839| r0_285(glval) = VariableAddress[pdv] : -# 839| r0_286(DerivedVB *) = Load : &:r0_285, ~mu0_2 -# 839| r0_287(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_286 -# 839| r0_288(glval) = VariableAddress[pb] : -# 839| mu0_289(Base *) = Store : &:r0_288, r0_287 -# 839| r0_290(glval) = CopyValue : r0_288 -# 840| v0_291(void) = NoOp : -# 799| v0_292(void) = ReturnVoid : -# 799| v0_293(void) = UnmodeledUse : mu* -# 799| v0_294(void) = ExitFunction : +# 812| r0_82(glval) = VariableAddress[pm] : +# 812| r0_83(Middle *) = Load : &:r0_82, ~mu0_2 +# 812| r0_84(Base *) = ConvertToBase[Middle : Base] : r0_83 +# 812| r0_85(glval) = VariableAddress[pb] : +# 812| mu0_86(Base *) = Store : &:r0_85, r0_84 +# 813| r0_87(glval) = VariableAddress[pm] : +# 813| r0_88(Middle *) = Load : &:r0_87, ~mu0_2 +# 813| r0_89(Base *) = ConvertToBase[Middle : Base] : r0_88 +# 813| r0_90(glval) = VariableAddress[pb] : +# 813| mu0_91(Base *) = Store : &:r0_90, r0_89 +# 814| r0_92(glval) = VariableAddress[pm] : +# 814| r0_93(Middle *) = Load : &:r0_92, ~mu0_2 +# 814| r0_94(Base *) = Convert : r0_93 +# 814| r0_95(glval) = VariableAddress[pb] : +# 814| mu0_96(Base *) = Store : &:r0_95, r0_94 +# 816| r0_97(glval) = VariableAddress[m] : +# 816| r0_98(glval) = FunctionAddress[operator=] : +# 816| r0_99(glval) = VariableAddress[b] : +# 816| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 +# 816| r0_101(glval) = Convert : r0_100 +# 816| r0_102(Middle &) = CopyValue : r0_101 +# 816| r0_103(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_102 +# 816| mu0_104(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_105(void) = ^IndirectReadSideEffect[-1] : &:r0_97, ~mu0_2 +# 816| v0_106(void) = ^IndirectReadSideEffect[0] : &:r0_102, ~mu0_2 +# 816| mu0_107(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 +# 816| mu0_108(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_102 +# 816| r0_109(glval) = CopyValue : r0_103 +# 817| r0_110(glval) = VariableAddress[m] : +# 817| r0_111(glval) = FunctionAddress[operator=] : +# 817| r0_112(glval) = VariableAddress[b] : +# 817| r0_113(glval) = ConvertToDerived[Middle : Base] : r0_112 +# 817| r0_114(glval) = Convert : r0_113 +# 817| r0_115(Middle &) = CopyValue : r0_114 +# 817| r0_116(Middle &) = Call : func:r0_111, this:r0_110, 0:r0_115 +# 817| mu0_117(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_118(void) = ^IndirectReadSideEffect[-1] : &:r0_110, ~mu0_2 +# 817| v0_119(void) = ^IndirectReadSideEffect[0] : &:r0_115, ~mu0_2 +# 817| mu0_120(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 +# 817| mu0_121(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_115 +# 817| r0_122(glval) = CopyValue : r0_116 +# 818| r0_123(glval) = VariableAddress[pb] : +# 818| r0_124(Base *) = Load : &:r0_123, ~mu0_2 +# 818| r0_125(Middle *) = ConvertToDerived[Middle : Base] : r0_124 +# 818| r0_126(glval) = VariableAddress[pm] : +# 818| mu0_127(Middle *) = Store : &:r0_126, r0_125 +# 819| r0_128(glval) = VariableAddress[pb] : +# 819| r0_129(Base *) = Load : &:r0_128, ~mu0_2 +# 819| r0_130(Middle *) = ConvertToDerived[Middle : Base] : r0_129 +# 819| r0_131(glval) = VariableAddress[pm] : +# 819| mu0_132(Middle *) = Store : &:r0_131, r0_130 +# 820| r0_133(glval) = VariableAddress[pb] : +# 820| r0_134(Base *) = Load : &:r0_133, ~mu0_2 +# 820| r0_135(Middle *) = Convert : r0_134 +# 820| r0_136(glval) = VariableAddress[pm] : +# 820| mu0_137(Middle *) = Store : &:r0_136, r0_135 +# 822| r0_138(glval) = VariableAddress[b] : +# 822| r0_139(glval) = FunctionAddress[operator=] : +# 822| r0_140(glval) = VariableAddress[d] : +# 822| r0_141(glval) = ConvertToBase[Derived : Middle] : r0_140 +# 822| r0_142(glval) = ConvertToBase[Middle : Base] : r0_141 +# 822| r0_143(Base &) = CopyValue : r0_142 +# 822| r0_144(Base &) = Call : func:r0_139, this:r0_138, 0:r0_143 +# 822| mu0_145(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_146(void) = ^IndirectReadSideEffect[-1] : &:r0_138, ~mu0_2 +# 822| v0_147(void) = ^IndirectReadSideEffect[0] : &:r0_143, ~mu0_2 +# 822| mu0_148(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_138 +# 822| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_143 +# 822| r0_150(glval) = CopyValue : r0_144 +# 823| r0_151(glval) = VariableAddress[b] : +# 823| r0_152(glval) = FunctionAddress[operator=] : +# 823| r0_153(glval) = FunctionAddress[Base] : +# 823| r0_154(glval) = VariableAddress[d] : +# 823| r0_155(glval) = ConvertToBase[Derived : Middle] : r0_154 +# 823| r0_156(glval) = ConvertToBase[Middle : Base] : r0_155 +# 823| r0_157(Base &) = CopyValue : r0_156 +# 823| v0_158(void) = Call : func:r0_153, 0:r0_157 +# 823| mu0_159(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_160(void) = ^IndirectReadSideEffect[0] : &:r0_157, ~mu0_2 +# 823| mu0_161(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_157 +# 823| r0_162(glval) = Convert : v0_158 +# 823| r0_163(Base &) = CopyValue : r0_162 +# 823| r0_164(Base &) = Call : func:r0_152, this:r0_151, 0:r0_163 +# 823| mu0_165(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_166(void) = ^IndirectReadSideEffect[-1] : &:r0_151, ~mu0_2 +# 823| v0_167(void) = ^IndirectReadSideEffect[0] : &:r0_163, ~mu0_2 +# 823| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 +# 823| mu0_169(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_163 +# 823| r0_170(glval) = CopyValue : r0_164 +# 824| r0_171(glval) = VariableAddress[b] : +# 824| r0_172(glval) = FunctionAddress[operator=] : +# 824| r0_173(glval) = FunctionAddress[Base] : +# 824| r0_174(glval) = VariableAddress[d] : +# 824| r0_175(glval) = ConvertToBase[Derived : Middle] : r0_174 +# 824| r0_176(glval) = ConvertToBase[Middle : Base] : r0_175 +# 824| r0_177(Base &) = CopyValue : r0_176 +# 824| v0_178(void) = Call : func:r0_173, 0:r0_177 +# 824| mu0_179(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_180(void) = ^IndirectReadSideEffect[0] : &:r0_177, ~mu0_2 +# 824| mu0_181(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_177 +# 824| r0_182(glval) = Convert : v0_178 +# 824| r0_183(Base &) = CopyValue : r0_182 +# 824| r0_184(Base &) = Call : func:r0_172, this:r0_171, 0:r0_183 +# 824| mu0_185(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_186(void) = ^IndirectReadSideEffect[-1] : &:r0_171, ~mu0_2 +# 824| v0_187(void) = ^IndirectReadSideEffect[0] : &:r0_183, ~mu0_2 +# 824| mu0_188(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_171 +# 824| mu0_189(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_183 +# 824| r0_190(glval) = CopyValue : r0_184 +# 825| r0_191(glval) = VariableAddress[pd] : +# 825| r0_192(Derived *) = Load : &:r0_191, ~mu0_2 +# 825| r0_193(Middle *) = ConvertToBase[Derived : Middle] : r0_192 +# 825| r0_194(Base *) = ConvertToBase[Middle : Base] : r0_193 +# 825| r0_195(glval) = VariableAddress[pb] : +# 825| mu0_196(Base *) = Store : &:r0_195, r0_194 +# 826| r0_197(glval) = VariableAddress[pd] : +# 826| r0_198(Derived *) = Load : &:r0_197, ~mu0_2 +# 826| r0_199(Middle *) = ConvertToBase[Derived : Middle] : r0_198 +# 826| r0_200(Base *) = ConvertToBase[Middle : Base] : r0_199 +# 826| r0_201(glval) = VariableAddress[pb] : +# 826| mu0_202(Base *) = Store : &:r0_201, r0_200 +# 827| r0_203(glval) = VariableAddress[pd] : +# 827| r0_204(Derived *) = Load : &:r0_203, ~mu0_2 +# 827| r0_205(Middle *) = ConvertToBase[Derived : Middle] : r0_204 +# 827| r0_206(Base *) = ConvertToBase[Middle : Base] : r0_205 +# 827| r0_207(glval) = VariableAddress[pb] : +# 827| mu0_208(Base *) = Store : &:r0_207, r0_206 +# 828| r0_209(glval) = VariableAddress[pd] : +# 828| r0_210(Derived *) = Load : &:r0_209, ~mu0_2 +# 828| r0_211(Base *) = Convert : r0_210 +# 828| r0_212(glval) = VariableAddress[pb] : +# 828| mu0_213(Base *) = Store : &:r0_212, r0_211 +# 830| r0_214(glval) = VariableAddress[d] : +# 830| r0_215(glval) = FunctionAddress[operator=] : +# 830| r0_216(glval) = VariableAddress[b] : +# 830| r0_217(glval) = ConvertToDerived[Middle : Base] : r0_216 +# 830| r0_218(glval) = ConvertToDerived[Derived : Middle] : r0_217 +# 830| r0_219(glval) = Convert : r0_218 +# 830| r0_220(Derived &) = CopyValue : r0_219 +# 830| r0_221(Derived &) = Call : func:r0_215, this:r0_214, 0:r0_220 +# 830| mu0_222(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_223(void) = ^IndirectReadSideEffect[-1] : &:r0_214, ~mu0_2 +# 830| v0_224(void) = ^IndirectReadSideEffect[0] : &:r0_220, ~mu0_2 +# 830| mu0_225(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_214 +# 830| mu0_226(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_220 +# 830| r0_227(glval) = CopyValue : r0_221 +# 831| r0_228(glval) = VariableAddress[d] : +# 831| r0_229(glval) = FunctionAddress[operator=] : +# 831| r0_230(glval) = VariableAddress[b] : +# 831| r0_231(glval) = ConvertToDerived[Middle : Base] : r0_230 +# 831| r0_232(glval) = ConvertToDerived[Derived : Middle] : r0_231 +# 831| r0_233(glval) = Convert : r0_232 +# 831| r0_234(Derived &) = CopyValue : r0_233 +# 831| r0_235(Derived &) = Call : func:r0_229, this:r0_228, 0:r0_234 +# 831| mu0_236(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_237(void) = ^IndirectReadSideEffect[-1] : &:r0_228, ~mu0_2 +# 831| v0_238(void) = ^IndirectReadSideEffect[0] : &:r0_234, ~mu0_2 +# 831| mu0_239(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_228 +# 831| mu0_240(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_234 +# 831| r0_241(glval) = CopyValue : r0_235 +# 832| r0_242(glval) = VariableAddress[pb] : +# 832| r0_243(Base *) = Load : &:r0_242, ~mu0_2 +# 832| r0_244(Middle *) = ConvertToDerived[Middle : Base] : r0_243 +# 832| r0_245(Derived *) = ConvertToDerived[Derived : Middle] : r0_244 +# 832| r0_246(glval) = VariableAddress[pd] : +# 832| mu0_247(Derived *) = Store : &:r0_246, r0_245 +# 833| r0_248(glval) = VariableAddress[pb] : +# 833| r0_249(Base *) = Load : &:r0_248, ~mu0_2 +# 833| r0_250(Middle *) = ConvertToDerived[Middle : Base] : r0_249 +# 833| r0_251(Derived *) = ConvertToDerived[Derived : Middle] : r0_250 +# 833| r0_252(glval) = VariableAddress[pd] : +# 833| mu0_253(Derived *) = Store : &:r0_252, r0_251 +# 834| r0_254(glval) = VariableAddress[pb] : +# 834| r0_255(Base *) = Load : &:r0_254, ~mu0_2 +# 834| r0_256(Derived *) = Convert : r0_255 +# 834| r0_257(glval) = VariableAddress[pd] : +# 834| mu0_258(Derived *) = Store : &:r0_257, r0_256 +# 836| r0_259(glval) = VariableAddress[pmv] : +# 836| r0_260(MiddleVB1 *) = Constant[0] : +# 836| mu0_261(MiddleVB1 *) = Store : &:r0_259, r0_260 +# 837| r0_262(glval) = VariableAddress[pdv] : +# 837| r0_263(DerivedVB *) = Constant[0] : +# 837| mu0_264(DerivedVB *) = Store : &:r0_262, r0_263 +# 838| r0_265(glval) = VariableAddress[pmv] : +# 838| r0_266(MiddleVB1 *) = Load : &:r0_265, ~mu0_2 +# 838| r0_267(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_266 +# 838| r0_268(glval) = VariableAddress[pb] : +# 838| mu0_269(Base *) = Store : &:r0_268, r0_267 +# 839| r0_270(glval) = VariableAddress[pdv] : +# 839| r0_271(DerivedVB *) = Load : &:r0_270, ~mu0_2 +# 839| r0_272(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_271 +# 839| r0_273(glval) = VariableAddress[pb] : +# 839| mu0_274(Base *) = Store : &:r0_273, r0_272 +# 840| v0_275(void) = NoOp : +# 799| v0_276(void) = ReturnVoid : +# 799| v0_277(void) = UnmodeledUse : mu* +# 799| v0_278(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -4179,37 +4021,35 @@ ir.cpp: # 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 # 857| r0_22(glval) = VariableAddress[pb] : # 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 -# 857| r0_24(glval) = CopyValue : r0_22 -# 858| r0_25(glval) = VariableAddress[rb] : -# 858| r0_26(glval) = VariableAddress[d] : -# 858| r0_27(glval) = CheckedConvertOrThrow : r0_26 -# 858| r0_28(PolymorphicBase &) = CopyValue : r0_27 -# 858| mu0_29(PolymorphicBase &) = Store : &:r0_25, r0_28 -# 860| r0_30(glval) = VariableAddress[pb] : -# 860| r0_31(PolymorphicBase *) = Load : &:r0_30, ~mu0_2 -# 860| r0_32(PolymorphicDerived *) = CheckedConvertOrNull : r0_31 -# 860| r0_33(glval) = VariableAddress[pd] : -# 860| mu0_34(PolymorphicDerived *) = Store : &:r0_33, r0_32 -# 860| r0_35(glval) = CopyValue : r0_33 -# 861| r0_36(glval) = VariableAddress[rd] : -# 861| r0_37(glval) = VariableAddress[b] : -# 861| r0_38(glval) = CheckedConvertOrThrow : r0_37 -# 861| r0_39(PolymorphicDerived &) = CopyValue : r0_38 -# 861| mu0_40(PolymorphicDerived &) = Store : &:r0_36, r0_39 -# 863| r0_41(glval) = VariableAddress[pv] : -# 863| r0_42(glval) = VariableAddress[pb] : -# 863| r0_43(PolymorphicBase *) = Load : &:r0_42, ~mu0_2 -# 863| r0_44(void *) = DynamicCastToVoid : r0_43 -# 863| mu0_45(void *) = Store : &:r0_41, r0_44 -# 864| r0_46(glval) = VariableAddress[pcv] : -# 864| r0_47(glval) = VariableAddress[pd] : -# 864| r0_48(PolymorphicDerived *) = Load : &:r0_47, ~mu0_2 -# 864| r0_49(void *) = DynamicCastToVoid : r0_48 -# 864| mu0_50(void *) = Store : &:r0_46, r0_49 -# 865| v0_51(void) = NoOp : -# 849| v0_52(void) = ReturnVoid : -# 849| v0_53(void) = UnmodeledUse : mu* -# 849| v0_54(void) = ExitFunction : +# 858| r0_24(glval) = VariableAddress[rb] : +# 858| r0_25(glval) = VariableAddress[d] : +# 858| r0_26(glval) = CheckedConvertOrThrow : r0_25 +# 858| r0_27(PolymorphicBase &) = CopyValue : r0_26 +# 858| mu0_28(PolymorphicBase &) = Store : &:r0_24, r0_27 +# 860| r0_29(glval) = VariableAddress[pb] : +# 860| r0_30(PolymorphicBase *) = Load : &:r0_29, ~mu0_2 +# 860| r0_31(PolymorphicDerived *) = CheckedConvertOrNull : r0_30 +# 860| r0_32(glval) = VariableAddress[pd] : +# 860| mu0_33(PolymorphicDerived *) = Store : &:r0_32, r0_31 +# 861| r0_34(glval) = VariableAddress[rd] : +# 861| r0_35(glval) = VariableAddress[b] : +# 861| r0_36(glval) = CheckedConvertOrThrow : r0_35 +# 861| r0_37(PolymorphicDerived &) = CopyValue : r0_36 +# 861| mu0_38(PolymorphicDerived &) = Store : &:r0_34, r0_37 +# 863| r0_39(glval) = VariableAddress[pv] : +# 863| r0_40(glval) = VariableAddress[pb] : +# 863| r0_41(PolymorphicBase *) = Load : &:r0_40, ~mu0_2 +# 863| r0_42(void *) = DynamicCastToVoid : r0_41 +# 863| mu0_43(void *) = Store : &:r0_39, r0_42 +# 864| r0_44(glval) = VariableAddress[pcv] : +# 864| r0_45(glval) = VariableAddress[pd] : +# 864| r0_46(PolymorphicDerived *) = Load : &:r0_45, ~mu0_2 +# 864| r0_47(void *) = DynamicCastToVoid : r0_46 +# 864| mu0_48(void *) = Store : &:r0_44, r0_47 +# 865| v0_49(void) = NoOp : +# 849| v0_50(void) = ReturnVoid : +# 849| v0_51(void) = UnmodeledUse : mu* +# 849| v0_52(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -4245,46 +4085,42 @@ ir.cpp: # 874| r0_11(char *) = Convert : r0_10 # 874| r0_12(glval) = VariableAddress[p] : # 874| mu0_13(char *) = Store : &:r0_12, r0_11 -# 874| r0_14(glval) = CopyValue : r0_12 -# 875| r0_15(glval) = VariableAddress[a] : -# 875| r0_16(char *) = Convert : r0_15 -# 875| r0_17(int) = Constant[0] : -# 875| r0_18(glval) = PointerAdd[1] : r0_16, r0_17 -# 875| r0_19(char *) = CopyValue : r0_18 -# 875| r0_20(char *) = Convert : r0_19 -# 875| r0_21(glval) = VariableAddress[p] : -# 875| mu0_22(char *) = Store : &:r0_21, r0_20 -# 875| r0_23(glval) = CopyValue : r0_21 -# 876| r0_24(glval) = StringConstant["test"] : -# 876| r0_25(char *) = Convert : r0_24 -# 876| r0_26(int) = Constant[0] : -# 876| r0_27(glval) = PointerAdd[1] : r0_25, r0_26 -# 876| r0_28(char *) = CopyValue : r0_27 -# 876| r0_29(glval) = VariableAddress[p] : -# 876| mu0_30(char *) = Store : &:r0_29, r0_28 -# 876| r0_31(glval) = CopyValue : r0_29 -# 877| r0_32(glval) = VariableAddress[ra] : -# 877| r0_33(glval) = VariableAddress[a] : -# 877| r0_34(char(&)[5]) = CopyValue : r0_33 -# 877| mu0_35(char(&)[5]) = Store : &:r0_32, r0_34 -# 878| r0_36(glval) = VariableAddress[rs] : -# 878| r0_37(glval) = StringConstant["test"] : -# 878| r0_38(char(&)[5]) = CopyValue : r0_37 -# 878| mu0_39(char(&)[5]) = Store : &:r0_36, r0_38 -# 879| r0_40(glval) = VariableAddress[pa] : -# 879| r0_41(glval) = VariableAddress[a] : -# 879| r0_42(char(*)[5]) = CopyValue : r0_41 -# 879| r0_43(char(*)[5]) = Convert : r0_42 -# 879| mu0_44(char(*)[5]) = Store : &:r0_40, r0_43 -# 880| r0_45(glval) = StringConstant["test"] : -# 880| r0_46(char(*)[5]) = CopyValue : r0_45 -# 880| r0_47(glval) = VariableAddress[pa] : -# 880| mu0_48(char(*)[5]) = Store : &:r0_47, r0_46 -# 880| r0_49(glval) = CopyValue : r0_47 -# 881| v0_50(void) = NoOp : -# 871| v0_51(void) = ReturnVoid : -# 871| v0_52(void) = UnmodeledUse : mu* -# 871| v0_53(void) = ExitFunction : +# 875| r0_14(glval) = VariableAddress[a] : +# 875| r0_15(char *) = Convert : r0_14 +# 875| r0_16(int) = Constant[0] : +# 875| r0_17(glval) = PointerAdd[1] : r0_15, r0_16 +# 875| r0_18(char *) = CopyValue : r0_17 +# 875| r0_19(char *) = Convert : r0_18 +# 875| r0_20(glval) = VariableAddress[p] : +# 875| mu0_21(char *) = Store : &:r0_20, r0_19 +# 876| r0_22(glval) = StringConstant["test"] : +# 876| r0_23(char *) = Convert : r0_22 +# 876| r0_24(int) = Constant[0] : +# 876| r0_25(glval) = PointerAdd[1] : r0_23, r0_24 +# 876| r0_26(char *) = CopyValue : r0_25 +# 876| r0_27(glval) = VariableAddress[p] : +# 876| mu0_28(char *) = Store : &:r0_27, r0_26 +# 877| r0_29(glval) = VariableAddress[ra] : +# 877| r0_30(glval) = VariableAddress[a] : +# 877| r0_31(char(&)[5]) = CopyValue : r0_30 +# 877| mu0_32(char(&)[5]) = Store : &:r0_29, r0_31 +# 878| r0_33(glval) = VariableAddress[rs] : +# 878| r0_34(glval) = StringConstant["test"] : +# 878| r0_35(char(&)[5]) = CopyValue : r0_34 +# 878| mu0_36(char(&)[5]) = Store : &:r0_33, r0_35 +# 879| r0_37(glval) = VariableAddress[pa] : +# 879| r0_38(glval) = VariableAddress[a] : +# 879| r0_39(char(*)[5]) = CopyValue : r0_38 +# 879| r0_40(char(*)[5]) = Convert : r0_39 +# 879| mu0_41(char(*)[5]) = Store : &:r0_37, r0_40 +# 880| r0_42(glval) = StringConstant["test"] : +# 880| r0_43(char(*)[5]) = CopyValue : r0_42 +# 880| r0_44(glval) = VariableAddress[pa] : +# 880| mu0_45(char(*)[5]) = Store : &:r0_44, r0_43 +# 881| v0_46(void) = NoOp : +# 871| v0_47(void) = ReturnVoid : +# 871| v0_48(void) = UnmodeledUse : mu* +# 871| v0_49(void) = ExitFunction : # 883| void FuncPtrConversions(int(*)(int), void*) # 883| Block 0 @@ -4300,17 +4136,15 @@ ir.cpp: # 884| r0_9(void *) = Convert : r0_8 # 884| r0_10(glval) = VariableAddress[p] : # 884| mu0_11(void *) = Store : &:r0_10, r0_9 -# 884| r0_12(glval) = CopyValue : r0_10 -# 885| r0_13(glval) = VariableAddress[p] : -# 885| r0_14(void *) = Load : &:r0_13, ~mu0_2 -# 885| r0_15(..(*)(..)) = Convert : r0_14 -# 885| r0_16(glval<..(*)(..)>) = VariableAddress[pfn] : -# 885| mu0_17(..(*)(..)) = Store : &:r0_16, r0_15 -# 885| r0_18(glval<..(*)(..)>) = CopyValue : r0_16 -# 886| v0_19(void) = NoOp : -# 883| v0_20(void) = ReturnVoid : -# 883| v0_21(void) = UnmodeledUse : mu* -# 883| v0_22(void) = ExitFunction : +# 885| r0_12(glval) = VariableAddress[p] : +# 885| r0_13(void *) = Load : &:r0_12, ~mu0_2 +# 885| r0_14(..(*)(..)) = Convert : r0_13 +# 885| r0_15(glval<..(*)(..)>) = VariableAddress[pfn] : +# 885| mu0_16(..(*)(..)) = Store : &:r0_15, r0_14 +# 886| v0_17(void) = NoOp : +# 883| v0_18(void) = ReturnVoid : +# 883| v0_19(void) = UnmodeledUse : mu* +# 883| v0_20(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4619,7 +4453,6 @@ ir.cpp: # 968| r1_0(int) = Constant[5] : # 968| r1_1(glval) = VariableAddress[x] : # 968| mu1_2(int) = Store : &:r1_1, r1_0 -# 968| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 6 # 970| Block 2 @@ -4643,7 +4476,6 @@ ir.cpp: # 971| r3_0(int) = Constant[7] : # 971| r3_1(glval) = VariableAddress[y] : # 971| mu3_2(int) = Store : &:r3_1, r3_0 -# 971| r3_3(glval) = CopyValue : r3_1 #-----| Goto -> Block 6 # 973| Block 4 @@ -4666,7 +4498,6 @@ ir.cpp: # 974| r5_2(int *) = Load : &:r5_1, ~mu0_2 # 974| r5_3(glval) = CopyValue : r5_2 # 974| mu5_4(int) = Store : &:r5_3, r5_0 -# 974| r5_5(glval) = CopyValue : r5_3 #-----| Goto -> Block 6 # 976| Block 6 @@ -4804,7 +4635,6 @@ ir.cpp: # 995| r1_1(int) = Load : &:r1_0, ~mu0_2 # 995| r1_2(glval) = VariableAddress[w] : # 995| mu1_3(int) = Store : &:r1_2, r1_1 -# 995| r1_4(glval) = CopyValue : r1_2 #-----| Goto -> Block 3 # 997| Block 2 @@ -4812,7 +4642,6 @@ ir.cpp: # 997| r2_1(int) = Load : &:r2_0, ~mu0_2 # 997| r2_2(glval) = VariableAddress[w] : # 997| mu2_3(int) = Store : &:r2_2, r2_1 -# 997| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 999| Block 3 @@ -5608,7 +5437,6 @@ ir.cpp: # 1130| r2_2(int) = Constant[1] : # 1130| r2_3(int) = Add : r2_1, r2_2 # 1130| mu2_4(int) = Store : &:r2_0, r2_3 -# 1130| r2_5(glval) = CopyValue : r2_0 #-----| Goto (back edge) -> Block 1 # 1130| Block 3 @@ -5674,7 +5502,6 @@ ir.cpp: # 1140| r6_4(int) = Load : &:r6_3, ~mu0_2 # 1140| r6_5(glval) = VariableAddress[x] : # 1140| mu6_6(int) = Store : &:r6_5, r6_4 -# 1140| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 1140| Block 7 @@ -5693,7 +5520,6 @@ ir.cpp: # 1142| r8_0(int) = Constant[7] : # 1142| r8_1(glval) = VariableAddress[x] : # 1142| mu8_2(int) = Store : &:r8_1, r8_0 -# 1142| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 13 # 1144| Block 9 @@ -5770,30 +5596,28 @@ ir.cpp: # 1156| r0_34(int) = Load : &:r0_33, ~mu0_2 # 1156| r0_35(glval) = PointerAdd[4] : r0_32, r0_34 # 1156| mu0_36(int) = Store : &:r0_35, r0_31 -# 1156| r0_37(glval) = CopyValue : r0_35 -# 1157| r0_38(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : -# 1157| r0_39(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1157| r0_40(__attribute((vector_size(16UL))) int) = Load : &:r0_39, ~mu0_2 -# 1157| r0_41(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1157| r0_42(__attribute((vector_size(16UL))) int) = Load : &:r0_41, ~mu0_2 -#-----| r0_43(int) = Constant[3] : -# 1157| r0_44(int) = Constant[2] : -# 1157| r0_45(int) = Constant[1] : -# 1157| r0_46(int) = Constant[0] : -# 1157| r0_47(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_40, 1:r0_42, 2:r0_43, 3:r0_44, 4:r0_45, 5:r0_46 -# 1157| mu0_48(__attribute((vector_size(16UL))) int) = Store : &:r0_38, r0_47 -# 1158| r0_49(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1158| r0_50(__attribute((vector_size(16UL))) int) = Load : &:r0_49, ~mu0_2 -# 1158| r0_51(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : -# 1158| r0_52(__attribute((vector_size(16UL))) int) = Load : &:r0_51, ~mu0_2 -# 1158| r0_53(__attribute((vector_size(16UL))) int) = Add : r0_50, r0_52 -# 1158| r0_54(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1158| mu0_55(__attribute((vector_size(16UL))) int) = Store : &:r0_54, r0_53 -# 1158| r0_56(glval<__attribute((vector_size(16UL))) int>) = CopyValue : r0_54 -# 1159| v0_57(void) = NoOp : -# 1153| v0_58(void) = ReturnVoid : -# 1153| v0_59(void) = UnmodeledUse : mu* -# 1153| v0_60(void) = ExitFunction : +# 1157| r0_37(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : +# 1157| r0_38(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1157| r0_39(__attribute((vector_size(16UL))) int) = Load : &:r0_38, ~mu0_2 +# 1157| r0_40(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1157| r0_41(__attribute((vector_size(16UL))) int) = Load : &:r0_40, ~mu0_2 +#-----| r0_42(int) = Constant[3] : +# 1157| r0_43(int) = Constant[2] : +# 1157| r0_44(int) = Constant[1] : +# 1157| r0_45(int) = Constant[0] : +# 1157| r0_46(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_39, 1:r0_41, 2:r0_42, 3:r0_43, 4:r0_44, 5:r0_45 +# 1157| mu0_47(__attribute((vector_size(16UL))) int) = Store : &:r0_37, r0_46 +# 1158| r0_48(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1158| r0_49(__attribute((vector_size(16UL))) int) = Load : &:r0_48, ~mu0_2 +# 1158| r0_50(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : +# 1158| r0_51(__attribute((vector_size(16UL))) int) = Load : &:r0_50, ~mu0_2 +# 1158| r0_52(__attribute((vector_size(16UL))) int) = Add : r0_49, r0_51 +# 1158| r0_53(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1158| mu0_54(__attribute((vector_size(16UL))) int) = Store : &:r0_53, r0_52 +# 1159| v0_55(void) = NoOp : +# 1153| v0_56(void) = ReturnVoid : +# 1153| v0_57(void) = UnmodeledUse : mu* +# 1153| v0_58(void) = ExitFunction : # 1163| int ModeledCallTarget(int) # 1163| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 9f13acbb1ff..ff8c2b30a05 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -214,7 +214,6 @@ ssa.cpp: # 70| r1_6(glval) = CopyValue : r1_2 # 70| m1_7(char) = Store : &:r1_6, r1_0 # 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7 -# 70| r1_9(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -264,23 +263,20 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 80| r1_3(glval) = CopyValue : r1_1 -# 81| r1_4(int) = Constant[4] : -# 81| r1_5(glval) = VariableAddress[y] : -# 81| m1_6(int) = Store : &:r1_5, r1_4 -# 81| r1_7(glval) = CopyValue : r1_5 +# 81| r1_3(int) = Constant[4] : +# 81| r1_4(glval) = VariableAddress[y] : +# 81| m1_5(int) = Store : &:r1_4, r1_3 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 -# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -501,7 +497,6 @@ ssa.cpp: # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| m1_4(int) = Store : &:r1_3, r1_1 # 125| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 125| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -511,7 +506,6 @@ ssa.cpp: # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| m2_4(int) = Store : &:r2_3, r2_1 # 128| m2_5(Point) = Chi : total:m0_18, partial:m2_4 -# 128| r2_6(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -565,7 +559,6 @@ ssa.cpp: # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| m1_4(int) = Store : &:r1_3, r1_1 # 137| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 137| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -573,7 +566,6 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| m2_3(Point) = Store : &:r2_2, r2_1 -# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -623,7 +615,6 @@ ssa.cpp: # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| m1_4(int) = Store : &:r1_3, r1_1 # 148| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 148| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -631,7 +622,6 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| m2_3(Point) = Store : &:r2_2, r2_1 -# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -680,7 +670,6 @@ ssa.cpp: # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| m1_5(int) = Store : &:r1_4, r1_1 # 159| m1_6(Rect) = Chi : total:m0_18, partial:m1_5 -# 159| r1_7(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -688,7 +677,6 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| m2_3(Rect) = Store : &:r2_2, r2_1 -# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -723,22 +711,19 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| m0_17(int) = Store : &:r0_16, r0_14 -# 174| r0_18(glval) = CopyValue : r0_16 -# 175| r0_19(glval) = VariableAddress[w] : -# 175| r0_20(glval) = FieldAddress[f] : r0_19 -# 175| r0_21(int) = Load : &:r0_20, m0_17 -# 175| r0_22(glval) = VariableAddress[a] : -# 175| m0_23(int) = Store : &:r0_22, r0_21 -# 175| r0_24(glval) = CopyValue : r0_22 -# 176| r0_25(glval) = VariableAddress[w] : -# 176| r0_26(Wrapper) = Load : &:r0_25, ~m0_17 -# 176| r0_27(glval) = VariableAddress[x] : -# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 -# 176| r0_29(glval) = CopyValue : r0_27 -# 177| v0_30(void) = NoOp : -# 171| v0_31(void) = ReturnVoid : -# 171| v0_32(void) = UnmodeledUse : mu* -# 171| v0_33(void) = ExitFunction : +# 175| r0_18(glval) = VariableAddress[w] : +# 175| r0_19(glval) = FieldAddress[f] : r0_18 +# 175| r0_20(int) = Load : &:r0_19, m0_17 +# 175| r0_21(glval) = VariableAddress[a] : +# 175| m0_22(int) = Store : &:r0_21, r0_20 +# 176| r0_23(glval) = VariableAddress[w] : +# 176| r0_24(Wrapper) = Load : &:r0_23, ~m0_17 +# 176| r0_25(glval) = VariableAddress[x] : +# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 +# 177| v0_27(void) = NoOp : +# 171| v0_28(void) = ReturnVoid : +# 171| v0_29(void) = UnmodeledUse : mu* +# 171| v0_30(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -819,24 +804,22 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 200| r0_30(glval) = CopyValue : r0_26 -# 201| r0_31(glval) = FunctionAddress[abs] : -# 201| r0_32(glval) = VariableAddress[x] : -# 201| r0_33(int) = Load : &:r0_32, m0_8 -# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 -# 201| r0_35(glval) = VariableAddress[ret] : -# 201| r0_36(int) = Load : &:r0_35, m0_29 -# 201| r0_37(int) = Add : r0_36, r0_34 -# 201| m0_38(int) = Store : &:r0_35, r0_37 -# 201| r0_39(glval) = CopyValue : r0_35 -# 202| r0_40(glval) = VariableAddress[#return] : -# 202| r0_41(glval) = VariableAddress[ret] : -# 202| r0_42(int) = Load : &:r0_41, m0_38 -# 202| m0_43(int) = Store : &:r0_40, r0_42 -# 198| r0_44(glval) = VariableAddress[#return] : -# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 -# 198| v0_46(void) = UnmodeledUse : mu* -# 198| v0_47(void) = ExitFunction : +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index fd21c3f2d71..8204cdad960 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -216,7 +216,6 @@ ssa.cpp: # 70| m1_5(char *) = Store : &:r1_1, r1_4 # 70| r1_6(glval) = CopyValue : r1_2 # 70| mu1_7(char) = Store : &:r1_6, r1_0 -# 70| r1_8(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -265,23 +264,20 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 80| r1_3(glval) = CopyValue : r1_1 -# 81| r1_4(int) = Constant[4] : -# 81| r1_5(glval) = VariableAddress[y] : -# 81| m1_6(int) = Store : &:r1_5, r1_4 -# 81| r1_7(glval) = CopyValue : r1_5 +# 81| r1_3(int) = Constant[4] : +# 81| r1_4(glval) = VariableAddress[y] : +# 81| m1_5(int) = Store : &:r1_4, r1_3 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 -# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -486,7 +482,6 @@ ssa.cpp: # 125| r1_2(glval) = VariableAddress[a] : # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| mu1_4(int) = Store : &:r1_3, r1_1 -# 125| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -495,7 +490,6 @@ ssa.cpp: # 128| r2_2(glval) = VariableAddress[a] : # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| mu2_4(int) = Store : &:r2_3, r2_1 -# 128| r2_5(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -544,7 +538,6 @@ ssa.cpp: # 137| r1_2(glval) = VariableAddress[a] : # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| mu1_4(int) = Store : &:r1_3, r1_1 -# 137| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -552,7 +545,6 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| mu2_3(Point) = Store : &:r2_2, r2_1 -# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -597,7 +589,6 @@ ssa.cpp: # 148| r1_2(glval) = VariableAddress[a] : # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| mu1_4(int) = Store : &:r1_3, r1_1 -# 148| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -605,7 +596,6 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| mu2_3(Point) = Store : &:r2_2, r2_1 -# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -650,7 +640,6 @@ ssa.cpp: # 159| r1_3(glval) = FieldAddress[topLeft] : r1_2 # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| mu1_5(int) = Store : &:r1_4, r1_1 -# 159| r1_6(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -658,7 +647,6 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| mu2_3(Rect) = Store : &:r2_2, r2_1 -# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -692,22 +680,19 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| mu0_17(int) = Store : &:r0_16, r0_14 -# 174| r0_18(glval) = CopyValue : r0_16 -# 175| r0_19(glval) = VariableAddress[w] : -# 175| r0_20(glval) = FieldAddress[f] : r0_19 -# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 -# 175| r0_22(glval) = VariableAddress[a] : -# 175| m0_23(int) = Store : &:r0_22, r0_21 -# 175| r0_24(glval) = CopyValue : r0_22 -# 176| r0_25(glval) = VariableAddress[w] : -# 176| r0_26(Wrapper) = Load : &:r0_25, ~mu0_2 -# 176| r0_27(glval) = VariableAddress[x] : -# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 -# 176| r0_29(glval) = CopyValue : r0_27 -# 177| v0_30(void) = NoOp : -# 171| v0_31(void) = ReturnVoid : -# 171| v0_32(void) = UnmodeledUse : mu* -# 171| v0_33(void) = ExitFunction : +# 175| r0_18(glval) = VariableAddress[w] : +# 175| r0_19(glval) = FieldAddress[f] : r0_18 +# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 175| r0_21(glval) = VariableAddress[a] : +# 175| m0_22(int) = Store : &:r0_21, r0_20 +# 176| r0_23(glval) = VariableAddress[w] : +# 176| r0_24(Wrapper) = Load : &:r0_23, ~mu0_2 +# 176| r0_25(glval) = VariableAddress[x] : +# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 +# 177| v0_27(void) = NoOp : +# 171| v0_28(void) = ReturnVoid : +# 171| v0_29(void) = UnmodeledUse : mu* +# 171| v0_30(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -782,24 +767,22 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 200| r0_30(glval) = CopyValue : r0_26 -# 201| r0_31(glval) = FunctionAddress[abs] : -# 201| r0_32(glval) = VariableAddress[x] : -# 201| r0_33(int) = Load : &:r0_32, m0_8 -# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 -# 201| r0_35(glval) = VariableAddress[ret] : -# 201| r0_36(int) = Load : &:r0_35, m0_29 -# 201| r0_37(int) = Add : r0_36, r0_34 -# 201| m0_38(int) = Store : &:r0_35, r0_37 -# 201| r0_39(glval) = CopyValue : r0_35 -# 202| r0_40(glval) = VariableAddress[#return] : -# 202| r0_41(glval) = VariableAddress[ret] : -# 202| r0_42(int) = Load : &:r0_41, m0_38 -# 202| m0_43(int) = Store : &:r0_40, r0_42 -# 198| r0_44(glval) = VariableAddress[#return] : -# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 -# 198| v0_46(void) = UnmodeledUse : mu* -# 198| v0_47(void) = ExitFunction : +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 589678d9f77..9e8588507ff 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -26,7 +26,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | Chi: call to C | | ms_try_mix.cpp:48:10:48:13 | Chi: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index bb312fa7691..1bcffed0736 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -4,7 +4,6 @@ missingOperand | condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | | condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | -| misc.c:220:3:223:3 | CopyValue: ... = ... | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -49,13 +48,13 @@ instructionWithoutSuccessor | misc.c:222:10:222:10 | Store: 2 | | ms_assume.cpp:20:12:20:12 | Constant: (bool)... | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_except.cpp:7:13:7:17 | CopyValue: ... = ... | +| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | | ms_try_except.cpp:9:19:9:19 | Load: j | -| ms_try_except.cpp:10:13:10:17 | CopyValue: ... = ... | -| ms_try_except.cpp:14:13:14:17 | CopyValue: ... = ... | -| ms_try_except.cpp:17:13:17:17 | CopyValue: ... = ... | +| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | +| ms_try_except.cpp:14:13:14:17 | Store: ... = ... | +| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | -| ms_try_except.cpp:20:9:20:13 | CopyValue: ... = ... | +| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | | ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | | ms_try_mix.cpp:18:16:18:19 | CallSideEffect: call to C | @@ -77,7 +76,7 @@ instructionWithoutSuccessor | static_init_templates.cpp:97:27:97:36 | Convert: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 0f8088f9a25..d064a1264ec 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -35,7 +35,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | | ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors From 11da4a53285b6fc93afc6e9c8c88bdc6644118d4 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 24 Oct 2019 15:17:16 +0200 Subject: [PATCH 047/232] C++: Accept test results for GVN and sign analysis --- .../signanalysis/SignAnalysis.expected | 28 --- .../GlobalValueNumbering/ir_gvn.expected | 234 ++++++++---------- 2 files changed, 101 insertions(+), 161 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected index 4dc280b6ca9..0c8f9c1cff1 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected @@ -13,7 +13,6 @@ | bounded_bounds.c:16:12:16:12 | Load: x | negative strictlyNegative | | bounded_bounds.c:16:12:16:12 | Store: x | negative strictlyNegative | | inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive | -| inline_assembly.c:10:3:10:7 | CopyValue: ... = ... | positive strictlyPositive | | inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive | | inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive | | inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive | @@ -28,10 +27,8 @@ | minmax.c:18:37:18:37 | Load: x | positive strictlyPositive | | minmax.c:18:40:18:40 | Load: y | positive strictlyPositive | | minmax.c:18:43:18:43 | Load: z | positive strictlyPositive | -| minmax.c:20:2:24:3 | CopyValue: ... = ... | positive | | minmax.c:20:2:24:3 | Store: ... = ... | positive | | minmax.c:20:6:24:3 | CopyValue: (statement expression) | positive | -| minmax.c:22:18:22:22 | CopyValue: ... = ... | positive strictlyPositive | | minmax.c:22:18:22:22 | Store: ... = ... | positive strictlyPositive | | minmax.c:22:22:22:22 | Load: x | positive strictlyPositive | | minmax.c:23:3:23:3 | Load: t | positive | @@ -40,7 +37,6 @@ | minmax.c:26:40:26:40 | Load: y | positive strictlyPositive | | minmax.c:26:43:26:43 | Load: z | positive | | test.c:7:10:7:10 | Phi: p | positive | -| test.c:8:5:8:19 | CopyValue: ... = ... | positive strictlyPositive | | test.c:8:5:8:19 | Store: ... = ... | positive strictlyPositive | | test.c:8:13:8:17 | Load: count | positive | | test.c:8:13:8:19 | Add: ... + ... | positive strictlyPositive | @@ -48,7 +44,6 @@ | test.c:10:10:10:14 | Load: count | positive | | test.c:10:10:10:14 | Store: count | positive | | test.c:15:10:15:10 | Phi: p | positive | -| test.c:16:5:16:26 | CopyValue: ... = ... | positive | | test.c:16:5:16:26 | Store: ... = ... | positive | | test.c:16:13:16:26 | Rem: ... % ... | positive | | test.c:16:14:16:18 | Load: count | positive | @@ -62,7 +57,6 @@ | test.c:24:5:24:11 | Constant: ... ++ | positive strictlyPositive | | test.c:24:5:24:11 | Load: ... ++ | positive | | test.c:24:5:24:11 | Store: ... ++ | positive strictlyPositive | -| test.c:25:5:25:22 | CopyValue: ... = ... | positive | | test.c:25:5:25:22 | Store: ... = ... | positive | | test.c:25:13:25:17 | Load: count | positive strictlyPositive | | test.c:25:13:25:22 | Rem: ... % ... | positive | @@ -73,7 +67,6 @@ | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:19:33:19 | Constant: 2 | positive strictlyPositive | -| test.c:33:22:33:28 | CopyValue: ... = ... | positive strictlyPositive | | test.c:33:22:33:28 | Store: ... = ... | positive strictlyPositive | | test.c:33:26:33:26 | Load: i | positive | | test.c:33:26:33:28 | Add: ... + ... | positive strictlyPositive | @@ -108,7 +101,6 @@ | test.c:51:15:51:17 | Add: ... + ... | positive strictlyPositive | | test.c:51:17:51:17 | Constant: 2 | positive strictlyPositive | | test.c:51:21:51:21 | Constant: 4 | positive strictlyPositive | -| test.c:51:24:51:30 | CopyValue: ... = ... | positive strictlyPositive | | test.c:51:24:51:30 | Store: ... = ... | positive strictlyPositive | | test.c:51:28:51:28 | Load: i | positive | | test.c:51:28:51:30 | Add: ... + ... | positive strictlyPositive | @@ -467,7 +459,6 @@ | test.c:343:5:343:7 | Constant: ... ++ | positive strictlyPositive | | test.c:343:5:343:7 | Load: ... ++ | positive | | test.c:343:5:343:7 | Store: ... ++ | positive strictlyPositive | -| test.c:345:3:345:7 | CopyValue: ... = ... | positive strictlyPositive | | test.c:345:3:345:7 | Store: ... = ... | positive strictlyPositive | | test.c:345:7:345:7 | Load: i | positive strictlyPositive | | test.c:346:7:346:7 | Load: x | positive | @@ -483,7 +474,6 @@ | test.c:356:36:356:37 | Uninitialized: definition of y6 | positive | | test.c:356:40:356:41 | Uninitialized: definition of y7 | positive | | test.c:356:44:356:45 | Uninitialized: definition of y8 | positive | -| test.c:357:3:357:23 | CopyValue: ... = ... | positive | | test.c:357:3:357:23 | Store: ... = ... | positive | | test.c:357:8:357:8 | Load: x | positive | | test.c:357:8:357:23 | Load: ... ? ... : ... | positive | @@ -493,7 +483,6 @@ | test.c:357:12:357:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:357:18:357:18 | Load: x | positive | | test.c:357:22:357:23 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:358:3:358:24 | CopyValue: ... = ... | positive | | test.c:358:3:358:24 | Store: ... = ... | positive | | test.c:358:8:358:8 | Load: x | positive | | test.c:358:8:358:24 | Load: ... ? ... : ... | positive | @@ -505,7 +494,6 @@ | test.c:358:24:358:24 | Load: x | positive | | test.c:365:7:365:7 | Load: x | positive | | test.c:365:11:365:13 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:366:5:366:15 | CopyValue: ... = ... | positive | | test.c:366:5:366:15 | Store: ... = ... | positive | | test.c:366:10:366:10 | Load: x | positive | | test.c:366:10:366:15 | Load: ... ? ... : ... | positive | @@ -513,7 +501,6 @@ | test.c:366:10:366:15 | Store: ... ? ... : ... | positive | | test.c:366:10:366:15 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:366:15:366:15 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:367:5:367:17 | CopyValue: ... = ... | positive | | test.c:367:5:367:17 | Store: ... = ... | positive | | test.c:367:10:367:10 | Load: x | positive | | test.c:367:10:367:17 | Load: ... ? ... : ... | positive | @@ -521,7 +508,6 @@ | test.c:367:10:367:17 | Store: ... ? ... : ... | positive | | test.c:367:10:367:17 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:368:5:368:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive | | test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -529,7 +515,6 @@ | test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive | | test.c:368:13:368:13 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:368:19:368:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:369:5:369:36 | CopyValue: ... = ... | positive strictlyPositive | | test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive | | test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive | @@ -539,7 +524,6 @@ | test.c:369:27:369:29 | Add: ... + ... | positive strictlyPositive | | test.c:369:29:369:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:369:36:369:36 | Constant: 5 | positive strictlyPositive | -| test.c:370:5:370:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive | | test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -549,7 +533,6 @@ | test.c:370:27:370:29 | Add: ... + ... | positive strictlyPositive | | test.c:370:29:370:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:370:36:370:38 | Constant: 500 | positive strictlyPositive | -| test.c:371:5:371:39 | CopyValue: ... = ... | positive strictlyPositive | | test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive | | test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive | @@ -587,7 +570,6 @@ | test.c:378:24:378:25 | Uninitialized: definition of y3 | positive | | test.c:378:28:378:29 | Uninitialized: definition of y4 | positive | | test.c:378:32:378:33 | Uninitialized: definition of y5 | positive | -| test.c:379:3:379:24 | CopyValue: ... = ... | positive strictlyPositive | | test.c:379:3:379:24 | Store: ... = ... | positive strictlyPositive | | test.c:379:8:379:8 | Load: x | positive | | test.c:379:8:379:24 | Load: ... ? ... : ... | positive strictlyPositive | @@ -597,7 +579,6 @@ | test.c:379:12:379:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:379:18:379:18 | Load: x | positive strictlyPositive | | test.c:379:22:379:24 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:380:3:380:25 | CopyValue: ... = ... | positive strictlyPositive | | test.c:380:3:380:25 | Store: ... = ... | positive strictlyPositive | | test.c:380:8:380:8 | Load: x | positive | | test.c:380:8:380:25 | Load: ... ? ... : ... | positive strictlyPositive | @@ -607,18 +588,14 @@ | test.c:380:13:380:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:19:380:21 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:25:380:25 | Load: x | positive strictlyPositive | -| test.c:381:3:381:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:381:3:381:11 | Store: ... = ... | positive strictlyPositive | | test.c:381:8:381:11 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:382:3:382:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:382:3:382:11 | Store: ... = ... | positive strictlyPositive | | test.c:382:8:382:11 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:383:3:383:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:383:3:383:11 | Store: ... = ... | positive strictlyPositive | | test.c:383:8:383:11 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:384:7:384:7 | Load: x | positive | | test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:385:5:385:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive | | test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -626,7 +603,6 @@ | test.c:385:11:385:15 | Sub: ... - ... | positive | | test.c:385:13:385:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:386:5:386:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive | | test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -634,7 +610,6 @@ | test.c:386:11:386:15 | Sub: ... - ... | positive | | test.c:386:13:386:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:386:21:386:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:387:5:387:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive | | test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -669,7 +644,6 @@ | test.c:394:34:394:36 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:395:16:395:17 | Uninitialized: definition of y1 | positive | | test.c:396:16:396:17 | Uninitialized: definition of y2 | positive | -| test.c:397:3:397:15 | CopyValue: ... = ... | positive strictlyPositive | | test.c:397:3:397:15 | Store: ... = ... | positive strictlyPositive | | test.c:397:9:397:11 | Add: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive | @@ -677,13 +651,11 @@ | test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive | | test.c:397:9:397:14 | CopyValue: ... , ... | positive strictlyPositive | | test.c:397:14:397:14 | Load: y | positive strictlyPositive | -| test.c:398:3:398:23 | CopyValue: ... = ... | positive strictlyPositive | | test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive | | test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive | -| test.c:398:9:398:19 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 4bc9f90cc60..ec6f300a957 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -40,40 +40,34 @@ test.cpp: # 5| valnum = r0_7 # 5| m0_19(int) = Store : &:r0_18, r0_17 # 5| valnum = r0_17 -# 5| r0_20(glval) = CopyValue : r0_18 -# 5| valnum = r0_7 -# 6| r0_21(glval) = VariableAddress[p0] : +# 6| r0_20(glval) = VariableAddress[p0] : # 6| valnum = r0_3 -# 6| r0_22(int) = Load : &:r0_21, m0_4 +# 6| r0_21(int) = Load : &:r0_20, m0_4 # 6| valnum = m0_4 -# 6| r0_23(glval) = VariableAddress[p1] : +# 6| r0_22(glval) = VariableAddress[p1] : # 6| valnum = r0_5 -# 6| r0_24(int) = Load : &:r0_23, m0_6 +# 6| r0_23(int) = Load : &:r0_22, m0_6 # 6| valnum = m0_6 -# 6| r0_25(int) = Add : r0_22, r0_24 +# 6| r0_24(int) = Add : r0_21, r0_23 # 6| valnum = r0_17 -# 6| r0_26(glval) = VariableAddress[x] : +# 6| r0_25(glval) = VariableAddress[x] : # 6| valnum = r0_7 -# 6| m0_27(int) = Store : &:r0_26, r0_25 +# 6| m0_26(int) = Store : &:r0_25, r0_24 # 6| valnum = r0_17 -# 6| r0_28(glval) = CopyValue : r0_26 -# 6| valnum = r0_7 -# 7| r0_29(glval) = VariableAddress[x] : +# 7| r0_27(glval) = VariableAddress[x] : # 7| valnum = r0_7 -# 7| r0_30(int) = Load : &:r0_29, m0_27 +# 7| r0_28(int) = Load : &:r0_27, m0_26 # 7| valnum = r0_17 -# 7| r0_31(glval) = VariableAddress[y] : +# 7| r0_29(glval) = VariableAddress[y] : # 7| valnum = r0_9 -# 7| m0_32(int) = Store : &:r0_31, r0_30 +# 7| m0_30(int) = Store : &:r0_29, r0_28 # 7| valnum = r0_17 -# 7| r0_33(glval) = CopyValue : r0_31 -# 7| valnum = r0_9 -# 8| v0_34(void) = NoOp : -# 1| r0_35(glval) = VariableAddress[#return] : +# 8| v0_31(void) = NoOp : +# 1| r0_32(glval) = VariableAddress[#return] : # 1| valnum = unique -# 1| v0_36(void) = ReturnValue : &:r0_35 -# 1| v0_37(void) = UnmodeledUse : mu* -# 1| v0_38(void) = ExitFunction : +# 1| v0_33(void) = ReturnValue : &:r0_32 +# 1| v0_34(void) = UnmodeledUse : mu* +# 1| v0_35(void) = ExitFunction : # 12| int test01(int, int) # 12| Block 0 @@ -122,46 +116,40 @@ test.cpp: # 16| valnum = r0_7 # 16| m0_22(int) = Store : &:r0_21, r0_20 # 16| valnum = r0_20 -# 16| r0_23(glval) = CopyValue : r0_21 -# 16| valnum = r0_7 -# 17| r0_24(glval) = VariableAddress[p0] : +# 17| r0_23(glval) = VariableAddress[p0] : # 17| valnum = r0_3 -# 17| r0_25(int) = Load : &:r0_24, m0_4 +# 17| r0_24(int) = Load : &:r0_23, m0_4 # 17| valnum = m0_4 -# 17| r0_26(glval) = VariableAddress[p1] : +# 17| r0_25(glval) = VariableAddress[p1] : # 17| valnum = r0_5 -# 17| r0_27(int) = Load : &:r0_26, m0_6 +# 17| r0_26(int) = Load : &:r0_25, m0_6 # 17| valnum = m0_6 -# 17| r0_28(int) = Add : r0_25, r0_27 +# 17| r0_27(int) = Add : r0_24, r0_26 # 17| valnum = r0_17 -# 17| r0_29(glval) = VariableAddress[global01] : +# 17| r0_28(glval) = VariableAddress[global01] : # 17| valnum = r0_18 -# 17| r0_30(int) = Load : &:r0_29, ~m0_1 +# 17| r0_29(int) = Load : &:r0_28, ~m0_1 # 17| valnum = unique -# 17| r0_31(int) = Add : r0_28, r0_30 -# 17| valnum = r0_31 -# 17| r0_32(glval) = VariableAddress[x] : +# 17| r0_30(int) = Add : r0_27, r0_29 +# 17| valnum = r0_30 +# 17| r0_31(glval) = VariableAddress[x] : # 17| valnum = r0_7 -# 17| m0_33(int) = Store : &:r0_32, r0_31 -# 17| valnum = r0_31 -# 17| r0_34(glval) = CopyValue : r0_32 -# 17| valnum = r0_7 -# 18| r0_35(glval) = VariableAddress[x] : +# 17| m0_32(int) = Store : &:r0_31, r0_30 +# 17| valnum = r0_30 +# 18| r0_33(glval) = VariableAddress[x] : # 18| valnum = r0_7 -# 18| r0_36(int) = Load : &:r0_35, m0_33 -# 18| valnum = r0_31 -# 18| r0_37(glval) = VariableAddress[y] : +# 18| r0_34(int) = Load : &:r0_33, m0_32 +# 18| valnum = r0_30 +# 18| r0_35(glval) = VariableAddress[y] : # 18| valnum = r0_9 -# 18| m0_38(int) = Store : &:r0_37, r0_36 -# 18| valnum = r0_31 -# 18| r0_39(glval) = CopyValue : r0_37 -# 18| valnum = r0_9 -# 19| v0_40(void) = NoOp : -# 12| r0_41(glval) = VariableAddress[#return] : +# 18| m0_36(int) = Store : &:r0_35, r0_34 +# 18| valnum = r0_30 +# 19| v0_37(void) = NoOp : +# 12| r0_38(glval) = VariableAddress[#return] : # 12| valnum = unique -# 12| v0_42(void) = ReturnValue : &:r0_41 -# 12| v0_43(void) = UnmodeledUse : mu* -# 12| v0_44(void) = ExitFunction : +# 12| v0_39(void) = ReturnValue : &:r0_38 +# 12| v0_40(void) = UnmodeledUse : mu* +# 12| v0_41(void) = ExitFunction : # 25| int test02(int, int) # 25| Block 0 @@ -210,53 +198,47 @@ test.cpp: # 29| valnum = r0_7 # 29| m0_22(int) = Store : &:r0_21, r0_20 # 29| valnum = r0_20 -# 29| r0_23(glval) = CopyValue : r0_21 -# 29| valnum = r0_7 -# 30| r0_24(glval) = FunctionAddress[change_global02] : +# 30| r0_23(glval) = FunctionAddress[change_global02] : # 30| valnum = unique -# 30| v0_25(void) = Call : func:r0_24 -# 30| m0_26(unknown) = ^CallSideEffect : ~m0_1 +# 30| v0_24(void) = Call : func:r0_23 +# 30| m0_25(unknown) = ^CallSideEffect : ~m0_1 # 30| valnum = unique -# 30| m0_27(unknown) = Chi : total:m0_1, partial:m0_26 +# 30| m0_26(unknown) = Chi : total:m0_1, partial:m0_25 # 30| valnum = unique -# 31| r0_28(glval) = VariableAddress[p0] : +# 31| r0_27(glval) = VariableAddress[p0] : # 31| valnum = r0_3 -# 31| r0_29(int) = Load : &:r0_28, m0_4 +# 31| r0_28(int) = Load : &:r0_27, m0_4 # 31| valnum = m0_4 -# 31| r0_30(glval) = VariableAddress[p1] : +# 31| r0_29(glval) = VariableAddress[p1] : # 31| valnum = r0_5 -# 31| r0_31(int) = Load : &:r0_30, m0_6 +# 31| r0_30(int) = Load : &:r0_29, m0_6 # 31| valnum = m0_6 -# 31| r0_32(int) = Add : r0_29, r0_31 +# 31| r0_31(int) = Add : r0_28, r0_30 # 31| valnum = r0_17 -# 31| r0_33(glval) = VariableAddress[global02] : +# 31| r0_32(glval) = VariableAddress[global02] : # 31| valnum = r0_18 -# 31| r0_34(int) = Load : &:r0_33, ~m0_27 +# 31| r0_33(int) = Load : &:r0_32, ~m0_26 # 31| valnum = unique -# 31| r0_35(int) = Add : r0_32, r0_34 -# 31| valnum = r0_35 -# 31| r0_36(glval) = VariableAddress[x] : +# 31| r0_34(int) = Add : r0_31, r0_33 +# 31| valnum = r0_34 +# 31| r0_35(glval) = VariableAddress[x] : # 31| valnum = r0_7 -# 31| m0_37(int) = Store : &:r0_36, r0_35 -# 31| valnum = r0_35 -# 31| r0_38(glval) = CopyValue : r0_36 -# 31| valnum = r0_7 -# 32| r0_39(glval) = VariableAddress[x] : +# 31| m0_36(int) = Store : &:r0_35, r0_34 +# 31| valnum = r0_34 +# 32| r0_37(glval) = VariableAddress[x] : # 32| valnum = r0_7 -# 32| r0_40(int) = Load : &:r0_39, m0_37 -# 32| valnum = r0_35 -# 32| r0_41(glval) = VariableAddress[y] : +# 32| r0_38(int) = Load : &:r0_37, m0_36 +# 32| valnum = r0_34 +# 32| r0_39(glval) = VariableAddress[y] : # 32| valnum = r0_9 -# 32| m0_42(int) = Store : &:r0_41, r0_40 -# 32| valnum = r0_35 -# 32| r0_43(glval) = CopyValue : r0_41 -# 32| valnum = r0_9 -# 33| v0_44(void) = NoOp : -# 25| r0_45(glval) = VariableAddress[#return] : +# 32| m0_40(int) = Store : &:r0_39, r0_38 +# 32| valnum = r0_34 +# 33| v0_41(void) = NoOp : +# 25| r0_42(glval) = VariableAddress[#return] : # 25| valnum = unique -# 25| v0_46(void) = ReturnValue : &:r0_45 -# 25| v0_47(void) = UnmodeledUse : mu* -# 25| v0_48(void) = ExitFunction : +# 25| v0_43(void) = ReturnValue : &:r0_42 +# 25| v0_44(void) = UnmodeledUse : mu* +# 25| v0_45(void) = ExitFunction : # 39| int test03(int, int, int*) # 39| Block 0 @@ -309,60 +291,52 @@ test.cpp: # 43| valnum = r0_9 # 43| m0_24(int) = Store : &:r0_23, r0_22 # 43| valnum = r0_22 -# 43| r0_25(glval) = CopyValue : r0_23 -# 43| valnum = r0_9 -# 44| r0_26(int) = Constant[0] : -# 44| valnum = r0_26 -# 44| r0_27(glval) = VariableAddress[p2] : +# 44| r0_25(int) = Constant[0] : +# 44| valnum = r0_25 +# 44| r0_26(glval) = VariableAddress[p2] : # 44| valnum = r0_7 -# 44| r0_28(int *) = Load : &:r0_27, m0_8 +# 44| r0_27(int *) = Load : &:r0_26, m0_8 # 44| valnum = m0_8 -# 44| r0_29(glval) = CopyValue : r0_28 +# 44| r0_28(glval) = CopyValue : r0_27 # 44| valnum = m0_8 -# 44| m0_30(int) = Store : &:r0_29, r0_26 -# 44| valnum = r0_26 -# 44| m0_31(unknown) = Chi : total:m0_1, partial:m0_30 +# 44| m0_29(int) = Store : &:r0_28, r0_25 +# 44| valnum = r0_25 +# 44| m0_30(unknown) = Chi : total:m0_1, partial:m0_29 # 44| valnum = unique -# 44| r0_32(glval) = CopyValue : r0_29 -# 44| valnum = m0_8 -# 45| r0_33(glval) = VariableAddress[p0] : +# 45| r0_31(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_34(int) = Load : &:r0_33, m0_4 +# 45| r0_32(int) = Load : &:r0_31, m0_4 # 45| valnum = m0_4 -# 45| r0_35(glval) = VariableAddress[p1] : +# 45| r0_33(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_36(int) = Load : &:r0_35, m0_6 +# 45| r0_34(int) = Load : &:r0_33, m0_6 # 45| valnum = m0_6 -# 45| r0_37(int) = Add : r0_34, r0_36 +# 45| r0_35(int) = Add : r0_32, r0_34 # 45| valnum = r0_19 -# 45| r0_38(glval) = VariableAddress[global03] : +# 45| r0_36(glval) = VariableAddress[global03] : # 45| valnum = r0_20 -# 45| r0_39(int) = Load : &:r0_38, ~m0_31 +# 45| r0_37(int) = Load : &:r0_36, ~m0_30 # 45| valnum = unique -# 45| r0_40(int) = Add : r0_37, r0_39 -# 45| valnum = r0_40 -# 45| r0_41(glval) = VariableAddress[x] : +# 45| r0_38(int) = Add : r0_35, r0_37 +# 45| valnum = r0_38 +# 45| r0_39(glval) = VariableAddress[x] : # 45| valnum = r0_9 -# 45| m0_42(int) = Store : &:r0_41, r0_40 -# 45| valnum = r0_40 -# 45| r0_43(glval) = CopyValue : r0_41 -# 45| valnum = r0_9 -# 46| r0_44(glval) = VariableAddress[x] : +# 45| m0_40(int) = Store : &:r0_39, r0_38 +# 45| valnum = r0_38 +# 46| r0_41(glval) = VariableAddress[x] : # 46| valnum = r0_9 -# 46| r0_45(int) = Load : &:r0_44, m0_42 -# 46| valnum = r0_40 -# 46| r0_46(glval) = VariableAddress[y] : +# 46| r0_42(int) = Load : &:r0_41, m0_40 +# 46| valnum = r0_38 +# 46| r0_43(glval) = VariableAddress[y] : # 46| valnum = r0_11 -# 46| m0_47(int) = Store : &:r0_46, r0_45 -# 46| valnum = r0_40 -# 46| r0_48(glval) = CopyValue : r0_46 -# 46| valnum = r0_11 -# 47| v0_49(void) = NoOp : -# 39| r0_50(glval) = VariableAddress[#return] : +# 46| m0_44(int) = Store : &:r0_43, r0_42 +# 46| valnum = r0_38 +# 47| v0_45(void) = NoOp : +# 39| r0_46(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_51(void) = ReturnValue : &:r0_50 -# 39| v0_52(void) = UnmodeledUse : mu* -# 39| v0_53(void) = ExitFunction : +# 39| v0_47(void) = ReturnValue : &:r0_46 +# 39| v0_48(void) = UnmodeledUse : mu* +# 39| v0_49(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -419,8 +393,6 @@ test.cpp: # 55| valnum = r0_7 # 55| m2_3(char *) = Store : &:r2_2, r2_1 # 55| valnum = m0_6 -# 55| r2_4(glval) = CopyValue : r2_2 -# 55| valnum = r0_7 #-----| Goto -> Block 3 # 56| Block 3 @@ -602,8 +574,6 @@ test.cpp: # 80| valnum = r0_5 # 80| m1_6(signed short) = Store : &:r1_5, r1_4 # 80| valnum = r1_4 -# 80| r1_7(glval) = CopyValue : r1_5 -# 80| valnum = r0_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -680,12 +650,10 @@ test.cpp: # 88| valnum = r0_9 # 88| m3_4(int) = Store : &:r3_3, r3_2 # 88| valnum = m3_0 -# 88| r3_5(glval) = CopyValue : r3_3 -# 88| valnum = r0_9 -# 89| v3_6(void) = NoOp : -# 84| v3_7(void) = ReturnVoid : -# 84| v3_8(void) = UnmodeledUse : mu* -# 84| v3_9(void) = ExitFunction : +# 89| v3_5(void) = NoOp : +# 84| v3_6(void) = ReturnVoid : +# 84| v3_7(void) = UnmodeledUse : mu* +# 84| v3_8(void) = ExitFunction : # 91| int regression_test00() # 91| Block 0 From 5c07750286a2bfa2c4bdffc35f4267e488d1f7f6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 24 Oct 2019 11:28:42 +0200 Subject: [PATCH 048/232] simplify the heuristic for Deferred promises --- .../ql/src/semmle/javascript/Promises.qll | 48 ++++--------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 13eb1e8114e..ae8554c1a0a 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -36,35 +36,9 @@ module Bluebird { * Provides classes for working with various Deferred implementations */ module Deferred { - class DeferredClass extends DataFlow::SourceNode { - DeferredClass() { - exists(Variable var | - var.getName() = "Deferred" and - ( - var.getADeclaration() instanceof LocalNamespaceDecl or - var.getScope() instanceof GlobalScope - ) and - this = DataFlow::valueNode(var.getADefinition()) - ) - or - this.(DataFlow::ParameterNode).getName() = "Deferred" - or - exists(Function f | - f.getName() = "Deferred" and - this = DataFlow::valueNode(f) - ) - or - exists(ClassDefinition c | - c.getName() = "Deferred" and - this = DataFlow::valueNode(c) - ) - } - } - class DeferredInstance extends DataFlow::NewNode { - DeferredClass deferredClass; - - DeferredInstance() { this = deferredClass.getAnInstantiation() } + // Describes both `new Deferred()`, `new $.Deferred` and other variants. + DeferredInstance() { this.getCalleeName() = "Deferred" } private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { t.start() and @@ -72,23 +46,17 @@ module Deferred { or exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) } - - DeferredClass getDeferredClass() { result = deferredClass } - - DataFlow::CallNode getPromiseMemberCall(string methodName) { - result = ref(DataFlow::TypeTracker::end()).getAMemberCall(methodName) - } + + DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } } /** * A promise object created by a Deferred constructor */ private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { - DeferredPromiseDefinition() { - this = any(DeferredClass c | - exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("resolve")) and - exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("reject")) - ).getAnInstantiation() + DeferredPromiseDefinition() { + // hardening of the "Deferred" heuristic: a method call to `resolve`. + exists(ref().getAMethodCall("resolve")) } override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } @@ -99,7 +67,7 @@ module Deferred { */ class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { ResolvedDeferredPromiseDefinition() { - this = any(DeferredPromiseDefinition def).getPromiseMemberCall("resolve") + this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") } override DataFlow::Node getValue() { result = getArgument(0) } From 5489a80372ab2fdbf1c30f7d3a5c0625a4ed9bf1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Oct 2019 16:20:27 +0200 Subject: [PATCH 049/232] add query for detecting ignored calls to Array.prototype.concat --- change-notes/1.23/analysis-javascript.md | 1 + .../src/Statements/IgnoreConcatReturn.qhelp | 44 +++++++++++++++++++ .../ql/src/Statements/IgnoreConcatReturn.ql | 42 ++++++++++++++++++ .../src/Statements/examples/IgnoreConcat.js | 5 +++ .../Statements/examples/IgnoreConcatFixed.js | 5 +++ .../IgnoreConcatReturn.expected | 2 + .../IgnoreConcatReturn.qlref | 1 + .../Statements/IgnoreConcatReturn/tst.js | 13 ++++++ 8 files changed, 113 insertions(+) create mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.qhelp create mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.ql create mode 100644 javascript/ql/src/Statements/examples/IgnoreConcat.js create mode 100644 javascript/ql/src/Statements/examples/IgnoreConcatFixed.js create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 73bbf1247f7..90f46403f26 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -23,6 +23,7 @@ | Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. | | Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. | | Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. | +| Ignoring return from concat (`js/ignore-return-from-concat`) | maintainability, correctness | Highlights calls to the concat method on array where the return value is ignored. Results are shown on LGTM by default. | ## Changes to existing queries diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp b/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp new file mode 100644 index 00000000000..1b69a61b3a9 --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp @@ -0,0 +1,44 @@ + + + +

    +The concat method on is pure and does not modify any of the input +arrays. It is therefore generally an error to ignore the return value from a +call to concat. +

    + +
    + + +

    +Use the returned value from the call to concat. +

    + +
    + + +

    +In the following example a function extend is defined. The +function uses the concat method to add elements to the +arr array. However, the extend function has no +effect as the return value from concat is ignored. +

    + + + +

    +Assigning the returned value from the call to concat to the +arr variable fixes the error. +

    + + + +
    + + +
  • Mozilla Developer Network: Array concat.
  • + +
    + diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.ql b/javascript/ql/src/Statements/IgnoreConcatReturn.ql new file mode 100644 index 00000000000..65c379b3437 --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreConcatReturn.ql @@ -0,0 +1,42 @@ +/** + * @name Ignoring return from concat + * @description The concat method does not modify an array, ignoring the result of a call to concat is therefore generally an error. + * @kind problem + * @problem.severity warning + * @id js/ignore-result-from-concat + * @tags maintainability, + * correctness + * @precision high + */ + +import javascript +import Expressions.ExprHasNoEffect + +DataFlow::SourceNode array(DataFlow::TypeTracker t) { + t.start() and + result instanceof DataFlow::ArrayCreationNode + or + exists (DataFlow::TypeTracker t2 | + result = array(t2).track(t2, t) + ) +} + +DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } + +predicate isArrayMethod(DataFlow::MethodCallNode call) { + call.getReceiver().getALocalSource() = array() +} + +predicate isIncomplete(DataFlow::Node node) { + any(DataFlow::Incompleteness cause | node.analyze().getAValue().isIndefinite(cause)) != "global" +} + +from DataFlow::CallNode call +where + isArrayMethod(call) and + call.getCalleeName() = "concat" and + call.getNumArgument() = 1 and + (call.getArgument(0).getALocalSource() = array() or isIncomplete(call.getArgument(0))) and + not call.getArgument(0).asExpr().(ArrayExpr).getSize() = 0 and + inVoidContext(call.asExpr()) +select call, "Return value from call to concat ignored." diff --git a/javascript/ql/src/Statements/examples/IgnoreConcat.js b/javascript/ql/src/Statements/examples/IgnoreConcat.js new file mode 100644 index 00000000000..7137d5261a6 --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreConcat.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js b/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js new file mode 100644 index 00000000000..1c7977e9ef0 --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr = arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected new file mode 100644 index 00000000000..1ae8b59226a --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected @@ -0,0 +1,2 @@ +| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Return value from call to concat ignored. | +| tst.js:5:1:5:15 | arr.concat(arr) | Return value from call to concat ignored. | diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref new file mode 100644 index 00000000000..485692fff07 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref @@ -0,0 +1 @@ +Statements/IgnoreConcatReturn.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js new file mode 100644 index 00000000000..f2c5f34cc60 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js @@ -0,0 +1,13 @@ +var arr = [1,2,3]; + +arr.concat([1,2,3]); // NOT OK! + +arr.concat(arr); // NOT OK! + +console.log(arr.concat([1,2,3])); + +arr.concat(null); +arr.concat(); +arr.concat([]); + +({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file From 5b26d03f1ca2dba1a91e86f363dd855e09529230 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Oct 2019 15:45:35 +0200 Subject: [PATCH 050/232] introduce backtracking, and also marking join/slice calls --- ...atReturn.qhelp => IgnoreArrayResult.qhelp} | 16 ++++--- .../ql/src/Statements/IgnoreArrayResult.ql | 45 +++++++++++++++++++ .../ql/src/Statements/IgnoreConcatReturn.ql | 42 ----------------- .../{IgnoreConcat.js => IgnoreArrayResult.js} | 0 ...ncatFixed.js => IgnoreArrayResultFixed.js} | 0 .../IgnoreArrayResult.expected} | 0 .../IgnoreArrayResult.qlref} | 0 .../tst.js | 0 8 files changed, 55 insertions(+), 48 deletions(-) rename javascript/ql/src/Statements/{IgnoreConcatReturn.qhelp => IgnoreArrayResult.qhelp} (50%) create mode 100644 javascript/ql/src/Statements/IgnoreArrayResult.ql delete mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.ql rename javascript/ql/src/Statements/examples/{IgnoreConcat.js => IgnoreArrayResult.js} (100%) rename javascript/ql/src/Statements/examples/{IgnoreConcatFixed.js => IgnoreArrayResultFixed.js} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn/IgnoreConcatReturn.expected => IgnoreArrayResult/IgnoreArrayResult.expected} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn/IgnoreConcatReturn.qlref => IgnoreArrayResult/IgnoreArrayResult.qlref} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn => IgnoreArrayResult}/tst.js (100%) diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp similarity index 50% rename from javascript/ql/src/Statements/IgnoreConcatReturn.qhelp rename to javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 1b69a61b3a9..b70ff1f1b32 100644 --- a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -4,16 +4,18 @@

    -The concat method on is pure and does not modify any of the input -arrays. It is therefore generally an error to ignore the return value from a -call to concat. +The concat, join and slice methods are +pure and does not modify any of the inputs or the array the method was called +on. It is therefore generally an error to ignore the return value from a call +to one of these methods.

    -Use the returned value from the call to concat. +Use the returned value from the calls to concat, join +or slice.

    @@ -26,19 +28,21 @@ function uses the concat method to add elements to the effect as the return value from concat is ignored.

    - +

    Assigning the returned value from the call to concat to the arr variable fixes the error.

    - +
  • Mozilla Developer Network: Array concat.
  • +
  • Mozilla Developer Network: Array slice.
  • +
  • Mozilla Developer Network: Array join.
  • diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql new file mode 100644 index 00000000000..b3703c6992d --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -0,0 +1,45 @@ +/** + * @name Ignoring result from pure array method + * @description The array methods do not modify the array, ignoring the result of such a call is therefore generally an error. + * @kind problem + * @problem.severity warning + * @id js/ignore-array-result + * @tags maintainability, + * correctness + * @precision high + */ + +import javascript +import Expressions.ExprHasNoEffect + +DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) { + isIgnoredPureArrayCall(call) and + ( + t.start() and + result = call.getReceiver() + or + exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) + ) +} + +DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) { + result = callsArray(DataFlow::TypeBackTracker::end(), call) +} + +predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) { + inVoidContext(call.asExpr()) and + ( + call.getMethodName() = "concat" and + call.getNumArgument() = 1 + or + call.getMethodName() = "join" and + call.getNumArgument() < 2 + or + call.getMethodName() = "slice" and + call.getNumArgument() < 3 + ) +} + +from DataFlow::MethodCallNode call +where callsArray(call) instanceof DataFlow::ArrayCreationNode +select call, "Result from call to " + call.getMethodName() + " ignored." diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.ql b/javascript/ql/src/Statements/IgnoreConcatReturn.ql deleted file mode 100644 index 65c379b3437..00000000000 --- a/javascript/ql/src/Statements/IgnoreConcatReturn.ql +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @name Ignoring return from concat - * @description The concat method does not modify an array, ignoring the result of a call to concat is therefore generally an error. - * @kind problem - * @problem.severity warning - * @id js/ignore-result-from-concat - * @tags maintainability, - * correctness - * @precision high - */ - -import javascript -import Expressions.ExprHasNoEffect - -DataFlow::SourceNode array(DataFlow::TypeTracker t) { - t.start() and - result instanceof DataFlow::ArrayCreationNode - or - exists (DataFlow::TypeTracker t2 | - result = array(t2).track(t2, t) - ) -} - -DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } - -predicate isArrayMethod(DataFlow::MethodCallNode call) { - call.getReceiver().getALocalSource() = array() -} - -predicate isIncomplete(DataFlow::Node node) { - any(DataFlow::Incompleteness cause | node.analyze().getAValue().isIndefinite(cause)) != "global" -} - -from DataFlow::CallNode call -where - isArrayMethod(call) and - call.getCalleeName() = "concat" and - call.getNumArgument() = 1 and - (call.getArgument(0).getALocalSource() = array() or isIncomplete(call.getArgument(0))) and - not call.getArgument(0).asExpr().(ArrayExpr).getSize() = 0 and - inVoidContext(call.asExpr()) -select call, "Return value from call to concat ignored." diff --git a/javascript/ql/src/Statements/examples/IgnoreConcat.js b/javascript/ql/src/Statements/examples/IgnoreArrayResult.js similarity index 100% rename from javascript/ql/src/Statements/examples/IgnoreConcat.js rename to javascript/ql/src/Statements/examples/IgnoreArrayResult.js diff --git a/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js b/javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js similarity index 100% rename from javascript/ql/src/Statements/examples/IgnoreConcatFixed.js rename to javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js From 841dac1abad86183a0c590fbe45eb486efd81039 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Oct 2019 17:46:55 +0200 Subject: [PATCH 051/232] address review feedback --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 2fc3f01a560..c01c6b5e3eb 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -127,8 +127,10 @@ DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and - func = call.getAnArgument().getALocalSource().asExpr() and - 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and + exists(int index | + index = min(int i | exists(call.getCallback(i))) and + func = call.getCallback(index).getFunction() + ) and returnsVoid(func) and not isStub(func) and not alwaysThrows(func) and From 1d052a8e6256aaa7aca937e77bc25a399e160f7f Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 13:07:54 -0700 Subject: [PATCH 052/232] [CPP-434] Address comments re change notes. --- change-notes/1.23/analysis-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 24fa06e9bbf..b3e16dcc29a 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,7 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | -| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | This query checks for when two signed values are added together to test for overflow (`a + b < a`), which is undefined behavior. | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which is undefined behavior. Example: `a + b < a`. | ## Changes to existing queries From f964fe8b0ee99ebc568fad54ea4c59038ab2ba23 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 14:08:30 -0700 Subject: [PATCH 053/232] [CPP-434] Address comments regarding .ql and .qhelp. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 12 ++++++------ .../Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 9b9d358dea2..df48af7056d 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,16 +4,16 @@

    -Testing for signed integer overflow by adding a -value to a variable and then comparing the result to that variable -is not defined by the C or C++ standards. The comparison may -produce an unintended result, or may be deleted by the compiler -entirely. +Testing for signed integer overflow by adding a +two signed values together and then comparing the result to one +of the values is ill-formed since the overflow check is undefined. +The comparison may produce an unintended result, or may be deleted +by the compiler entirely.

    -Make sure that the comparison in question uses unsigned values. +When checking for overflow, make sure that unsigned values are used.

    diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index f1b65dd4a96..7ea5df5da64 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -2,7 +2,7 @@ * @name Undefined result of signed test for overflow * @description Testing for overflow by adding a value to a variable * to see if it "wraps around" works only for - * `unsigned` integer values. + * unsigned integer values. * @kind problem * @problem.severity warning * @precision high @@ -15,12 +15,12 @@ import cpp private import semmle.code.cpp.valuenumbering.GlobalValueNumbering private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis -from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 +from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2 where ro.getAnOperand() = add and - add.getAnOperand() = va1 and - ro.getAnOperand() = va2 and - globalValueNumber(va1) = globalValueNumber(va2) and - add.getType().getUnspecifiedType().(IntegralType).isSigned() and + add.getAnOperand() = expr1 and + ro.getAnOperand() = expr2 and + globalValueNumber(expr1) = globalValueNumber(expr2) and + add.getUnspecifiedType().(IntegralType).isSigned() and exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." From 7204e137467f25d317194eab9805a846b320f3de Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 14:37:28 -0700 Subject: [PATCH 054/232] [CPP-434] Address comments re .cpp test cases. --- .../SignedOverflowCheck.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 72767c54aab..273c84ae73b 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -29,10 +29,10 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { } bool shortShort1(unsigned short n1, unsigned short delta) { - // clang 8.0.0 -O2: deleted - // gcc 9.2 -O2: deleted - // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // GOOD: always false, but will never overflow + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return n1 + delta < n1; } bool shortShort2(unsigned short n1, unsigned short delta) { @@ -107,10 +107,10 @@ bool multipleCasts(char x) { } bool multipleCasts2(char x) { - // clang 9.0.0 -O2: not deleted - // gcc 9.2 -O2: not deleted - // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD: cannot overflow + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; } int does_it_overflow(int n1, unsigned short delta) { From 6ee3d7d788fe5e990b27309b2dcf4dd79f3d9d80 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 15:50:00 -0700 Subject: [PATCH 055/232] [CPP-434] Address more comments re .cpp test cases. --- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 12 ++++++------ .../SignedOverflowCheck.expected | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 273c84ae73b..bbfb1c3fad8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -44,7 +44,7 @@ bool shortShort2(unsigned short n1, unsigned short delta) { /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ struct N { - unsigned short n1; + int n1; } n, *np; bool shortStruct1(unsigned short n1, unsigned short delta) { @@ -60,7 +60,7 @@ bool shortStruct2(unsigned short n1, unsigned short delta) { } struct se { - short xPos; + int xPos; short yPos; short xSize; short ySize; @@ -70,7 +70,7 @@ extern se *getSo(void); bool func1(se *so) { se *o = getSo(); - if (so->xPos + so->xSize < o->xPos // GOOD + if (so->xPos + so->xSize < so->xPos // BAD || so->xPos > o->xPos + o->xSize) { // GOOD // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted @@ -100,9 +100,9 @@ int overflow12(int n) { } bool multipleCasts(char x) { - // clang 9.0.0 -O2: deleted - // gcc 9.2 -O2: deleted - // msvc 19.22 /O2: deleted + + // BAD [UNDETECTED - BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index eaf6a7ac1e4..414bc74f99e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,4 +1,5 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:73:6:73:36 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. | From da23898ebae5e0701ba1aa40783401e232619c16 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 26 Oct 2019 23:26:45 +0200 Subject: [PATCH 056/232] update tests --- .../Statements/IgnoreArrayResult/IgnoreArrayResult.expected | 4 ++-- .../Statements/IgnoreArrayResult/IgnoreArrayResult.qlref | 2 +- .../ql/test/query-tests/Statements/IgnoreArrayResult/tst.js | 4 ---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected index 1ae8b59226a..9f5c5a0b082 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected @@ -1,2 +1,2 @@ -| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Return value from call to concat ignored. | -| tst.js:5:1:5:15 | arr.concat(arr) | Return value from call to concat ignored. | +| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Result from call to concat ignored. | +| tst.js:5:1:5:15 | arr.concat(arr) | Result from call to concat ignored. | diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref index 485692fff07..2cbc7e722a5 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref @@ -1 +1 @@ -Statements/IgnoreConcatReturn.ql \ No newline at end of file +Statements/IgnoreArrayResult.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js index f2c5f34cc60..fc00470c8e1 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js @@ -6,8 +6,4 @@ arr.concat(arr); // NOT OK! console.log(arr.concat([1,2,3])); -arr.concat(null); -arr.concat(); -arr.concat([]); - ({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file From c6f53199d400c11c4ad71f75e44484bef81a6e18 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 00:24:38 +0200 Subject: [PATCH 057/232] ignore when the reciever is the empty array --- javascript/ql/src/Statements/IgnoreArrayResult.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index b3703c6992d..b6137e664d7 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -41,5 +41,7 @@ predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) { } from DataFlow::MethodCallNode call -where callsArray(call) instanceof DataFlow::ArrayCreationNode +where + callsArray(call) instanceof DataFlow::ArrayCreationNode and + not call.getReceiver().asExpr().(ArrayExpr).getSize() = 0 select call, "Result from call to " + call.getMethodName() + " ignored." From 92cebea235d6906a18e818c5234696fae2e58965 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 00:25:59 +0200 Subject: [PATCH 058/232] update tests to include empty reciever case --- .../ql/test/query-tests/Statements/IgnoreArrayResult/tst.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js index fc00470c8e1..47efe8c1cb6 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js @@ -6,4 +6,6 @@ arr.concat(arr); // NOT OK! console.log(arr.concat([1,2,3])); -({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file +({concat: Array.prototype.concat}.concat(arr)); + +[].concat([1,2,3]); \ No newline at end of file From b2c31701f3cf6dfdfb900fdaeba38b5e0ced2444 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 09:07:45 +0100 Subject: [PATCH 059/232] add documentation to two predicates --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index c01c6b5e3eb..77ec29ba9ee 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -89,6 +89,9 @@ predicate lastStatementHasNoEffect(Function f) { hasNoEffect(f.getExit().getAPredecessor()) } +/** + * Holds if `func` is a callee of `call`, and all possible callees of `call` never return a value. + */ predicate callToVoidFunction(DataFlow::CallNode call, Function func) { not call.isIncomplete() and func = call.getACallee() and @@ -97,6 +100,11 @@ predicate callToVoidFunction(DataFlow::CallNode call, Function func) { ) } +/** + * Holds if `name` is the name of a method from `Array.prototype` or Lodash, + * where that method takes a callback as parameter, + * and the callback is expected to return a value. + */ predicate hasNonVoidCallbackMethod(string name) { name = "every" or name = "filter" or From 1500148c765438be0170777a7c6bcd79e71b0872 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Sun, 27 Oct 2019 11:23:54 -0700 Subject: [PATCH 060/232] [CPP-434] Clarify Qhelp. --- .../Arithmetic/SignedOverflowCheck-good1.cpp | 2 +- .../Arithmetic/SignedOverflowCheck-good2.cpp | 4 +- .../Arithmetic/SignedOverflowCheck.qhelp | 48 +++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp index d79d3ccbe93..2209b8bff71 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -1,3 +1,3 @@ bool baf(unsigned short n1, unsigned short delta) { - return n1 + (unsigned)delta < n1; // GOOD + return (unsigned short)(n1 + delta) < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp index 2670a4371f6..cccc66b71f8 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp @@ -1,3 +1,3 @@ -bool baz(int n1, unsigned int delta) { - return n1 + delta < n1; // GOOD +bool baz(int n1, int delta) { + return (unsigned)n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index df48af7056d..ae4dae55016 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,16 +4,22 @@

    -Testing for signed integer overflow by adding a -two signed values together and then comparing the result to one -of the values is ill-formed since the overflow check is undefined. -The comparison may produce an unintended result, or may be deleted -by the compiler entirely. +When checking for integer overflow, one often writes tests like +a + b < a. This works fine if a or +b are unsigned integers, since any overflow in the addition +will cause the value to simply "wrap around". However, using +signed integers is problematic because signed overflows have undefined +behavior according to the C and C++ standards. If the addition overflows +and has an undefined result, the comparison will likewise be undefined; +it may produce an unintended result, or may be deleted entirely by an +optimizing compiler.

    -When checking for overflow, make sure that unsigned values are used. +When checking for overflow by adding two values, first make sure that a +or b are (converted into) unsigned values, unless it is +certain that the signed addition cannot overflow.

    @@ -21,9 +27,10 @@ When checking for overflow, make sure that unsigned values are used In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, -namely a signed int. As a result, the entire expression is -evaluated using signed integers and may overflow, and hence -is undefined. +namely a signed int. Addition is performed on +signed integers, and may have undefined behavior if an overflow occurs. +As a result, the entire (comparison) expression may also have an undefined +result.

    @@ -39,21 +46,20 @@ hold true, which likely is not what the programmer intended. (see also the

    The following example builds upon the previous one. Again, we have two -unsigned short values getting promoted to a wider type. However, -since delta is explicitly cast to an unsigned type, -n1 (on both sides of the comparison) is promoted to -unsigned int as well. Since we are now operating on -unsigned values, the overflow check is defined and supported by -standard C/C++. +unsigned short values getting promoted to a wider type, resulting +in a comparison that always succeeds (since there is no overflow). To +test whether we have an unsigned short overflow, we cast the +left-hand side to it, causing the right-hand side to remain an unsigned +short as well.

    -In the next example, a value of type signed int is -added to a value of type unsigned int. Because -the types are of the same size, C/C++ conversion rules dictate that -unsigned int is chosen as the overall type of the addition -operation. The entire expression is evaluated using unsigned -values, which is allowed and defined behavior per the C/C++ standard. +In the next example, we have two signed int values that we +wish to add together. Adding them "as-is" opens the possibility of +a signed integer overflow, the results of which are undefined. +By casting one of the operands to unsigned, the entire +expression is evaluated using unsigned +values, which is defined behavior per the C/C++ standard.

    From b0cf7cb39a9f04648fc98f796ee2c9a444d63d74 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 13:38:53 +0100 Subject: [PATCH 061/232] C#: Move `UnsafeDeserialization.qll` --- .../ql/src/Security Features/CWE-502/UnsafeDeserialization.ql | 2 +- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 2 +- .../code/csharp/security/dataflow}/UnsafeDeserialization.qll | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename csharp/ql/src/{Security Features/CWE-502 => semmle/code/csharp/security/dataflow}/UnsafeDeserialization.qll (100%) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index edd0e15c247..d0ab23560a1 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -14,7 +14,7 @@ */ import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization from Call deserializeCall, Sink sink where deserializeCall.getAnArgument() = sink.asExpr() diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index b0b659857ab..fb4011ec846 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -14,7 +14,7 @@ */ import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph from TaintTrackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll similarity index 100% rename from csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll From eb990525d740a3744dcb2781d5466ed00140c2c3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 14:19:40 +0100 Subject: [PATCH 062/232] C#: Add precision tags to `UnsafeDeserialization[UntrustedInput].ql` --- .../CWE-502/UnsafeDeserialization.ql | 5 +-- .../UnsafeDeserializationUntrustedInput.ql | 5 +-- .../dataflow/UnsafeDeserialization.qll | 1 - .../UnsafeDeserialization/ExtractorOptions.cs | 2 +- .../UnsafeDeserialization/SystemWebStub.cs | 34 -------------- .../ExtractorOptions.cs | 2 +- .../SystemWebStub.cs | 45 ------------------- csharp/ql/test/resources/stubs/System.Web.cs | 22 +++++++++ 8 files changed, 26 insertions(+), 90 deletions(-) delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index d0ab23560a1..40022d40573 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -5,14 +5,11 @@ * @kind problem * @id cs/unsafe-deserialization * @problem.severity warning + * @precision low * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision low - */ - import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index fb4011ec846..80a3762a8bc 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -5,14 +5,11 @@ * @kind path-problem * @id cs/unsafe-deserialization-untrusted-input * @problem.severity error + * @precision high * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision high - */ - import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 4e401eb4804..57b3a78485b 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,6 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs index 11f05a14a00..bd796aa9f51 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs deleted file mode 100644 index 48c74335f6f..00000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs +++ /dev/null @@ -1,34 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs index 11f05a14a00..bd796aa9f51 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs deleted file mode 100644 index 293c0cdf355..00000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs +++ /dev/null @@ -1,45 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace UI - { - namespace WebControls - { - public class TextBox - { - public string Text { get; set; } - } - } - } - - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index eb08326b794..13ebaf316d7 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -346,3 +346,25 @@ namespace System.Web.Helpers public static void Validate() { } } } + +namespace System.Web.Script.Serialization +{ + // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class JavaScriptSerializer + { + public JavaScriptSerializer() => throw null; + public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; + public object DeserializeObject(string input) => throw null; + } + + // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + abstract public class JavaScriptTypeResolver + { + } + + // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver + { + public SimpleTypeResolver() => throw null; + } +} From 3f5ee5138b99d52ae2146e8ceddc96b628d9e331 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 14:22:59 +0100 Subject: [PATCH 063/232] C#: Add change notes --- change-notes/1.23/analysis-csharp.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index 7ec412a0eb2..786c35ffbae 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -8,7 +8,9 @@ The following changes in version 1.23 affect C# analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| +| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security | Finds flow of untrusted input to calls to unsafe deserializers. | | Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. | +| Unsafe deserializer (`cs/unsafe-deserialization`) | security | Finds calls to unsafe deserializers. | | Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. | ## Changes to existing queries From d693eb8c20a147a927ae2e5dda179d9233cde6b9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Oct 2019 17:39:45 +0000 Subject: [PATCH 064/232] CPP: Correct the ConditionallyUninitializedVariable examples. --- .../CWE/CWE-457/ConditionallyUninitializedVariableBad.c | 6 +++--- .../CWE/CWE-457/ConditionallyUninitializedVariableGood.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c index 1f281f3cfd9..73a01c2d900 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c @@ -19,7 +19,7 @@ int notify(int deviceNumber) { DeviceConfig config; initDeviceConfig(&config, deviceNumber); // BAD: Using config without checking the status code that is returned - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } -} \ No newline at end of file +} diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c index a9dcc06c9a5..ced43a66cfc 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c @@ -20,8 +20,8 @@ void notify(int deviceNumber) { int statusCode = initDeviceConfig(&config, deviceNumber); if (statusCode == 0) { // GOOD: Status code returned by initialization function is checked, so this is safe - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } } -} \ No newline at end of file +} From c40c88ec4bfd2ddd5e79ed48fb1c955e23bf2a7b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Oct 2019 18:43:00 +0000 Subject: [PATCH 065/232] CPP: Add test cases for ConditionallyUninitializedVariables.ql. --- ...onditionallyUninitializedVariable.expected | 3 + .../ConditionallyUninitializedVariable.qlref | 1 + .../examples.cpp | 43 +++++++++ .../test.cpp | 96 +++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected new file mode 100644 index 00000000000..60964c8f178 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected @@ -0,0 +1,3 @@ +| examples.cpp:38:3:38:18 | call to initDeviceConfig | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | examples.cpp:13:5:13:20 | initDeviceConfig | initDeviceConfig | examples.cpp:37:16:37:21 | config | config | +| test.cpp:22:2:22:17 | call to maybeInitialize1 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:4:5:4:20 | maybeInitialize1 | maybeInitialize1 | test.cpp:19:6:19:6 | a | a | +| test.cpp:68:2:68:17 | call to maybeInitialize2 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:51:6:51:21 | maybeInitialize2 | maybeInitialize2 | test.cpp:66:6:66:6 | a | a | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref new file mode 100644 index 00000000000..5150d627257 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp new file mode 100644 index 00000000000..ccb15904d02 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp @@ -0,0 +1,43 @@ +// based on the qhelp + +int getMaxDevices(); +bool fetchIsDeviceEnabled(int deviceNumber); +int fetchDeviceChannel(int deviceNumber); +void notifyChannel(int channel); + +struct DeviceConfig { + bool isEnabled; + int channel; +}; + +int initDeviceConfig(DeviceConfig *ref, int deviceNumber) { + if (deviceNumber >= getMaxDevices()) { + // No device with that number, return -1 to indicate failure + return -1; + } + // Device with that number, fetch parameters and initialize struct + ref->isEnabled = fetchIsDeviceEnabled(deviceNumber); + ref->channel = fetchDeviceChannel(deviceNumber); + // Return 0 to indicate success + return 0; +} + +void notifyGood(int deviceNumber) { + DeviceConfig config; + int statusCode = initDeviceConfig(&config, deviceNumber); + if (statusCode == 0) { + // GOOD: Status code returned by initialization function is checked, so this is safe + if (config.isEnabled) { + notifyChannel(config.channel); + } + } +} + +int notifyBad(int deviceNumber) { + DeviceConfig config; + initDeviceConfig(&config, deviceNumber); + // BAD: Using config without checking the status code that is returned + if (config.isEnabled) { + notifyChannel(config.channel); + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp new file mode 100644 index 00000000000..a3c9b0a24aa --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp @@ -0,0 +1,96 @@ + +void use(int i); + +int maybeInitialize1(int *v) +{ + static int resources = 100; + + if (resources == 0) + { + return 0; // FAIL + } + + *v = resources--; + return 1; // SUCCESS +} + +void test1() +{ + int a, b, c, d, e, f; + int result1, result2; + + maybeInitialize1(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize1(&b) == 1) // GOOD + { + use(b); + } + + if (maybeInitialize1(&c) == 0) // BAD (initialization check is wrong) [NOT DETECTED] + { + use(c); + } + + result1 = maybeInitialize1(&d); // BAD (initialization stored but not checked) [NOT DETECTED] + use(d); + + result2 = maybeInitialize1(&e); // GOOD + if (result2 == 1) + { + use(e); + } + + if (maybeInitialize1(&f) == 0) // GOOD + { + return; + } + use(f); +} + +bool maybeInitialize2(int *v) +{ + static int resources = 100; + + if (resources > 0) + { + *v = resources--; + return true; // SUCCESS + } + + return false; // FAIL +} + +void test2() +{ + int a, b; + + maybeInitialize2(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize2(&b)) // GOOD + { + use(b); + } +} + +int alwaysInitialize(int *v) +{ + static int resources = 0; + + *v = resources++; + return 1; // SUCCESS +} + +void test3() +{ + int a, b; + + alwaysInitialize(&a); // GOOD (initialization never fails) + use(a); + + if (alwaysInitialize(&b) == 1) // GOOD + { + use(b); + } +} From 2d64fedeb021db7fa0a919bad6f189ae4805907f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:19:31 +0100 Subject: [PATCH 066/232] CPP: Speed up VirtualDispatch.qll's getAViableTarget. --- .../code/cpp/dispatch/VirtualDispatch.qll | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll index 2fa9322843e..1113fc430e7 100644 --- a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll @@ -28,6 +28,19 @@ module VirtualDispatch { not result.hasName("IUnknown") } + /** + * Helper predicate for `getAViableTarget`, which computes the viable targets for + * virtual calls based on the qualifier type. + */ + private Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) { + exists(Class qualifierSubType | + result = getAPossibleImplementation(staticTarget) and + qualifierType = qualifierSubType.getABaseClass*() and + mayInherit(qualifierSubType, result) and + not cannotInherit(qualifierSubType, result) + ) + } + /** * Gets a viable target for the given function call. * @@ -42,18 +55,9 @@ module VirtualDispatch { * If `c` is not a virtual call, the result will be `c.getTarget()`. */ Function getAViableTarget(Call c) { - exists(Function staticTarget | staticTarget = c.getTarget() | - if c.(FunctionCall).isVirtual() and staticTarget instanceof MemberFunction - then - exists(Class qualifierType, Class qualifierSubType | - result = getAPossibleImplementation(staticTarget) and - qualifierType = getCallQualifierType(c) and - qualifierType = qualifierSubType.getABaseClass*() and - mayInherit(qualifierSubType, result) and - not cannotInherit(qualifierSubType, result) - ) - else result = staticTarget - ) + if c.(FunctionCall).isVirtual() and c.getTarget() instanceof MemberFunction + then result = getAViableVirtualCallTarget(getCallQualifierType(c), c.getTarget()) + else result = c.getTarget() } /** Holds if `f` is declared in `c` or a transitive base class of `c`. */ From 3584c0b2e5ae646b0e4c53d4d80810e84ed5c780 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:22:42 +0100 Subject: [PATCH 067/232] CPP: Speed up InitializationFunctions.qll's getTarget. --- .../CWE/CWE-457/InitializationFunctions.qll | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 240bd7aa25e..720cf11950b 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -618,6 +618,33 @@ Function getAPossibleDefinition(Function undefinedFunction) { ) and result.isDefined() } + +private Function getTarget1(Call c) { + /* + * If there is at least one defined target after performing some simple virtual dispatch + * resolution, then the result is all the defined targets. + */ + + result = VirtualDispatch::getAViableTarget(c) and + result.isDefined() +} + +private Function getTarget2(Call c) { + /* + * If we can use the heuristic matching of functions to find definitions for some of the viable + * targets, return those. + */ + + not exists(getTarget1(c)) and + result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) +} + +private Function getTarget3(Call c) { + not exists(getTarget1(c)) and + not exists(getTarget2(c)) and + // Otherwise, the result is the undefined `Function` instances. + result = VirtualDispatch::getAViableTarget(c) +} /** * Gets a possible target for the Call, using the name and parameter matching if we did not associate @@ -625,27 +652,9 @@ Function getAPossibleDefinition(Function undefinedFunction) { * dispatch resolution. */ Function getTarget(Call c) { - if VirtualDispatch::getAViableTarget(c).isDefined() - then - /* - * If there is at least one defined target after performing some simple virtual dispatch - * resolution, then the result is all the defined targets. - */ - - result = VirtualDispatch::getAViableTarget(c) and - result.isDefined() - else - if exists(getAPossibleDefinition(VirtualDispatch::getAViableTarget(c))) - then - /* - * If we can use the heuristic matching of functions to find definitions for some of the viable - * targets, return those. - */ - - result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) - else - // Otherwise, the result is the undefined `Function` instances - result = VirtualDispatch::getAViableTarget(c) + result = getTarget1(c) or + result = getTarget2(c) or + result = getTarget3(c) } /** From 563f32193cfbb747c19c0b28884be70264a6296c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Oct 2019 12:10:12 +0100 Subject: [PATCH 068/232] suggestions from @max-schaefer Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 2 +- javascript/ql/src/Statements/IgnoreArrayResult.ql | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index b70ff1f1b32..2232784d881 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -5,7 +5,7 @@

    The concat, join and slice methods are -pure and does not modify any of the inputs or the array the method was called +pure and do not modify any of the inputs or the array the method was called on. It is therefore generally an error to ignore the return value from a call to one of these methods.

    diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index b6137e664d7..5ab778ed95b 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -1,10 +1,10 @@ /** * @name Ignoring result from pure array method - * @description The array methods do not modify the array, ignoring the result of such a call is therefore generally an error. + * @description Ignoring the result of an array method that does not modify its receiver is generally an error. * @kind problem * @problem.severity warning * @id js/ignore-array-result - * @tags maintainability, + * @tags maintainability * correctness * @precision high */ @@ -16,7 +16,7 @@ DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCal isIgnoredPureArrayCall(call) and ( t.start() and - result = call.getReceiver() + result = call.getReceiver().getALocalSource() or exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) ) From 2d01e7c5ed97392e55db948755d445dc8337a68a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Oct 2019 12:13:01 +0100 Subject: [PATCH 069/232] simplify the callsArray predicate --- javascript/ql/src/Statements/IgnoreArrayResult.ql | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index 5ab778ed95b..6f6698797f1 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -13,13 +13,11 @@ import javascript import Expressions.ExprHasNoEffect DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) { - isIgnoredPureArrayCall(call) and - ( - t.start() and - result = call.getReceiver().getALocalSource() - or - exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) - ) + isIgnoredPureArrayCall(call) and + t.start() and + result = call.getReceiver().getALocalSource() + or + exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) } DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) { From 49dd2216a65e55824bb0371d8d476eebae1c241b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 10 Oct 2019 16:14:12 +0200 Subject: [PATCH 070/232] Python: Refactor django library Use General.qll for routing, like in other web libraries --- .../src/semmle/python/web/django/General.qll | 28 +++++++++++++ .../src/semmle/python/web/django/Request.qll | 41 ++++--------------- 2 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 python/ql/src/semmle/python/web/django/General.qll diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll new file mode 100644 index 00000000000..954df1892e8 --- /dev/null +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -0,0 +1,28 @@ +import python +import semmle.python.regex +import semmle.python.web.Http + +predicate django_route(CallNode call, ControlFlowNode regex, FunctionValue view) { + exists(FunctionValue url | + Value::named("django.conf.urls.url") = url and + url.getArgumentForCall(call, 0) = regex and + url.getArgumentForCall(call, 1).pointsTo(view) + ) +} + +class DjangoRouteRegex extends RegexString { + DjangoRouteRegex() { django_route(_, this.getAFlowNode(), _) } +} + +class DjangoRoute extends CallNode { + DjangoRoute() { django_route(this, _, _) } + + FunctionValue getViewFunction() { django_route(this, _, result) } + + string getNamedArgument() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + regex.getGroupName(_, _) = result + ) + } +} diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index d2ad2ff30d3..71da78f9b43 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -1,7 +1,7 @@ import python -import semmle.python.regex import semmle.python.security.TaintTracking import semmle.python.web.Http +import semmle.python.web.django.General /** A django.request.HttpRequest object */ class DjangoRequest extends TaintKind { @@ -52,7 +52,7 @@ abstract class DjangoRequestSource extends HttpRequestTaintSource { private class DjangoFunctionBasedViewRequestArgument extends DjangoRequestSource { DjangoFunctionBasedViewRequestArgument() { exists(FunctionValue view | - url_dispatch(_, _, view) and + django_route(_, _, view) and this = view.getScope().getArg(0).asName().getAFlowNode() ) } @@ -76,41 +76,14 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { } } -/* *********** Routing ********* */ -/* Function based views */ -predicate url_dispatch(CallNode call, ControlFlowNode regex, FunctionValue view) { - exists(FunctionValue url | - Value::named("django.conf.urls.url") = url and - url.getArgumentForCall(call, 0) = regex and - url.getArgumentForCall(call, 1).pointsTo(view) - ) -} - -class UrlRegex extends RegexString { - UrlRegex() { url_dispatch(_, this.getAFlowNode(), _) } -} - -class UrlRouting extends CallNode { - UrlRouting() { url_dispatch(this, _, _) } - - FunctionValue getViewFunction() { url_dispatch(this, _, result) } - - string getNamedArgument() { - exists(UrlRegex regex | - url_dispatch(this, regex.getAFlowNode(), _) and - regex.getGroupName(_, _) = result - ) - } -} - /** An argument specified in a url routing table */ -class HttpRequestParameter extends HttpRequestTaintSource { - HttpRequestParameter() { - exists(UrlRouting url | - this.(ControlFlowNode).getNode() = url +class DjangoRequestParameter extends HttpRequestTaintSource { + DjangoRequestParameter() { + exists(DjangoRoute route | + this.(ControlFlowNode).getNode() = route .getViewFunction() .getScope() - .getArgByName(url.getNamedArgument()) + .getArgByName(route.getNamedArgument()) ) } From afe7a0536cc0ad3cc93b396c0d3ed40bb1c5502c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 10 Oct 2019 17:25:09 +0200 Subject: [PATCH 071/232] Python: Support positional arguments in Django routes --- change-notes/1.23/analysis-python.md | 5 +++ .../src/semmle/python/web/django/General.qll | 12 +++++++ .../src/semmle/python/web/django/Request.qll | 14 +++++--- .../library-tests/web/django/Sinks.expected | 4 +++ .../library-tests/web/django/Sources.expected | 9 +++++ .../ql/test/library-tests/web/django/test.py | 33 ++++++++++++++++++- 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/change-notes/1.23/analysis-python.md b/change-notes/1.23/analysis-python.md index 00fab13e098..6cea1745284 100644 --- a/change-notes/1.23/analysis-python.md +++ b/change-notes/1.23/analysis-python.md @@ -20,3 +20,8 @@ |----------------------------|------------------------|------------| | Unreachable code | Fewer false positives | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. | | `__iter__` method returns a non-iterator | Better alert message | Alert now highlights which class is expected to be an iterator. | + + +## Changes to QL libraries + +* Django library now recognizes positional arguments from a `django.conf.urls.url` regex (Django version 1.x) diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll index 954df1892e8..423d853cdad 100644 --- a/python/ql/src/semmle/python/web/django/General.qll +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -25,4 +25,16 @@ class DjangoRoute extends CallNode { regex.getGroupName(_, _) = result ) } + + /** + * Get the number of positional arguments that will be passed to the view. + * Will only return a result if there are no named arguments. + */ + int getNumPositionalArguments() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + not exists(string s | s = regex.getGroupName(_, _)) and + result = count(regex.getGroupNumber(_, _)) + ) + } } diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index 71da78f9b43..15ea032e6d7 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -79,11 +79,15 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { /** An argument specified in a url routing table */ class DjangoRequestParameter extends HttpRequestTaintSource { DjangoRequestParameter() { - exists(DjangoRoute route | - this.(ControlFlowNode).getNode() = route - .getViewFunction() - .getScope() - .getArgByName(route.getNamedArgument()) + exists(DjangoRoute route, Function f | + f = route.getViewFunction().getScope() | + this.(ControlFlowNode).getNode() = f.getArgByName(route.getNamedArgument()) + or + exists(int i | i >= 0 | + i < route.getNumPositionalArguments() and + // +1 because first argument is always the request + this.(ControlFlowNode).getNode() = f.getArg(i+1) + ) ) } diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 82d1b71e53a..7201a7a20a9 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -4,3 +4,7 @@ | test.py:25 | BinaryExpr | externally controlled string | | test.py:26 | BinaryExpr | externally controlled string | | test.py:34 | BinaryExpr | externally controlled string | +| test.py:46 | Attribute() | externally controlled string | +| test.py:57 | Attribute() | externally controlled string | +| test.py:60 | Attribute() | externally controlled string | +| test.py:63 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 8f421a2d169..7482f21cdda 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,2 +1,11 @@ | test.py:11 | request | django.request.HttpRequest | | test.py:31 | request | django.request.HttpRequest | +| test.py:56 | arg0 | externally controlled string | +| test.py:56 | request | django.request.HttpRequest | +| test.py:59 | arg0 | externally controlled string | +| test.py:59 | arg1 | externally controlled string | +| test.py:59 | arg2 | externally controlled string | +| test.py:59 | request | django.request.HttpRequest | +| test.py:62 | arg0 | externally controlled string | +| test.py:62 | arg1 | externally controlled string | +| test.py:62 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index e6c39c30a32..3cabac0e5c5 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -34,7 +34,38 @@ def maybe_xss(request): resp.write("first name is " + first_name) return resp -urlpatterns2 = [ +urlpatterns = [ # Route to code_execution url(r'^maybe_xss$', maybe_xss, name='maybe_xss') ] + + +# Non capturing group (we correctly identify page_number as a request parameter) + +def show_articles(request, page_number=1): + return HttpResponse('articles page: {}'.format(page_number)) + +urlpatterns = [ + # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 + url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), +] + + +# Positional arguments + +def xxs_positional_arg1(request, arg0): + return HttpResponse('xxs_positional_arg1: {}'.format(arg0)) + +def xxs_positional_arg2(request, arg0, arg1, arg2): + return HttpResponse('xxs_positional_arg2: {} {} {}'.format(arg0, arg1, arg2)) + +def xxs_positional_arg3(request, arg0, arg1): + return HttpResponse('xxs_positional_arg3: {} {}'.format(arg0, arg1)) + +urlpatterns = [ + # passing as positional argument is not the recommended way of doing things, + # but it is certainly possible + url(r'^(.+)$', xxs_positional_arg1, name='xxs_positional_arg1'), + url(r'^([^/]+)/([^/]+)/([^/]+)$', xxs_positional_arg2, name='xxs_positional_arg2'), + url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg3, name='xxs_positional_arg3'), +] From 471318369b4fee5c66239a5f33c91d9410df8f76 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Oct 2019 16:51:50 +0200 Subject: [PATCH 072/232] Python: Don't quote %s in django example This is vulnerable to SQL injection because of the quotes around %s -- added some code that highlights this in test.py Since our examples did this in the safe query, I ended up rewriting them completely, causing a lot of trouble for myself :D --- .../src/Security/CWE-089/SqlInjection.qhelp | 17 +++++-- .../CWE-089/examples/sql_injection.py | 28 +++++----- .../library-tests/web/django/Sinks.expected | 21 ++++---- .../library-tests/web/django/Sources.expected | 26 ++++++---- .../ql/test/library-tests/web/django/test.py | 51 ++++++++++++------- .../Security/CWE-089/SqlInjection.expected | 27 +++++----- .../Security/CWE-089/sql_injection.py | 48 ++++++++++------- 7 files changed, 128 insertions(+), 90 deletions(-) diff --git a/python/ql/src/Security/CWE-089/SqlInjection.qhelp b/python/ql/src/Security/CWE-089/SqlInjection.qhelp index e976401a6b5..286b71a6047 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.qhelp +++ b/python/ql/src/Security/CWE-089/SqlInjection.qhelp @@ -21,20 +21,29 @@ or prepared statements.

    -In the following snippet, from an example django app, -a name is stored in the database using two different queries. +In the following snippet, a user is fetched from the database using three +different queries.

    In the first case, the query string is built by -directly using string formatting from a user-supplied request attribute. +directly using string formatting from a user-supplied request parameter. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.

    In the second case, the user-supplied request attribute is passed -to the database using query parameters. +to the database using query parameters. The database connector library will +take care of escaping and inserting quotes as needed. +

    + +

    +In the third case, the placeholder in the SQL string has been manually quoted. Since most +databaseconnector libraries will insert their own quotes, doing so yourself will make the code +vulnerable to SQL injection attacks. In this example, if username was +; DROP ALL TABLES -- , the final SQL query would be +SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''

    diff --git a/python/ql/src/Security/CWE-089/examples/sql_injection.py b/python/ql/src/Security/CWE-089/examples/sql_injection.py index 541c580f712..fe6dbc50c01 100644 --- a/python/ql/src/Security/CWE-089/examples/sql_injection.py +++ b/python/ql/src/Security/CWE-089/examples/sql_injection.py @@ -1,21 +1,19 @@ - -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + user = cursor.fetchone() - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + user = cursor.fetchone() + # BAD -- Manually quoting placeholder (%s) + cursor.execute("SELECT * FROM users WHERE username = '%s'", username) + user = cursor.fetchone() -urlpatterns = patterns(url(r'^save_name/$', - upload, name='save_name')) - +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 7201a7a20a9..31a42364762 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -1,10 +1,13 @@ -| test.py:18 | Str | externally controlled string | +| test.py:14 | Str | externally controlled string | +| test.py:15 | Str | externally controlled string | +| test.py:18 | BinaryExpr | externally controlled string | | test.py:21 | BinaryExpr | externally controlled string | -| test.py:24 | BinaryExpr | externally controlled string | -| test.py:25 | BinaryExpr | externally controlled string | -| test.py:26 | BinaryExpr | externally controlled string | -| test.py:34 | BinaryExpr | externally controlled string | -| test.py:46 | Attribute() | externally controlled string | -| test.py:57 | Attribute() | externally controlled string | -| test.py:60 | Attribute() | externally controlled string | -| test.py:63 | Attribute() | externally controlled string | +| test.py:22 | BinaryExpr | externally controlled string | +| test.py:23 | BinaryExpr | externally controlled string | +| test.py:37 | Str | externally controlled string | +| test.py:44 | BinaryExpr | externally controlled string | +| test.py:48 | Attribute() | externally controlled string | +| test.py:59 | Attribute() | externally controlled string | +| test.py:70 | Attribute() | externally controlled string | +| test.py:73 | Attribute() | externally controlled string | +| test.py:76 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 7482f21cdda..371b1e7cb6f 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,11 +1,17 @@ | test.py:11 | request | django.request.HttpRequest | -| test.py:31 | request | django.request.HttpRequest | -| test.py:56 | arg0 | externally controlled string | -| test.py:56 | request | django.request.HttpRequest | -| test.py:59 | arg0 | externally controlled string | -| test.py:59 | arg1 | externally controlled string | -| test.py:59 | arg2 | externally controlled string | -| test.py:59 | request | django.request.HttpRequest | -| test.py:62 | arg0 | externally controlled string | -| test.py:62 | arg1 | externally controlled string | -| test.py:62 | request | django.request.HttpRequest | +| test.py:11 | username | externally controlled string | +| test.py:41 | request | django.request.HttpRequest | +| test.py:47 | bar | externally controlled string | +| test.py:47 | foo | externally controlled string | +| test.py:47 | request | django.request.HttpRequest | +| test.py:58 | page_number | externally controlled string | +| test.py:58 | request | django.request.HttpRequest | +| test.py:69 | arg0 | externally controlled string | +| test.py:69 | request | django.request.HttpRequest | +| test.py:72 | arg0 | externally controlled string | +| test.py:72 | arg1 | externally controlled string | +| test.py:72 | arg2 | externally controlled string | +| test.py:72 | request | django.request.HttpRequest | +| test.py:75 | arg0 | externally controlled string | +| test.py:75 | arg1 | externally controlled string | +| test.py:75 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index 3cabac0e5c5..1240b9ae5a1 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -5,28 +5,38 @@ from django.db.models.expressions import RawSQL from django.http.response import HttpResponse import base64 -class Name(models.Model): +class User(models.Model): pass -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) -urlpatterns1 = patterns(url(r'^save_name/$', - save_name, name='save_name')) + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) + +urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) def maybe_xss(request): first_name = request.POST.get('first_name', '') @@ -34,9 +44,12 @@ def maybe_xss(request): resp.write("first name is " + first_name) return resp +def xss_kwargs(request, foo, bar, baz=None): + return HttpResponse('xss_kwargs: {} {}'.format(foo, bar)) + urlpatterns = [ - # Route to code_execution - url(r'^maybe_xss$', maybe_xss, name='maybe_xss') + url(r'^maybe_xss$', maybe_xss, name='maybe_xss'), + url(r'^bar/(?P[^/]+)/foo/(?P[^/]+)', xss_kwargs, name='xss_kwargs'), ] diff --git a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 9c00ffdb2db..461d42fccf1 100644 --- a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -1,17 +1,14 @@ edges -| sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:12:16:12:22 | django.request.HttpRequest | -| sql_injection.py:12:16:12:22 | django.request.HttpRequest | sql_injection.py:12:16:12:27 | django.http.request.QueryDict | -| sql_injection.py:12:16:12:27 | django.http.request.QueryDict | sql_injection.py:12:16:12:39 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:19:63:19:66 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:22:88:22:91 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:23:76:23:79 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:24:78:24:81 | externally controlled string | -| sql_injection.py:19:63:19:66 | externally controlled string | sql_injection.py:19:13:19:66 | externally controlled string | -| sql_injection.py:22:88:22:91 | externally controlled string | sql_injection.py:22:38:22:91 | externally controlled string | -| sql_injection.py:23:76:23:79 | externally controlled string | sql_injection.py:23:26:23:79 | externally controlled string | -| sql_injection.py:24:78:24:81 | externally controlled string | sql_injection.py:24:28:24:81 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:70:19:77 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:88:22:95 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:76:23:83 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:78:24:85 | externally controlled string | +| sql_injection.py:19:70:19:77 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | +| sql_injection.py:22:88:22:95 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | +| sql_injection.py:23:76:23:83 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | +| sql_injection.py:24:78:24:85 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | #select -| sql_injection.py:19:13:19:66 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:19:13:19:66 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:22:38:22:91 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:22:38:22:91 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:23:26:23:79 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:23:26:23:79 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:24:28:24:81 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:24:28:24:81 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | +| sql_injection.py:19:24:19:77 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:22:38:22:95 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:23:26:23:83 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:24:28:24:85 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py index b312241b809..9ccca7503bd 100644 --- a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py +++ b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py @@ -1,28 +1,40 @@ +"""This is copied from ql/python/ql/test/library-tests/web/django/test.py +and a only a slight extension of ql/python/ql/src/Security/CWE-089/examples/sql_injection.py +""" -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection, models from django.db.models.expressions import RawSQL -class Name(models.Model): +class User(models.Model): pass -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) -urlpatterns = patterns(url(r'^save_name/$', - save_name, name='save_name')) + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] From 91f269ed7b873cc7fc329f562a99552297467a0e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Oct 2019 16:44:26 +0200 Subject: [PATCH 073/232] Python: Remove unused django sinks This would find instances of `thing = MyThing.objects.get(field=userinput)`, and what seems to be a query that wants to match on `thing = MyThing(); thing.field=userinput`. Both are not vulnerable to user-input, due to the build-in escaping by django. The DjangoModelFieldWrite actually matches on `MyThing.field=userinput` and not `thing.field=userinput`. I suspect this to be a mistake. Matching on `thing.field=userinput`, would require this CodeQL: attr.getObject(_).pointsTo().getClass() = model --- .../ql/src/semmle/python/web/django/Model.qll | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/python/ql/src/semmle/python/web/django/Model.qll b/python/ql/src/semmle/python/web/django/Model.qll index 34cf5856802..b8f47b64bdf 100644 --- a/python/ql/src/semmle/python/web/django/Model.qll +++ b/python/ql/src/semmle/python/web/django/Model.qll @@ -54,33 +54,6 @@ class DjangoModelObjects extends TaintSource { override string toString() { result = "django.db.models.Model.objects" } } -/** A write to a field of a django model, which is a vulnerable to external data. */ -class DjangoModelFieldWrite extends SqlInjectionSink { - DjangoModelFieldWrite() { - exists(AttrNode attr, DjangoModel model | - this = attr and attr.isStore() and attr.getObject(_).pointsTo(model) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model field write" } -} - -/** A direct reference to a django model object, which is vulnerable to external data. */ -class DjangoModelDirectObjectReference extends TaintSink { - DjangoModelDirectObjectReference() { - exists(CallNode objects_get_call, ControlFlowNode objects | this = objects_get_call.getAnArg() | - objects_get_call.getFunction().(AttrNode).getObject("get") = objects and - any(DjangoDbTableObjects objs).taints(objects) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model object reference" } -} - /** * A call to the `raw` method on a django model. This allows a raw SQL query * to be sent to the database, which is a security risk. From fb864b7262ec63ed695edf8fd084f6eb1b124da1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 21 Oct 2019 16:39:55 +0200 Subject: [PATCH 074/232] Python: Consolidate tests for django The tests in 3/ was not Python 3 specific anymore --- .../3/library-tests/web/django/Sinks.expected | 6 -- .../test/3/library-tests/web/django/Sinks.ql | 13 --- .../library-tests/web/django/Sources.expected | 8 -- .../3/library-tests/web/django/Sources.ql | 12 --- .../3/library-tests/web/django/Taint.expected | 24 ------ .../test/3/library-tests/web/django/Taint.ql | 14 --- .../web/django/django/__init__.py | 1 - .../web/django/django/conf/__init__.py | 1 - .../web/django/django/conf/urls.py | 3 - .../web/django/django/db/__init__.py | 1 - .../web/django/django/db/models/__init__.py | 2 - .../django/django/db/models/expressions.py | 2 - .../web/django/django/http/__init__.py | 2 - .../web/django/django/http/response.py | 5 -- .../test/3/library-tests/web/django/models.py | 10 --- .../test/3/library-tests/web/django/rawsql.py | 23 ----- .../test/3/library-tests/web/django/urls.py | 9 -- .../test/3/library-tests/web/django/views.py | 19 ---- python/ql/test/3/library-tests/web/options | 1 - .../library-tests/web/django/Sinks.expected | 28 +++--- .../library-tests/web/django/Sources.expected | 32 +++---- .../ql/test/library-tests/web/django/sql.py | 53 ++++++++++++ .../ql/test/library-tests/web/django/test.py | 86 +++---------------- .../ql/test/library-tests/web/django/views.py | 65 ++++++++++++++ .../Security/lib/django/conf/urls.py | 5 +- 25 files changed, 161 insertions(+), 264 deletions(-) delete mode 100644 python/ql/test/3/library-tests/web/django/Sinks.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Sinks.ql delete mode 100644 python/ql/test/3/library-tests/web/django/Sources.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Sources.ql delete mode 100644 python/ql/test/3/library-tests/web/django/Taint.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Taint.ql delete mode 100644 python/ql/test/3/library-tests/web/django/django/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/conf/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/conf/urls.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/models/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/models/expressions.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/http/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/http/response.py delete mode 100644 python/ql/test/3/library-tests/web/django/models.py delete mode 100644 python/ql/test/3/library-tests/web/django/rawsql.py delete mode 100644 python/ql/test/3/library-tests/web/django/urls.py delete mode 100644 python/ql/test/3/library-tests/web/django/views.py delete mode 100644 python/ql/test/3/library-tests/web/options create mode 100644 python/ql/test/library-tests/web/django/sql.py create mode 100644 python/ql/test/library-tests/web/django/views.py diff --git a/python/ql/test/3/library-tests/web/django/Sinks.expected b/python/ql/test/3/library-tests/web/django/Sinks.expected deleted file mode 100644 index b4142a2d82a..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.expected +++ /dev/null @@ -1,6 +0,0 @@ -| models.py:9 | key | externally controlled string | -| rawsql.py:4 | BinaryExpr | externally controlled string | -| rawsql.py:13 | BinaryExpr | externally controlled string | -| rawsql.py:18 | BinaryExpr | externally controlled string | -| rawsql.py:22 | BinaryExpr | externally controlled string | -| views.py:8 | Attribute() | externally controlled string | diff --git a/python/ql/test/3/library-tests/web/django/Sinks.ql b/python/ql/test/3/library-tests/web/django/Sinks.ql deleted file mode 100644 index db9b6a89b93..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.ql +++ /dev/null @@ -1,13 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Db -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Sources.expected b/python/ql/test/3/library-tests/web/django/Sources.expected deleted file mode 100644 index 965142343dc..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.expected +++ /dev/null @@ -1,8 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Sources.ql b/python/ql/test/3/library-tests/web/django/Sources.ql deleted file mode 100644 index 60d42cb2ac1..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.ql +++ /dev/null @@ -1,12 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Taint.expected b/python/ql/test/3/library-tests/web/django/Taint.expected deleted file mode 100644 index 3f40979c8a2..00000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.expected +++ /dev/null @@ -1,24 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute() | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | m | django.db.models.Model.objects | -| rawsql.py:18 | Attribute() | django.db.models.Model.objects | -| rawsql.py:18 | m | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | m | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | Attribute | django.http.request.QueryDict | -| views.py:8 | Attribute() | externally controlled string | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:8 | request | django.request.HttpRequest | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | -| views.py:12 | Dict | {externally controlled string} | -| views.py:12 | path | externally controlled string | -| views.py:13 | env | {externally controlled string} | -| views.py:13 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Taint.ql b/python/ql/test/3/library-tests/web/django/Taint.ql deleted file mode 100644 index b12a6560125..00000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.ql +++ /dev/null @@ -1,14 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - - -from TaintedNode node - -select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind().toString() - diff --git a/python/ql/test/3/library-tests/web/django/django/__init__.py b/python/ql/test/3/library-tests/web/django/django/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py b/python/ql/test/3/library-tests/web/django/django/conf/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/urls.py b/python/ql/test/3/library-tests/web/django/django/conf/urls.py deleted file mode 100644 index 580cc063d99..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/urls.py +++ /dev/null @@ -1,3 +0,0 @@ - -def url(regex, view): - pass \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py deleted file mode 100644 index eb9c72adc45..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -class Model: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py b/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py deleted file mode 100644 index d7e0d1c27b6..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py +++ /dev/null @@ -1,2 +0,0 @@ -class RawSQL: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/http/__init__.py b/python/ql/test/3/library-tests/web/django/django/http/__init__.py deleted file mode 100644 index e1a02f873cb..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -from .response import HttpResponse diff --git a/python/ql/test/3/library-tests/web/django/django/http/response.py b/python/ql/test/3/library-tests/web/django/django/http/response.py deleted file mode 100644 index f3dd53d15b0..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/response.py +++ /dev/null @@ -1,5 +0,0 @@ - -class HttpResponse: - - def __init__(self, *args): - pass diff --git a/python/ql/test/3/library-tests/web/django/models.py b/python/ql/test/3/library-tests/web/django/models.py deleted file mode 100644 index 571c594d055..00000000000 --- a/python/ql/test/3/library-tests/web/django/models.py +++ /dev/null @@ -1,10 +0,0 @@ - -from django.db import models - -class MyModel(models.Model): - title = models.CharField(max_length=500) - summary = models.TextField(blank=True) - -def update_my_model(key, title): - item = MyModel.objects.get(pk=key) - item.title = title diff --git a/python/ql/test/3/library-tests/web/django/rawsql.py b/python/ql/test/3/library-tests/web/django/rawsql.py deleted file mode 100644 index c6c82909c2d..00000000000 --- a/python/ql/test/3/library-tests/web/django/rawsql.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.db.models.expressions import RawSQL - -def raw1(arg): - return RawSQL("select foo from bar where baz = %s" % arg, "") - - -from django.db import models - -class MyModel(models.Model): - pass - -def raw2(arg): - MyModel.objects.raw("select foo from bar where baz = %s" % arg) - -def raw3(arg): - m = MyModel.objects.filter('foo') - m = m.filter('bar') - m.raw("select foo from bar where baz = %s" % arg) - -def raw4(arg): - m = MyModel.objects.filter('foo') - m.extra("select foo from bar where baz = %s" % arg) - diff --git a/python/ql/test/3/library-tests/web/django/urls.py b/python/ql/test/3/library-tests/web/django/urls.py deleted file mode 100644 index d5a941ae519..00000000000 --- a/python/ql/test/3/library-tests/web/django/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.conf.urls import url -import views - -urlpatterns = [ - - url(r'^route1$', views.view_func1), - url(r'^(?P.*)$', views.view_func2), - url(r'^route2$', views.ClassView.as_view()) -] diff --git a/python/ql/test/3/library-tests/web/django/views.py b/python/ql/test/3/library-tests/web/django/views.py deleted file mode 100644 index f7de60a23f6..00000000000 --- a/python/ql/test/3/library-tests/web/django/views.py +++ /dev/null @@ -1,19 +0,0 @@ - -from django.http import HttpResponse -from django.shortcuts import redirect, render -from django.views.generic import View - -def view_func1(request): - # Whether this is safe depends on template.html -- annoyingly - return HttpResponse(request.GET.get("untrusted")) - - -def view_func2(request, path='default'): - env = {'path': path} - return render(request, 'vulnerable-path.html', env) - - -class ClassView(View): - - def get(self, request): - pass diff --git a/python/ql/test/3/library-tests/web/options b/python/ql/test/3/library-tests/web/options deleted file mode 100644 index f2d60a4bc3c..00000000000 --- a/python/ql/test/3/library-tests/web/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 --lang=3 diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 31a42364762..86e05bca6dc 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -1,13 +1,15 @@ -| test.py:14 | Str | externally controlled string | -| test.py:15 | Str | externally controlled string | -| test.py:18 | BinaryExpr | externally controlled string | -| test.py:21 | BinaryExpr | externally controlled string | -| test.py:22 | BinaryExpr | externally controlled string | -| test.py:23 | BinaryExpr | externally controlled string | -| test.py:37 | Str | externally controlled string | -| test.py:44 | BinaryExpr | externally controlled string | -| test.py:48 | Attribute() | externally controlled string | -| test.py:59 | Attribute() | externally controlled string | -| test.py:70 | Attribute() | externally controlled string | -| test.py:73 | Attribute() | externally controlled string | -| test.py:76 | Attribute() | externally controlled string | +| sql.py:13 | Str | externally controlled string | +| sql.py:14 | Str | externally controlled string | +| sql.py:17 | BinaryExpr | externally controlled string | +| sql.py:20 | BinaryExpr | externally controlled string | +| sql.py:21 | BinaryExpr | externally controlled string | +| sql.py:22 | BinaryExpr | externally controlled string | +| sql.py:36 | Str | externally controlled string | +| sql.py:42 | BinaryExpr | externally controlled string | +| sql.py:47 | BinaryExpr | externally controlled string | +| views.py:7 | Attribute() | externally controlled string | +| views.py:11 | Attribute() | externally controlled string | +| views.py:15 | Attribute() | externally controlled string | +| views.py:22 | Attribute() | externally controlled string | +| views.py:27 | Attribute() | externally controlled string | +| views.py:31 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 371b1e7cb6f..a0c253b27c5 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,17 +1,17 @@ +| test.py:5 | path | externally controlled string | +| test.py:5 | request | django.request.HttpRequest | +| test.py:11 | path | externally controlled string | | test.py:11 | request | django.request.HttpRequest | -| test.py:11 | username | externally controlled string | -| test.py:41 | request | django.request.HttpRequest | -| test.py:47 | bar | externally controlled string | -| test.py:47 | foo | externally controlled string | -| test.py:47 | request | django.request.HttpRequest | -| test.py:58 | page_number | externally controlled string | -| test.py:58 | request | django.request.HttpRequest | -| test.py:69 | arg0 | externally controlled string | -| test.py:69 | request | django.request.HttpRequest | -| test.py:72 | arg0 | externally controlled string | -| test.py:72 | arg1 | externally controlled string | -| test.py:72 | arg2 | externally controlled string | -| test.py:72 | request | django.request.HttpRequest | -| test.py:75 | arg0 | externally controlled string | -| test.py:75 | arg1 | externally controlled string | -| test.py:75 | request | django.request.HttpRequest | +| views.py:6 | bar | externally controlled string | +| views.py:6 | foo | externally controlled string | +| views.py:6 | request | django.request.HttpRequest | +| views.py:10 | request | django.request.HttpRequest | +| views.py:14 | request | django.request.HttpRequest | +| views.py:25 | page_number | externally controlled string | +| views.py:25 | request | django.request.HttpRequest | +| views.py:30 | arg0 | externally controlled string | +| views.py:30 | arg1 | externally controlled string | +| views.py:30 | request | django.request.HttpRequest | +| views.py:50 | request | django.request.HttpRequest | +| views.py:50 | username | externally controlled string | +| views.py:59 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/sql.py b/python/ql/test/library-tests/web/django/sql.py new file mode 100644 index 00000000000..7809c24edc1 --- /dev/null +++ b/python/ql/test/library-tests/web/django/sql.py @@ -0,0 +1,53 @@ +from django.db import connection, models +from django.db.models.expressions import RawSQL + + +class User(models.Model): + username = models.CharField(max_length=100) + description = models.TextField(blank=True) + + +def show_user(username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) + + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) + + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) + + +def raw3(arg): + m = User.objects.filter('foo') + m = m.filter('bar') + m.raw("select foo from bar where baz = %s" % arg) + + +def raw4(arg): + m = User.objects.filter('foo') + m.extra("select foo from bar where baz = %s" % arg) + + +def update_user(key, description1): + # Neither of these are exposed to sql-injections + user = User.objects.get(pk=key) + item.description = description diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index 1240b9ae5a1..5664647c3a7 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -1,84 +1,18 @@ +from django.conf.urls import url +from django.shortcuts import redirect, render -from django.conf.urls import patterns, url -from django.db import connection, models -from django.db.models.expressions import RawSQL -from django.http.response import HttpResponse -import base64 -class User(models.Model): - pass +def with_template(request, path='default'): + env = {'path': path} + # We would need to understand django templates to know if this is safe or not + return render(request, 'possibly-vulnerable-template.html', env) -def show_user(request, username): - with connection.cursor() as cursor: - # GOOD -- Using parameters - cursor.execute("SELECT * FROM users WHERE username = %s", username) - User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - # BAD -- Using string formatting - cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) +def vuln_redirect(request, path): + return redirect(path) - # BAD -- other ways of executing raw SQL code with string interpolation - User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) - User.objects.raw("insert into names_file ('name') values ('%s')" % username) - User.objects.extra("insert into names_file ('name') values ('%s')" % username) - - # BAD (but currently no custom query to find this) - # - # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) - # For example, using name = "; DROP ALL TABLES -- " - # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' - # - # This shouldn't be very widespread, since using a normal string will result in invalid SQL - # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' - # which in MySQL will give a syntax error - # - # When testing this out locally, none of the queries worked against SQLite3, but I could use - # the SQL injection against MySQL. - User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) - -urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) - -def maybe_xss(request): - first_name = request.POST.get('first_name', '') - resp = HttpResponse() - resp.write("first name is " + first_name) - return resp - -def xss_kwargs(request, foo, bar, baz=None): - return HttpResponse('xss_kwargs: {} {}'.format(foo, bar)) urlpatterns = [ - url(r'^maybe_xss$', maybe_xss, name='maybe_xss'), - url(r'^bar/(?P[^/]+)/foo/(?P[^/]+)', xss_kwargs, name='xss_kwargs'), -] - - -# Non capturing group (we correctly identify page_number as a request parameter) - -def show_articles(request, page_number=1): - return HttpResponse('articles page: {}'.format(page_number)) - -urlpatterns = [ - # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 - url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), -] - - -# Positional arguments - -def xxs_positional_arg1(request, arg0): - return HttpResponse('xxs_positional_arg1: {}'.format(arg0)) - -def xxs_positional_arg2(request, arg0, arg1, arg2): - return HttpResponse('xxs_positional_arg2: {} {} {}'.format(arg0, arg1, arg2)) - -def xxs_positional_arg3(request, arg0, arg1): - return HttpResponse('xxs_positional_arg3: {} {}'.format(arg0, arg1)) - -urlpatterns = [ - # passing as positional argument is not the recommended way of doing things, - # but it is certainly possible - url(r'^(.+)$', xxs_positional_arg1, name='xxs_positional_arg1'), - url(r'^([^/]+)/([^/]+)/([^/]+)$', xxs_positional_arg2, name='xxs_positional_arg2'), - url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg3, name='xxs_positional_arg3'), + url(r'^(?P.*)$', with_template), + url(r'^redirect/(?P.*)$', vuln_redirect), ] diff --git a/python/ql/test/library-tests/web/django/views.py b/python/ql/test/library-tests/web/django/views.py new file mode 100644 index 00000000000..ffa49118785 --- /dev/null +++ b/python/ql/test/library-tests/web/django/views.py @@ -0,0 +1,65 @@ +from django.conf.urls import patterns, url +from django.http.response import HttpResponse +from django.views.generic import View + + +def url_match_xss(request, foo, bar, no_taint=None): + return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) + + +def get_params_xss(request): + return HttpResponse(request.GET.get("untrusted")) + + +def post_params_xss(request): + return HttpResponse(request.POST.get("untrusted")) + + +class ClassView(View): + + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def get(self, request, untrusted): + return HttpResponse('ClassView: {}'.format(untrusted)) + + +def show_articles(request, page_number=1): + page_number = int(page_number) + return HttpResponse('articles page: {}'.format(page_number)) + + +def xxs_positional_arg(request, arg0, arg1, no_taint=None): + return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) + + +urlpatterns = [ + url(r'^url_match/(?P[^/]+)/(?P[^/]+)$', url_match_xss), + url(r'^get_params$', get_params_xss), + url(r'^post_params$', post_params_xss), + url(r'^class_view/(?P.+)$', ClassView.as_view()), + + # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 + url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), + # passing as positional argument is not the recommended way of doing things, but it is certainly + # possible + url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg, name='xxs_positional_arg'), +] + + +# Using patterns() for routing + +def show_user(request, username): + pass + + +urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) + + +# Show we understand the keyword arguments to django.conf.urls.url + +def we_understand_url_kwargs(request): + pass + + +urlpatterns = [ + url(view=we_understand_url_kwargs, regex=r'^specifying-as-kwargs-is-not-a-problem$') +] diff --git a/python/ql/test/query-tests/Security/lib/django/conf/urls.py b/python/ql/test/query-tests/Security/lib/django/conf/urls.py index cf65525e893..6c1a83baf0b 100644 --- a/python/ql/test/query-tests/Security/lib/django/conf/urls.py +++ b/python/ql/test/query-tests/Security/lib/django/conf/urls.py @@ -1,7 +1,6 @@ - -def url(pattern, *args): +# https://docs.djangoproject.com/en/1.11/_modules/django/conf/urls/#url +def url(regex, view, kwargs=None, name=None): pass def patterns(*urls): pass - From fc851b46c3d41cda88ecfecd8c35821d96ac7222 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 21 Oct 2019 16:44:35 +0200 Subject: [PATCH 075/232] Python: Fix Django class-based views --- .../src/semmle/python/web/django/Request.qll | 2 +- .../library-tests/web/django/Sinks.expected | 7 ++++--- .../library-tests/web/django/Sources.expected | 18 ++++++++++-------- .../ql/test/library-tests/web/django/views.py | 11 +++++++++-- .../Security/lib/django/views/__init__.py | 0 .../Security/lib/django/views/generic.py | 2 ++ 6 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 python/ql/test/query-tests/Security/lib/django/views/__init__.py create mode 100644 python/ql/test/query-tests/Security/lib/django/views/generic.py diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index 15ea032e6d7..24a29ea4542 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -67,7 +67,7 @@ private class DjangoView extends ClassValue { } private FunctionValue djangoViewHttpMethod() { - exists(DjangoView view | view.attr(httpVerbLower()) = result) + exists(DjangoView view | view.lookup(httpVerbLower()) = result) } class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 86e05bca6dc..e3d233c9990 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -10,6 +10,7 @@ | views.py:7 | Attribute() | externally controlled string | | views.py:11 | Attribute() | externally controlled string | | views.py:15 | Attribute() | externally controlled string | -| views.py:22 | Attribute() | externally controlled string | -| views.py:27 | Attribute() | externally controlled string | -| views.py:31 | Attribute() | externally controlled string | +| views.py:23 | Attribute() | externally controlled string | +| views.py:29 | Attribute() | externally controlled string | +| views.py:34 | Attribute() | externally controlled string | +| views.py:38 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index a0c253b27c5..35e0d3d8ced 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -7,11 +7,13 @@ | views.py:6 | request | django.request.HttpRequest | | views.py:10 | request | django.request.HttpRequest | | views.py:14 | request | django.request.HttpRequest | -| views.py:25 | page_number | externally controlled string | -| views.py:25 | request | django.request.HttpRequest | -| views.py:30 | arg0 | externally controlled string | -| views.py:30 | arg1 | externally controlled string | -| views.py:30 | request | django.request.HttpRequest | -| views.py:50 | request | django.request.HttpRequest | -| views.py:50 | username | externally controlled string | -| views.py:59 | request | django.request.HttpRequest | +| views.py:22 | request | django.request.HttpRequest | +| views.py:28 | request | django.request.HttpRequest | +| views.py:32 | page_number | externally controlled string | +| views.py:32 | request | django.request.HttpRequest | +| views.py:37 | arg0 | externally controlled string | +| views.py:37 | arg1 | externally controlled string | +| views.py:37 | request | django.request.HttpRequest | +| views.py:57 | request | django.request.HttpRequest | +| views.py:57 | username | externally controlled string | +| views.py:66 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/views.py b/python/ql/test/library-tests/web/django/views.py index ffa49118785..57d1ea5460c 100644 --- a/python/ql/test/library-tests/web/django/views.py +++ b/python/ql/test/library-tests/web/django/views.py @@ -15,11 +15,18 @@ def post_params_xss(request): return HttpResponse(request.POST.get("untrusted")) -class ClassView(View): +class Foo(object): + # Note: since Foo is used as the super type in a class view, it will be able to handle requests. + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def post(self, request, untrusted): + return HttpResponse('Foo post: {}'.format(untrusted)) + + +class ClassView(View, Foo): # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter def get(self, request, untrusted): - return HttpResponse('ClassView: {}'.format(untrusted)) + return HttpResponse('ClassView get: {}'.format(untrusted)) def show_articles(request, page_number=1): diff --git a/python/ql/test/query-tests/Security/lib/django/views/__init__.py b/python/ql/test/query-tests/Security/lib/django/views/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/query-tests/Security/lib/django/views/generic.py b/python/ql/test/query-tests/Security/lib/django/views/generic.py new file mode 100644 index 00000000000..d924b03d062 --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/django/views/generic.py @@ -0,0 +1,2 @@ +class View: + pass From 63f24476e96771b0d557d3b7c2c01c547068d511 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 08:29:10 +0000 Subject: [PATCH 076/232] JavaScript: Refactor `DoubleEscaping.ql`. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 62 ++++++++++++------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index a150a2d7a7a..124dcf304aa 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -62,30 +62,23 @@ predicate escapingScheme(string metachar, string regex) { } /** - * A call to `String.prototype.replace` that replaces all instances of a pattern. + * A method call that performs string replacement. */ -class Replacement extends DataFlow::Node { - RegExpLiteral pattern; - - Replacement() { - exists(DataFlow::MethodCallNode mcn | this = mcn | - mcn.getMethodName() = "replace" and - pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0)) and - mcn.getNumArgument() = 2 and - pattern.isGlobal() - ) - } - +abstract class Replacement extends DataFlow::Node { /** * Holds if this replacement replaces the string `input` with `output`. */ - predicate replaces(string input, string output) { - exists(DataFlow::MethodCallNode mcn | - mcn = this and - input = getStringValue(pattern) and - output = mcn.getArgument(1).getStringValue() - ) - } + abstract predicate replaces(string input, string output); + + /** + * Gets the input of this replacement. + */ + abstract DataFlow::Node getInput(); + + /** + * Gets the output of this replacement. + */ + abstract DataFlow::SourceNode getOutput(); /** * Holds if this replacement escapes `char` using `metachar`. @@ -119,7 +112,7 @@ class Replacement extends DataFlow::Node { * Gets the previous replacement in this chain of replacements. */ Replacement getPreviousReplacement() { - result = getASimplePredecessor*(this.(DataFlow::MethodCallNode).getReceiver()) + result.getOutput() = getASimplePredecessor*(getInput()) } /** @@ -147,6 +140,33 @@ class Replacement extends DataFlow::Node { } } +/** + * A call to `String.prototype.replace` that replaces all instances of a pattern. + */ +class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { + RegExpLiteral pattern; + + GlobalStringReplacement() { + this.getMethodName() = "replace" and + pattern.flow().(DataFlow::SourceNode).flowsTo(this.getArgument(0)) and + this.getNumArgument() = 2 and + pattern.isGlobal() + } + + override predicate replaces(string input, string output) { + input = getStringValue(pattern) and + output = this.getArgument(1).getStringValue() + } + + override DataFlow::Node getInput() { + result = this.getReceiver() + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and From bd1c99d8a428770a12c90450ce3518854427b352 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 09:35:49 +0000 Subject: [PATCH 077/232] JavaScript: Recognise `JSON.stringify` and `JSON.parse` as escaper/unescaper. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 46 +++++++++++++++++++ .../DoubleEscaping/DoubleEscaping.expected | 2 + .../Security/CWE-116/DoubleEscaping/tst.js | 20 ++++++++ 3 files changed, 68 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 124dcf304aa..589a935d5fe 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -167,6 +167,52 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { } } +/** + * A call to `JSON.stringify`, viewed as a string replacement. + */ +class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { + JsonStringifyReplacement() { + this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") + } + + override predicate replaces(string input, string output) { + input = "\\" and output = "\\\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { + result = this.getArgument(0) + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + +/** + * A call to `JSON.parse`, viewed as a string replacement. + */ +class JsonParseReplacement extends Replacement { + JsonParserCall self; + + JsonParseReplacement() { + this = self + } + + override predicate replaces(string input, string output) { + input = "\\\\" and output = "\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { + result = self.getInput() + } + + override DataFlow::SourceNode getOutput() { + result = self.getOutput() + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d4930ad07cf..e3d5a9a4252 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -5,3 +5,5 @@ | tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here | | tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here | | tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here | +| tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | +| tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 19ab94d2691..ee9cd930b6f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -69,3 +69,23 @@ function badEncode(s) { .replace(indirect2, "'") .replace(indirect3, "&"); } + +function badEscape1(s) { + return JSON.stringify( + s.replace(//g, "\\u003E") + ); +} + +function goodEscape1(s) { + return JSON.stringify(s) + .replace(//g, "\\u003E"); +} + +function badUnescape2(s) { + return JSON.parse(s).replace(/\\u003C/g, "<").replace(/\\u003E/g, ">"); +} + +function goodUnescape2(s) { + return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">")); +} From aaeca325193deedc7ac8ea163cbe574514d44b94 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 09:55:28 +0000 Subject: [PATCH 078/232] JavaScript: Recognize string escaping using `.replace` with a callback. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 8 ++++++++ .../CWE-116/DoubleEscaping/DoubleEscaping.expected | 1 + .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 589a935d5fe..4e6969e54c3 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -156,6 +156,14 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { override predicate replaces(string input, string output) { input = getStringValue(pattern) and output = this.getArgument(1).getStringValue() + or + exists(DataFlow::FunctionNode replacer, DataFlow::PropRead pr, DataFlow::ObjectLiteralNode map | + replacer = getCallback(1) and + replacer.getParameter(0).flowsToExpr(pr.getPropertyNameExpr()) and + pr = map.getAPropertyRead() and + pr.flowsTo(replacer.getAReturn()) and + map.asExpr().(ObjectExpr).getPropertyByName(input).getInit().getStringValue() = output + ) } override DataFlow::Node getInput() { diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index e3d5a9a4252..d7e2b558a06 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -7,3 +7,4 @@ | tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here | | tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | +| tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index ee9cd930b6f..78c73ce9584 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -89,3 +89,12 @@ function badUnescape2(s) { function goodUnescape2(s) { return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">")); } + +function badEncodeWithReplacer(s) { + var repl = { + '"': """, + "'": "'", + "&": "&" + }; + return s.replace(/["']/g, (c) => repl[c]).replace(/&/g, "&"); +} From 02d16b1dc99ddbcb3b2c8148b0cb53731214b039 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 10:59:04 +0000 Subject: [PATCH 079/232] JavaScript: Recognise wrapped string replacement functions. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 28 +++++++++++++++++++ .../DoubleEscaping/DoubleEscaping.expected | 1 + .../Security/CWE-116/DoubleEscaping/tst.js | 8 ++++++ 3 files changed, 37 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 4e6969e54c3..733afad0b06 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -221,6 +221,34 @@ class JsonParseReplacement extends Replacement { } } +/** + * A string replacement wrapped in a utility function. + */ +class WrappedReplacement extends Replacement, DataFlow::CallNode { + int i; + + Replacement inner; + + WrappedReplacement() { + exists(DataFlow::FunctionNode wrapped | wrapped.getFunction() = getACallee() | + wrapped.getParameter(i).flowsTo(inner.getInput()) and + inner.getOutput().flowsTo(wrapped.getAReturn()) + ) + } + + override predicate replaces(string input, string output) { + inner.replaces(input, output) + } + + override DataFlow::Node getInput() { + result = getArgument(i) + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d7e2b558a06..d0747087d12 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -8,3 +8,4 @@ | tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | | tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | +| tst.js:107:10:107:53 | encodeD ... &") | This replacement may double-escape '&' characters from $@. | tst.js:107:10:107:30 | encodeD ... otes(s) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 78c73ce9584..d88422e74a4 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -98,3 +98,11 @@ function badEncodeWithReplacer(s) { }; return s.replace(/["']/g, (c) => repl[c]).replace(/&/g, "&"); } + +function encodeDoubleQuotes(s) { + return s.replace(/"/g, """); +} + +function badWrappedEncode(s) { + return encodeDoubleQuotes(s).replace(/&/g, "&"); +} From 5349e0f88142ae4e7a63038fa3238b5001e0972d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 13:02:59 +0000 Subject: [PATCH 080/232] JavaScript: Recognise wrapped chains of replacements. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 11 +++++++++-- .../CWE-116/DoubleEscaping/DoubleEscaping.expected | 1 + .../Security/CWE-116/DoubleEscaping/tst.js | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 733afad0b06..2fc91a9854d 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -115,6 +115,13 @@ abstract class Replacement extends DataFlow::Node { result.getOutput() = getASimplePredecessor*(getInput()) } + /** + * Gets the next replacement in this chain of replacements. + */ + Replacement getNextReplacement() { + this = result.getPreviousReplacement() + } + /** * Gets an earlier replacement in this chain of replacements that * performs an escaping. @@ -231,8 +238,8 @@ class WrappedReplacement extends Replacement, DataFlow::CallNode { WrappedReplacement() { exists(DataFlow::FunctionNode wrapped | wrapped.getFunction() = getACallee() | - wrapped.getParameter(i).flowsTo(inner.getInput()) and - inner.getOutput().flowsTo(wrapped.getAReturn()) + wrapped.getParameter(i).flowsTo(inner.getPreviousReplacement*().getInput()) and + inner.getNextReplacement*().getOutput().flowsTo(wrapped.getAReturn()) ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d0747087d12..23e5a4a6b05 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -9,3 +9,4 @@ | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | | tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | | tst.js:107:10:107:53 | encodeD ... &") | This replacement may double-escape '&' characters from $@. | tst.js:107:10:107:30 | encodeD ... otes(s) | here | +| tst.js:115:10:115:47 | encodeQ ... &") | This replacement may double-escape '&' characters from $@. | tst.js:115:10:115:24 | encodeQuotes(s) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index d88422e74a4..628166ed04a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -106,3 +106,11 @@ function encodeDoubleQuotes(s) { function badWrappedEncode(s) { return encodeDoubleQuotes(s).replace(/&/g, "&"); } + +function encodeQuotes(s) { + return s.replace(/"/g, """).replace(/'/g, "'"); +} + +function badWrappedEncode2(s) { + return encodeQuotes(s).replace(/&/g, "&"); +} From a8214ce7ee070ad082430a6ea0140548ea1b0799 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:15:59 +0000 Subject: [PATCH 081/232] JavaScript: Fix regexes for escaping schemes. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 6 +++--- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 2fc91a9854d..5d5157bafb3 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -54,11 +54,11 @@ DataFlow::Node getASimplePredecessor(DataFlow::Node nd) { * into a form described by regular expression `regex`. */ predicate escapingScheme(string metachar, string regex) { - metachar = "&" and regex = "&.*;" + metachar = "&" and regex = "&.+;" or - metachar = "%" and regex = "%.*" + metachar = "%" and regex = "%.+" or - metachar = "\\" and regex = "\\\\.*" + metachar = "\\" and regex = "\\\\.+" } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 628166ed04a..e05779eeb7a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -114,3 +114,12 @@ function encodeQuotes(s) { function badWrappedEncode2(s) { return encodeQuotes(s).replace(/&/g, "&"); } + +function roundtrip(s) { + return JSON.parse(JSON.stringify(s)); +} + +// dubious, but out of scope for this query +function badRoundtrip(s) { + return s.replace(/\\\\/g, "\\").replace(/\\/g, "\\\\"); +} From 8c133ff61d873b574ff0fef778f5248f8c4b11d9 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:46:50 +0000 Subject: [PATCH 082/232] JavaScript: Deal with (un-)escaping on captured variables. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 7 ++++++- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 5d5157bafb3..b6d76956630 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -46,7 +46,12 @@ string getStringValue(RegExpLiteral rl) { */ DataFlow::Node getASimplePredecessor(DataFlow::Node nd) { result = nd.getAPredecessor() and - not nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition() instanceof SsaPhiNode + not exists(SsaDefinition ssa | + ssa = nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition() + | + ssa instanceof SsaPhiNode or + ssa instanceof SsaVariableCapture + ) } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index e05779eeb7a..7b840e2be08 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -123,3 +123,10 @@ function roundtrip(s) { function badRoundtrip(s) { return s.replace(/\\\\/g, "\\").replace(/\\/g, "\\\\"); } + +function testWithCapturedVar(x) { + var captured = x; + (function() { + captured = captured.replace(/\\/g, "\\\\"); + })(); +} From bb0771b36c3065c60dd4aa3f04a481b241ff9c86 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:49:01 +0000 Subject: [PATCH 083/232] JavaScript: Deal with escape-unescape-escape (and similar) chains. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 8 ++++++-- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index b6d76956630..db8624458b7 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -135,7 +135,9 @@ abstract class Replacement extends DataFlow::Node { exists(Replacement pred | pred = this.getPreviousReplacement() | if pred.escapes(_, metachar) then result = pred - else result = pred.getAnEarlierEscaping(metachar) + else ( + not pred.unescapes(metachar, _) and result = pred.getAnEarlierEscaping(metachar) + ) ) } @@ -147,7 +149,9 @@ abstract class Replacement extends DataFlow::Node { exists(Replacement succ | this = succ.getPreviousReplacement() | if succ.unescapes(metachar, _) then result = succ - else result = succ.getALaterUnescaping(metachar) + else ( + not succ.escapes(_, metachar) and result = succ.getALaterUnescaping(metachar) + ) ) } } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 7b840e2be08..9c69c837f6b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -130,3 +130,7 @@ function testWithCapturedVar(x) { captured = captured.replace(/\\/g, "\\\\"); })(); } + +function cloneAndStringify(s) { + return JSON.stringify(JSON.parse(JSON.stringify(s))); +} From 3bbded57d3c45c1adc1056d23c3c74f0ffb38568 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:49:18 +0000 Subject: [PATCH 084/232] JavaScript: Autoformat. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 52 +++++-------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index db8624458b7..6340a2fcedc 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -116,16 +116,12 @@ abstract class Replacement extends DataFlow::Node { /** * Gets the previous replacement in this chain of replacements. */ - Replacement getPreviousReplacement() { - result.getOutput() = getASimplePredecessor*(getInput()) - } + Replacement getPreviousReplacement() { result.getOutput() = getASimplePredecessor*(getInput()) } /** * Gets the next replacement in this chain of replacements. */ - Replacement getNextReplacement() { - this = result.getPreviousReplacement() - } + Replacement getNextReplacement() { this = result.getPreviousReplacement() } /** * Gets an earlier replacement in this chain of replacements that @@ -182,35 +178,25 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { ) } - override DataFlow::Node getInput() { - result = this.getReceiver() - } + override DataFlow::Node getInput() { result = this.getReceiver() } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } /** * A call to `JSON.stringify`, viewed as a string replacement. */ class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { - JsonStringifyReplacement() { - this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") - } + JsonStringifyReplacement() { this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") } override predicate replaces(string input, string output) { input = "\\" and output = "\\\\" // the other replacements are not relevant for this query } - override DataFlow::Node getInput() { - result = this.getArgument(0) - } + override DataFlow::Node getInput() { result = this.getArgument(0) } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } /** @@ -219,22 +205,16 @@ class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { class JsonParseReplacement extends Replacement { JsonParserCall self; - JsonParseReplacement() { - this = self - } + JsonParseReplacement() { this = self } override predicate replaces(string input, string output) { input = "\\\\" and output = "\\" // the other replacements are not relevant for this query } - override DataFlow::Node getInput() { - result = self.getInput() - } + override DataFlow::Node getInput() { result = self.getInput() } - override DataFlow::SourceNode getOutput() { - result = self.getOutput() - } + override DataFlow::SourceNode getOutput() { result = self.getOutput() } } /** @@ -252,17 +232,11 @@ class WrappedReplacement extends Replacement, DataFlow::CallNode { ) } - override predicate replaces(string input, string output) { - inner.replaces(input, output) - } + override predicate replaces(string input, string output) { inner.replaces(input, output) } - override DataFlow::Node getInput() { - result = getArgument(i) - } + override DataFlow::Node getInput() { result = getArgument(i) } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } from Replacement primary, Replacement supplementary, string message, string metachar From 8620b0513efa171a2713c08f8fdde5576b73078a Mon Sep 17 00:00:00 2001 From: yh-semmle Date: Wed, 30 Oct 2019 11:18:36 -0400 Subject: [PATCH 085/232] Java: move `UnsafeDeserialization.qll` to standard library location --- java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql | 2 +- .../code/java/security}/UnsafeDeserialization.qll | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/{Security/CWE/CWE-502 => semmle/code/java/security}/UnsafeDeserialization.qll (100%) diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql index 18cf624375f..bb4df03cd4f 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql @@ -12,7 +12,7 @@ import java import semmle.code.java.dataflow.FlowSources -import UnsafeDeserialization +import semmle.code.java.security.UnsafeDeserialization import DataFlow::PathGraph class UnsafeDeserializationConfig extends TaintTracking::Configuration { diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll similarity index 100% rename from java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll rename to java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll From 27d0b51c6b4eabc891c71eb8952874c07932c7e3 Mon Sep 17 00:00:00 2001 From: alistair Date: Wed, 30 Oct 2019 16:10:03 +0000 Subject: [PATCH 086/232] CPP & C#: Review of qhelp PR #2151 got merged without a review of the qhelp by a technical writer. The current PR makes changes I would have suggested on that PR. --- .../NtohlArrayNoBoundOpenSource.qhelp | 2 +- .../ConditionallyUninitializedVariable.qhelp | 2 +- .../ConditionallyUninitializedVariable.ql | 2 +- .../CWE-091/XMLInjection.qhelp | 4 ++-- .../CWE-114/AssemblyPathInjection.qhelp | 6 ++--- .../CWE-321/HardcodedEncryptionKey.ql | 4 ++-- .../CWE-327/InsecureSQLConnection.qhelp | 22 +++++++++---------- .../CWE-327/InsecureSQLConnection.ql | 2 +- 8 files changed, 21 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp index 522d6cde74c..fc8f309f73a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp @@ -14,7 +14,7 @@ byte order function, such as ntohl. The use of a network-to-host byte order function is therefore a good indicator that the returned value is unvalidated data retrieved from the network, and should not be used without further validation. In particular, the returned value should not be used as an array index or array length -value without validation, which may result in a buffer overflow vulnerability. +value without validation, as this could result in a buffer overflow vulnerability.

    diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp index b9118edc736..8e6a8903483 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp @@ -37,7 +37,7 @@ which is then subsequently accessed to fetch properties of the device. However, check the return value from the function call to initDeviceConfig. If the device number passed to the notify function was invalid, the initDeviceConfig function will leave the config variable uninitialized, -which would result in the notify function accessing uninitialized memory.

    +which will result in the notify function accessing uninitialized memory.

    diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql index eb00fb9ea10..f9eb2fe5400 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql @@ -2,7 +2,7 @@ * @name Conditionally uninitialized variable * @description When an initialization function is used to initialize a local variable, but the * returned status code is not checked, the variable may be left in an uninitialized - * state, and reading the variable may result in undefined behaviour. + * state, and reading the variable may result in undefined behavior. * @kind problem * @problem.severity warning * @opaque-id SM02313 diff --git a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp index 4e70b06531a..3aff9901bfc 100644 --- a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp @@ -36,10 +36,10 @@ which ensures the content is appropriately escaped.

  • - XML Injection (The Web Application Security Consortium). + Web Application Security Consortium: XML Injection.
  • - WriteRaw (Microsoft documentation). + Microsoft Docs: WriteRaw.
  • diff --git a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp index 5f95181c092..e1dbe9c1bd0 100644 --- a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp @@ -14,7 +14,7 @@ was not intended to be loaded, and executing arbitrary code.

    Avoid loading assemblies based on user provided input. If this is not possible, ensure that the path is validated before being used with Assembly. For example, compare the provided input -against a whitelist of known safe assemblies, or confirm that path is restricted to a single +against a whitelist of known safe assemblies, or confirm that the path is restricted to a single directory which only contains safe assemblies.

    @@ -30,8 +30,8 @@ is only loaded if the user input matches one of those options.

    -
  • - System.Reflection.Assembly (Microsoft documentation). +
  • Microsoft: + System.Reflection.Assembly.
  • diff --git a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql index c09a67d756c..cce122ffa62 100644 --- a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql +++ b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql @@ -1,6 +1,6 @@ /** - * @name Do not use hard-coded encryption keys. - * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hardcoded value. + * @name Hard-coded encryption key + * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hard-coded value. * @kind problem * @id cs/hardcoded-key * @problem.severity error diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp index ae69402eb7e..c59feeed61c 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp @@ -3,7 +3,6 @@ "qhelp.dtd"> -

    Finds uses of insecure SQL Connections string by not enabling the Encrypt option.

    SQL Server connections where the client is not enforcing the encryption in transit are susceptible to multiple attacks, including a man-in-the-middle, that would potentially compromise the user credentials and/or the TDS session. @@ -29,18 +28,17 @@ - -

  • - Selectively using secure connection to SQL Server +
  • Microsoft, SQL Protocols blog: + Selectively using secure connection to SQL Server.
  • -
  • - Net SqlClient (ADO .Net) +
  • Microsoft: + SqlConnection.ConnectionString Property. +
  • +
  • Microsoft: + Using Connection String Keywords with SQL Server Native Client. +
  • +
  • Microsoft: + Setting the connection properties.
  • -
  • SQL native driver (SNAC) -
  • -
  • - JDBC driver -
  • -
    diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index 0f855150aa9..78bcc1c19e5 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -1,6 +1,6 @@ /** * @name Insecure SQL connection - * @description TODO. + * @description Using an SQL Server connection without enforcing encryption is a security vulnerability. * @kind path-problem * @id cs/insecure-sql-connection * @problem.severity error From 03c9a40ba35db5be5e635703db8b2ab82beca909 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 22 Oct 2019 09:32:51 +0100 Subject: [PATCH 087/232] JavaScript: Add libraries for forward and backward data-flow exploration. --- .../dataflow/BackwardExploration.qll | 44 +++++++++++++++++++ .../dataflow/ForwardExploration.qll | 42 ++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll create mode 100644 javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll new file mode 100644 index 00000000000..caf67e6db7f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll @@ -0,0 +1,44 @@ +/** + * Provides machinery for performing backward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSource` predicate. Instead, flow is tracked from any _initial node_ (that is, + * a node without incoming flow) to a sink node. All initial nodes are then treated as source + * nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. Backward + * exploration in particular does not scale on non-trivial code bases and hence is of limited + * usefulness as it stands. + */ + +import javascript + +private class BackwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + BackwardExploringConfiguration() { + this = cfg + } + + override predicate isSource(DataFlow::Node node) { any() } + + override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode first | + source.getConfiguration() = this and + source.getASuccessor() = first and + not exists(DataFlow::MidPathNode mid | mid.getASuccessor() = first) and + first.getASuccessor*() = sink + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll new file mode 100644 index 00000000000..0e3a7ae91c2 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll @@ -0,0 +1,42 @@ +/** + * Provides machinery for performing forward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSink` predicate. Instead, flow is tracked from source nodes as far as + * possible, until a _terminal node_ (that is, a node without any outgoing flow) is reached. + * All terminal nodes are then treated as sink nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. + */ + +import javascript + +private class ForwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + ForwardExploringConfiguration() { + this = cfg + } + + override predicate isSink(DataFlow::Node node) { any() } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode last | + source.getConfiguration() = this and + source.getASuccessor*() = last and + not last.getASuccessor() instanceof DataFlow::MidPathNode and + last.getASuccessor() = sink + ) + } +} From 3e1fd4a737549a47d322a47a3bf28720989ffceb Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 31 Oct 2019 18:03:34 -0700 Subject: [PATCH 088/232] [CPP-434] Add table of constructs to Qhelp. Rewrite examples section. --- change-notes/1.23/analysis-cpp.md | 2 +- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 2 +- .../Arithmetic/SignedOverflowCheck-good1.cpp | 5 +- .../Arithmetic/SignedOverflowCheck-good2.cpp | 4 +- .../Arithmetic/SignedOverflowCheck.qhelp | 124 +++++++++++++++--- 5 files changed, 110 insertions(+), 27 deletions(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index b3e16dcc29a..f98e3c7fef1 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,7 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | -| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which is undefined behavior. Example: `a + b < a`. | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. | ## Changes to existing queries diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp index d4d9cd75393..7f69e374ed1 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -1,4 +1,4 @@ bool bar(unsigned short n1, unsigned short delta) { // NB: Comparison is always false - return n1 + delta < n1; // GOOD + return n1 + delta < n1; // GOOD (but misleading) } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp index 2209b8bff71..424684ee2ec 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -1,3 +1,4 @@ -bool baf(unsigned short n1, unsigned short delta) { - return (unsigned short)(n1 + delta) < n1; // GOOD +#include +bool foo(int n1, unsigned short delta) { + return n1 > INT_MAX - delta; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp index cccc66b71f8..de8de2b9847 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp @@ -1,3 +1,3 @@ -bool baz(int n1, int delta) { - return (unsigned)n1 + delta < n1; // GOOD +bool bar(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index ae4dae55016..da7f86f021b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,11 +4,11 @@

    -When checking for integer overflow, one often writes tests like +When checking for integer overflow, you may often write tests like a + b < a. This works fine if a or b are unsigned integers, since any overflow in the addition -will cause the value to simply "wrap around". However, using -signed integers is problematic because signed overflows have undefined +will cause the value to simply "wrap around." However, using +signed integers is problematic because signed overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an @@ -17,10 +17,89 @@ optimizing compiler.

    -When checking for overflow by adding two values, first make sure that a -or b are (converted into) unsigned values, unless it is -certain that the signed addition cannot overflow. +Solutions to this problem can be thought of as falling into one of two +categories: (1) rewrite the signed expression so that overflow cannot occur +but the signedness remains, or (2) rewrite (or cast) the signed expression +into unsigned form. + +The table below lists various expressions where signed overflow may +occur, along with proposed rewritings. It should not be +considered as exhaustive.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Original ConstructAlternate Construct(s)Notes
    + + + + + +
    unsigned short i, delta;
    i + delta < i
    + + + + + +
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      + + + + + +
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climits
    + + + + + +
    int i, delta;
    i + delta < i
    + + + + + +
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climits
      + + + + + +
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      + + + + + +
    unsigned int i, delta;
    i + delta < i
    Change in program semantics

    @@ -34,6 +113,17 @@ result.

    +The following example builds upon the previous one. Instead of +performing an addition (which could overflow), we have re-framed the +solution so that a subtraction is used instead. Since delta +is promoted to a signed int and INT_MAX denotes +the largest possible positive value for an signed int, +the expression INT_MAX - delta can never be less than zero +or more than INT_MAX. Hence, any overflow and underflow +are avoided. +

    + +

    In the following example, even though both n and delta have been declared unsigned short, both are promoted to signed int prior to addition. Because we started out with the @@ -45,26 +135,18 @@ hold true, which likely is not what the programmer intended. (see also the

    -The following example builds upon the previous one. Again, we have two -unsigned short values getting promoted to a wider type, resulting -in a comparison that always succeeds (since there is no overflow). To -test whether we have an unsigned short overflow, we cast the -left-hand side to it, causing the right-hand side to remain an unsigned -short as well. -

    - -

    -In the next example, we have two signed int values that we -wish to add together. Adding them "as-is" opens the possibility of -a signed integer overflow, the results of which are undefined. -By casting one of the operands to unsigned, the entire -expression is evaluated using unsigned -values, which is defined behavior per the C/C++ standard. +The next example provides a solution to the previous one. Even though +i + delta does not overflow, casting it to an +unsigned short truncates the addition modulo 2^16, +so that unsigned short "wrap around" may now be observed. +Furthermore, since the left-hand side is now of type unsigned short, +the right-hand side does not need to be promoted to a signed int.

  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • +
  • W. Dietz,∗ P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • From 02bb142e7c6b3d8df058b60139504c1ead6b39e7 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:05:13 +0000 Subject: [PATCH 089/232] Update repository artifacts for name change --- CONTRIBUTING.md | 14 +++++++------- README.md | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c0714571fc..e074b1c2079 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to QL +# Contributing to CodeQL We welcome contributions to our standard library and standard checks. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! @@ -9,13 +9,13 @@ Before we accept your pull request, we require that you have agreed to our Contr If you have an idea for a query that you would like to share with other Semmle users, please open a pull request to add it to this repository. Follow the steps below to help other users understand what your query does, and to ensure that your query is consistent with the other Semmle queries. -1. **Consult the QL documentation for query writers** +1. **Consult the documentation for query writers** - There is lots of useful documentation to help you write QL, ranging from information about query file structure to language-specific tutorials. For more information on the documentation available, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). + There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). -2. **Format your QL correctly** +2. **Format your code correctly** - All of Semmle's standard QL queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all QL contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). + All of Semmle's standard queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). 3. **Make sure your query has the correct metadata** @@ -29,7 +29,7 @@ Follow the steps below to help other users understand what your query does, and The `select` statement of your query must be compatible with the query type (determined by the `@kind` metadata property) for alert or path results to be displayed correctly in LGTM and QL for Eclipse. For more information on `select` statement format, see [Introduction to query files](https://help.semmle.com/QL/learn-ql/writing-queries/introduction-to-queries.html#select-clause) on help.semmle.com. -5. **Save your query in a `.ql` file in correct language directory in this repository** +5. **Save your query in a `.ql` file in the correct language directory in this repository** There are five language-specific directories in this repository: @@ -54,7 +54,7 @@ repositories, which might be made public. We might also use this information to contact you in relation to your contributions, as well as in the normal course of software development. We also store records of your CLA agreements. Under GDPR legislation, we do this -on the basis of our legitimate interest in creating the QL product. +on the basis of our legitimate interest in creating the CodeQL product. Please do get in touch (privacy@semmle.com) if you have any questions about this or our data protection policies. diff --git a/README.md b/README.md index b483d29cae2..a6aa5e38f1a 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# Semmle QL +# CodeQL -This open source repository contains the standard QL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. +This open source repository contains the standard CodeQL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. -## How do I learn QL and run queries? +## How do I learn CodeQL and run queries? -There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing QL. +There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL. You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open-source project that's currently being analyzed. ## Contributing -We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your QL for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. +We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. ## License -The QL queries in this repository are licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). +The code in this repository is licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). From 570e55190dda6e94d8080760f0987f6f6271becb Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:20:45 +0000 Subject: [PATCH 090/232] Update style guides for name change --- docs/ql-style-guide.md | 4 ++-- docs/query-metadata-style-guide.md | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/ql-style-guide.md b/docs/ql-style-guide.md index 7b6ee9caf94..9e926c0b07e 100644 --- a/docs/ql-style-guide.md +++ b/docs/ql-style-guide.md @@ -1,8 +1,8 @@ -# QL Style Guide +# CodeQL style guide ## Introduction -This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming, and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. +This document describes how to format the code you contribute to this repository. It covers aspects such as layout, white-space, naming, and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. Note, if you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). Words in *italic* are defined in the [Glossary](#glossary). diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index 979594eb925..aab4365c445 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -1,6 +1,5 @@ # Query file metadata and alert message style guide - ## Introduction This document outlines the structure of Semmle query files. You should adopt this structure when contributing custom queries to this repository, in order to ensure that new queries are consistent with the standard Semmle queries. @@ -11,13 +10,13 @@ Query files have the extension `.ql`. Each file has two distinct areas: * Metadata area–displayed at the top of the file, contains the metadata that defines how results for the query are interpreted and gives a brief description of the purpose of the query. * Query definition–defined using QL. The query includes a select statement, which defines the content and format of the results. For further information about writing QL, see the following topics: - * [Learning QL](https://help.semmle.com/QL/learn-ql/index.html) + * [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html) * [QL language handbook](https://help.semmle.com/QL/ql-handbook/index.html) * [QL language specification](https://help.semmle.com/QL/ql-spec/language.html) * [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) -For examples of query files for the languages supported by Semmle, visit the following links: +For examples of query files for the languages supported by CodeQL, visit the following links: * [C/C++ queries](https://help.semmle.com/wiki/display/CCPPOBJ/) * [C# queries](https://help.semmle.com/wiki/display/CSHARP/) @@ -178,4 +177,4 @@ For examples of select clauses and alert messages, see the query source files at * [JavaScript queries](https://help.semmle.com/wiki/display/JS/) * [Python queries](https://help.semmle.com/wiki/display/PYTHON/) -For further information on query writing, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/ql/writing-queries/writing-queries.html). For more information on learning QL, see [Learning QL](https://help.semmle.com/QL/learn-ql/index.html). +For further information on query writing, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/ql/writing-queries/writing-queries.html). For more information on learning CodeQL, see [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html). From 236e1f7955a66a94562aa003253dd8d43093e7fd Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:27:43 +0000 Subject: [PATCH 091/232] Update change notes for name change --- change-notes/1.23/analysis-cpp.md | 2 +- change-notes/1.23/analysis-csharp.md | 2 +- change-notes/1.23/analysis-java.md | 2 +- change-notes/1.23/analysis-javascript.md | 2 +- change-notes/support/README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 64e9b98fcfb..a24559dc5d0 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -24,7 +24,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. | | Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index 7ec412a0eb2..1b9b70f9172 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -24,7 +24,7 @@ The following changes in version 1.23 affect C# analysis in all applications. * `nameof` expressions are now extracted correctly when the name is a namespace. -## Changes to QL libraries +## Changes to libraries * The new class `NamespaceAccess` models accesses to namespaces, for example in `nameof` expressions. * The data-flow library now makes it easier to specify barriers/sanitizers diff --git a/change-notes/1.23/analysis-java.md b/change-notes/1.23/analysis-java.md index b81b681aac5..8c38f57e9d2 100644 --- a/change-notes/1.23/analysis-java.md +++ b/change-notes/1.23/analysis-java.md @@ -19,7 +19,7 @@ The following changes in version 1.23 affect Java analysis in all applications. | Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. | | Useless comparison test (`java/constant-comparison`) | Fewer false positives | Additional overflow check patterns are now recognized and no longer reported. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 20f9ad1df87..cc349113468 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -46,7 +46,7 @@ | Uncontrolled data used in path expression (`js/path-injection`) | Fewer false-positive results | This query now recognizes calls to Express `sendFile` as safe in some cases. | | Unknown directive (`js/unknown-directive`) | Fewer false positive results | This query no longer flags uses of ":", which is sometimes used like a directive. | -## Changes to QL libraries +## Changes to libraries * `Expr.getDocumentation()` now handles chain assignments. diff --git a/change-notes/support/README.md b/change-notes/support/README.md index 7813c69523d..f111a437183 100644 --- a/change-notes/support/README.md +++ b/change-notes/support/README.md @@ -1,6 +1,6 @@ # Files moved to ``docs`` directory -Now that all of the QL documentation is in this repository, +Now that all of the CodeQL documentation is in this repository, notes on the languages, compilers, and frameworks supported have moved. They're now stored as part of the Sphinx ``support`` project with the other documentation: ``docs/language/support``. From 692e977a7148da6c6dc13a38c258b9034ae84bf7 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 13:44:23 +0000 Subject: [PATCH 092/232] Update docs/query-metadata-style-guide.md Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/query-metadata-style-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index aab4365c445..d5f5606002c 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -13,7 +13,7 @@ Query files have the extension `.ql`. Each file has two distinct areas: * [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html) * [QL language handbook](https://help.semmle.com/QL/ql-handbook/index.html) * [QL language specification](https://help.semmle.com/QL/ql-spec/language.html) - * [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) + * [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) For examples of query files for the languages supported by CodeQL, visit the following links: From 458108f66b7fc5848ff3cffb7477efd4817e7fca Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 14:08:50 +0000 Subject: [PATCH 093/232] Make 'open source' consistent on the page and with other docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6aa5e38f1a..3c73253b6df 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This open source repository contains the standard CodeQL libraries and queries t ## How do I learn CodeQL and run queries? There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL. -You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open-source project that's currently being analyzed. +You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open source project that's currently being analyzed. ## Contributing From e2b0ec5696111ab5183d291de61dbd5b81b5ce3e Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 16:17:17 +0000 Subject: [PATCH 094/232] JS: Handle multiple and/or operators in SanitizerFunction --- .../javascript/dataflow/TaintTracking.qll | 24 +++++++++++-- .../TaintTracking/BasicTaintTracking.expected | 2 ++ .../TaintTracking/DataFlowTracking.expected | 5 +++ .../TaintTracking/sanitizer-function.js | 35 +++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 06a0d904261..41afdb653f7 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -846,6 +846,26 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } + /** + * Gets an operand of the given `&&` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ + private Expr getALogicalAndOperand(LogAndExpr e) { + result = e.getAnOperand() + } + + /** + * Gets an operand of the given `||` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ + private Expr getALogicalOrOperand(LogOrExpr e) { + result = e.getAnOperand() + } + /** * A function that returns the result of a sanitizer check. */ @@ -860,10 +880,10 @@ module TaintTracking { returnExpr = sanitizer.asExpr() or // ad hoc support for conjunctions: - returnExpr.(LogAndExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = true + getALogicalAndOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = true or // ad hoc support for disjunctions: - returnExpr.(LogOrExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = false + getALogicalOrOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = false | exists(SsaExplicitDefinition ssa | ssa.getDef().getSource() = returnExpr and diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 2722f67d6fd..df1d6306feb 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,6 +69,8 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index 6a589e3e0d9..f3023ad44da 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -41,6 +41,11 @@ | partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:41:10:41:18 | id(taint) | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:51:14:51:14 | x | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:17:14:17:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:21:14:21:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:25:14:25:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js new file mode 100644 index 00000000000..6df74cf29ee --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js @@ -0,0 +1,35 @@ +function test() { + function myCheck1(x) { + return x === "a" && something() && somethingElse(); + } + function myCheck2(x) { + return something() && x === "a" && somethingElse(); + } + function myCheck3(x) { + return something() && somethingElse() && x === "a"; + } + + let taint = source(); + + sink(taint); // NOT OK + + if (myCheck1(taint)) { + sink(taint); // OK + } + + if (myCheck2(taint)) { + sink(taint); // OK + } + + if (myCheck3(taint)) { + sink(taint); // OK + } + + function badCheck(x) { + return something && x + isSafe(x) != null; + } + + if (badCheck(taint)) { + sink(taint); // NOT OK + } +} From d6158427c5cdecea8569441c71c59bb892304380 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 22:33:36 +0000 Subject: [PATCH 095/232] JS: Generalize SanitizerFunction to data flow configs and flow labels --- .../javascript/dataflow/Configuration.qll | 169 +++++++++++++++--- .../javascript/dataflow/TaintTracking.qll | 89 +-------- 2 files changed, 145 insertions(+), 113 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 568c1c92eab..68771406006 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -147,7 +147,7 @@ abstract class Configuration extends string { */ predicate isBarrier(DataFlow::Node node) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, "") ) } @@ -181,7 +181,7 @@ abstract class Configuration extends string { */ predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, lbl) ) or @@ -198,6 +198,12 @@ abstract class Configuration extends string { */ predicate isBarrierGuard(BarrierGuardNode guard) { none() } + private predicate isBarrierGuardInternal(BarrierGuardNode guard) { + isBarrierGuard(guard) + or + guard.(AdditionalBarrierGuardNode).appliesTo(this) + } + /** * Holds if data may flow from `source` to `sink` for this configuration. */ @@ -304,7 +310,7 @@ abstract class BarrierGuardNode extends DataFlow::Node { forex(SsaVariable input | input = ref.getAnInput() | asExpr() = ref.getGuard().getTest() and outcome = ref.getGuard().(ConditionGuardNode).getOutcome() and - internalBlocksExpr(outcome, input.getAUse(), label) + barrierGuardBlocksExpr(this, outcome, input.getAUse(), label) ) ) or @@ -313,33 +319,11 @@ abstract class BarrierGuardNode extends DataFlow::Node { nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and asExpr() = cond.getTest() and outcome = cond.getOutcome() and - internalBlocksAccessPath(outcome, p, label) and + barrierGuardBlocksAccessPath(this, outcome, p, label) and cond.dominates(bb) ) } - /** - * Holds if data flow node `nd` acts as a barrier for data flow. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - private predicate internalBlocksExpr(boolean outcome, Expr test, string label) { - blocks(outcome, test) and label = "" - or - blocks(outcome, test, label) - } - - /** - * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through - * an access path. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - pragma[noinline] - private predicate internalBlocksAccessPath(boolean outcome, AccessPath ap, string label) { - internalBlocksExpr(outcome, ap.getAnInstance(), label) - } - /** * Holds if this node blocks expression `e` provided it evaluates to `outcome`. * @@ -353,6 +337,32 @@ abstract class BarrierGuardNode extends DataFlow::Node { predicate blocks(boolean outcome, Expr e, FlowLabel label) { none() } } +/** + * Holds if data flow node `nd` acts as a barrier for data flow. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +private predicate barrierGuardBlocksExpr(BarrierGuardNode guard, boolean outcome, Expr test, string label) { + guard.blocks(outcome, test) and label = "" + or + guard.blocks(outcome, test, label) + or + // Handle labelled barrier guard functions specially, to avoid negative recursion + // through the non-abstract 3-argument version of blocks(). + guard.(AdditionalBarrierGuardCall).internalBlocksLabel(outcome, test, label) +} + +/** + * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through + * an access path. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +pragma[noinline] +private predicate barrierGuardBlocksAccessPath(BarrierGuardNode guard, boolean outcome, AccessPath ap, string label) { + barrierGuardBlocksExpr(guard, outcome, ap.getAnInstance(), label) +} + /** * A guard node that only blocks specific labels. */ @@ -1186,3 +1196,110 @@ module PathGraph { not pred = finalMidNode(succ) } } + + + +/** + * Gets an operand of the given `&&` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalAndOperand(LogAndExpr e) { + result = e.getAnOperand() +} + +/** + * Gets an operand of the given `||` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalOrOperand(LogOrExpr e) { + result = e.getAnOperand() +} + +/** + * A `BarrierGuardNode` that controls which data flow + * configurations it is used in. + * + * Note: For performance reasons, all subclasses of this class should be part + * of the standard library. Override `Configuration::isBarrierGuard` + * for analysis-specific barrier guards. + */ +abstract class AdditionalBarrierGuardNode extends BarrierGuardNode { + abstract predicate appliesTo(Configuration cfg); +} + +/** + * A function that returns the result of a barrier guard. + */ +private class BarrierGuardFunction extends Function { + DataFlow::ParameterNode sanitizedParameter; + BarrierGuardNode guard; + boolean guardOutcome; + string label; + + BarrierGuardFunction() { + exists(Expr e | + exists(Expr returnExpr | + returnExpr = guard.asExpr() + or + // ad hoc support for conjunctions: + getALogicalAndOperand+(returnExpr) = guard.asExpr() and guardOutcome = true + or + // ad hoc support for disjunctions: + getALogicalOrOperand+(returnExpr) = guard.asExpr() and guardOutcome = false + | + exists(SsaExplicitDefinition ssa | + ssa.getDef().getSource() = returnExpr and + ssa.getVariable().getAUse() = getAReturnedExpr() + ) + or + returnExpr = getAReturnedExpr() + ) and + sanitizedParameter.flowsToExpr(e) and + barrierGuardBlocksExpr(guard, guardOutcome, e, label) + ) and + getNumParameter() = 1 and + sanitizedParameter.getParameter() = getParameter(0) + } + + /** + * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. + */ + predicate isBarrierCall(DataFlow::CallNode call, Expr e, boolean outcome, string lbl) { + exists(DataFlow::Node arg | + arg.asExpr() = e and + arg = call.getArgument(0) and + call.getNumArgument() = 1 and + argumentPassing(call, arg, this, sanitizedParameter) and + outcome = guardOutcome and + lbl = label + ) + } + + /** + * Holds if this function applies to the flow in `cfg`. + */ + predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(guard) } +} + +/** + * A call that sanitizes an argument. + */ +private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, DataFlow::CallNode { + BarrierGuardFunction f; + + AdditionalBarrierGuardCall() { f.isBarrierCall(this, _, _, _) } + + override predicate blocks(boolean outcome, Expr e) { + f.isBarrierCall(this, e, outcome, "") + } + + predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel label) { + f.isBarrierCall(this, e, outcome, label) + } + + override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 41afdb653f7..43a04c55363 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -133,8 +133,8 @@ module TaintTracking { * configurations it is used in. * * Note: For performance reasons, all subclasses of this class should be part - * of the standard library. Override `Configuration::isSanitizer` - * for analysis-specific taint steps. + * of the standard library. Override `Configuration::isSanitizerGuard` + * for analysis-specific taint sanitizer guards. */ abstract class AdditionalSanitizerGuardNode extends SanitizerGuardNode { /** @@ -846,91 +846,6 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } - /** - * Gets an operand of the given `&&` operator. - * - * We use this to construct the transitive closure over a relation - * that does not include all of `BinaryExpr.getAnOperand`. - */ - private Expr getALogicalAndOperand(LogAndExpr e) { - result = e.getAnOperand() - } - - /** - * Gets an operand of the given `||` operator. - * - * We use this to construct the transitive closure over a relation - * that does not include all of `BinaryExpr.getAnOperand`. - */ - private Expr getALogicalOrOperand(LogOrExpr e) { - result = e.getAnOperand() - } - - /** - * A function that returns the result of a sanitizer check. - */ - private class SanitizingFunction extends Function { - DataFlow::ParameterNode sanitizedParameter; - SanitizerGuardNode sanitizer; - boolean sanitizerOutcome; - - SanitizingFunction() { - exists(Expr e | - exists(Expr returnExpr | - returnExpr = sanitizer.asExpr() - or - // ad hoc support for conjunctions: - getALogicalAndOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = true - or - // ad hoc support for disjunctions: - getALogicalOrOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = false - | - exists(SsaExplicitDefinition ssa | - ssa.getDef().getSource() = returnExpr and - ssa.getVariable().getAUse() = getAReturnedExpr() - ) - or - returnExpr = getAReturnedExpr() - ) and - sanitizedParameter.flowsToExpr(e) and - sanitizer.sanitizes(sanitizerOutcome, e) - ) and - getNumParameter() = 1 and - sanitizedParameter.getParameter() = getParameter(0) - } - - /** - * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. - */ - predicate isSanitizingCall(DataFlow::CallNode call, Expr e, boolean outcome) { - exists(DataFlow::Node arg | - arg.asExpr() = e and - arg = call.getArgument(0) and - call.getNumArgument() = 1 and - FlowSteps::argumentPassing(call, arg, this, sanitizedParameter) and - outcome = sanitizerOutcome - ) - } - - /** - * Holds if this function applies to the flow in `cfg`. - */ - predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(sanitizer) } - } - - /** - * A call that sanitizes an argument. - */ - private class AdditionalSanitizingCall extends AdditionalSanitizerGuardNode, DataFlow::CallNode { - SanitizingFunction f; - - AdditionalSanitizingCall() { f.isSanitizingCall(this, _, _) } - - override predicate sanitizes(boolean outcome, Expr e) { f.isSanitizingCall(this, e, outcome) } - - override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } - } - /** * An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object, * considered as a sanitizer for `e`. From f48d16fcb7450579e4e36e6eaa1a1d8547eed4ef Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 1 Nov 2019 15:22:03 +0000 Subject: [PATCH 096/232] JS: Support barrier guards that are reflective calls --- .../semmle/javascript/dataflow/Configuration.qll | 11 +++++++++-- .../ql/src/semmle/javascript/dataflow/DataFlow.qll | 9 +++++++++ .../TaintTracking/BasicTaintTracking.expected | 2 ++ .../TaintTracking/BasicTaintTracking.ql | 6 +++++- .../TaintTracking/DataFlowTracking.expected | 3 +++ .../TaintTracking/sanitizer-guards.js | 14 ++++++++++++++ 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 68771406006..11cfb24376e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -308,7 +308,7 @@ abstract class BarrierGuardNode extends DataFlow::Node { exists(SsaRefinementNode ref, boolean outcome | nd = DataFlow::ssaDefinitionNode(ref) and forex(SsaVariable input | input = ref.getAnInput() | - asExpr() = ref.getGuard().getTest() and + getExpr() = ref.getGuard().getTest() and outcome = ref.getGuard().(ConditionGuardNode).getOutcome() and barrierGuardBlocksExpr(this, outcome, input.getAUse(), label) ) @@ -317,13 +317,20 @@ abstract class BarrierGuardNode extends DataFlow::Node { // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p` exists(AccessPath p, BasicBlock bb, ConditionGuardNode cond, boolean outcome | nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and - asExpr() = cond.getTest() and + getExpr() = cond.getTest() and outcome = cond.getOutcome() and barrierGuardBlocksAccessPath(this, outcome, p, label) and cond.dominates(bb) ) } + /** Gets the corresponding expression, including that of reflective calls. */ + private Expr getExpr() { + result = asExpr() + or + this = DataFlow::reflectiveCallNode(result) + } + /** * Holds if this node blocks expression `e` provided it evaluates to `outcome`. * diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37..0faecc01109 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -932,6 +932,15 @@ module DataFlow { */ DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot } + /** + * Gets a data flow node representing the underlying call performed by the given + * call to `Function.prototype.call` or `Function.prototype.apply`. + * + * For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the + * callee, `x` as the receiver, and `y` as the first argument. + */ + DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) } + /** * Provides classes representing various kinds of calls. * diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index df1d6306feb..93dc5e6e200 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -75,6 +75,8 @@ typeInferenceMismatch | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | | spread.js:2:15:2:22 | source() | spread.js:4:8:4:19 | { ...taint } | | spread.js:2:15:2:22 | source() | spread.js:5:8:5:43 | { f: 'h ... orld' } | | spread.js:2:15:2:22 | source() | spread.js:7:8:7:19 | [ ...taint ] | diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql index 0b1d5d9da84..26c66a1b4fe 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql @@ -1,7 +1,11 @@ import javascript import semmle.javascript.dataflow.InferredTypes -DataFlow::CallNode getACall(string name) { result.getCalleeName() = name } +DataFlow::CallNode getACall(string name) { + result.getCalleeName() = name + or + result.getCalleeNode().getALocalSource() = DataFlow::globalVarRef(name) +} class Sink extends DataFlow::Node { Sink() { this = getACall("sink").getAnArgument() } diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index f3023ad44da..f2799d763fd 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -50,6 +50,9 @@ | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:52:10:52:10 | x | | thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field | | thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 | | tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x | diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js index 494e828460d..03d6a9aedd7 100644 --- a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js @@ -38,3 +38,17 @@ class C { }); } } + +function reflective() { + let x = source(); + + sink(x); // NOT OK + + if (isSafe.call(x)) { + sink(x); // NOT OK - `isSafe` does not sanitize the receiver + } + + if (isSafe.call(null, x)) { + sink(x); // OK + } +} From fa203254ce09661d52db689e4f5a388f0acf69b7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:09:42 +0000 Subject: [PATCH 097/232] CPP: Add test cases. --- .../TlsSettingsMisconfiguration.expected | 11 ++++ .../Likely Bugs/Protocols/boostorg/test2.cpp | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected index 8a3acb1aeb5..c6883e156d1 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected @@ -1,3 +1,14 @@ +| test2.cpp:15:32:15:33 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:15:32:15:33 | call to context | boost::asio::ssl::context::context | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:45:35:45:98 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:35:45:98 | call to context | boost::asio::ssl::context::context | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_sslv3 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set | | test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set | | test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | | test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp new file mode 100644 index 00000000000..5679cee8b0f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp @@ -0,0 +1,55 @@ +#include "asio/boost_simulation.hpp" + +void good1() +{ + // GOOD + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad1() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void good2() +{ + // GOOD [FALSE POSITIVE x 3] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void bad2() +{ + // BAD: missing disable SSLv3 [WITH FALSE POSITIVE x 2] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void good3() +{ + // GOOD + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad3() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void bad4() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); +} + + From 6a865ed580c3dfdfedb0236f9067206421b37d4c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:03:10 +0000 Subject: [PATCH 098/232] CPP: De-duplicate TlsSettingsMisconfiguration.ql. --- .../boostorg/TlsSettingsMisconfiguration.ql | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 83ed90bafab..0089221799c 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -46,29 +46,8 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { bindingset[flag] predicate isOptionNotSet(ConstructorCall cc, int flag) { - not exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, - Expr optionsSink - | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and - exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f | - f.getACallToThisFunction() = fcSetOptions - | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) - ) - ) + not exists(FunctionCall fcSetOptions | + isOptionSet(cc, flag, fcSetOptions) ) } From c08493670b56d1ac019161e676f766c930942df7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:09:25 +0000 Subject: [PATCH 099/232] CPP: Speed up ExistsAnyFlowConfig. --- .../Protocols/boostorg/TlsSettingsMisconfiguration.ql | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 0089221799c..1a5dbfb74fc 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -13,7 +13,9 @@ import semmle.code.cpp.security.boostorg.asio.protocols class ExistsAnyFlowConfig extends DataFlow::Configuration { ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } - override predicate isSource(DataFlow::Node source) { any() } + override predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof ConstructorCall + } override predicate isSink(DataFlow::Node sink) { any() } } @@ -21,12 +23,12 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, + BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig anyFlowConfig, Expr optionsSink | config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | contextSetOptions = fcSetOptions.getQualifier() and forall( From 98b9afd83f772e45f9c3c44cdb8211eef0d01446 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:19:36 +0000 Subject: [PATCH 100/232] CPP: Remove apparently irrelevant parts of the query. This is not strictly behaviour preserving, but I believe the parts I've removed or simplified weren't intended to do what they were doing. --- .../boostorg/TlsSettingsMisconfiguration.ql | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 1a5dbfb74fc..369dbf77973 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -22,11 +22,9 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig anyFlowConfig, - Expr optionsSink + exists(BoostorgAsio::SslContextClass c, ExistsAnyFlowConfig anyFlowConfig | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + c.getAContructorCall() = cc and exists(VariableAccess contextSetOptions | anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | @@ -55,15 +53,14 @@ predicate isOptionNotSet(ConstructorCall cc, int flag) { from BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, - BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink, - ConstructorCall cc, Expr e, string msg + Expr protocolSource, Expr protocolSink, + BoostorgAsio::SslContextClass c, ConstructorCall cc, Expr e, string msg where configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and ( BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and @@ -72,8 +69,7 @@ where or BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2()) From 08293d00095c4f01b8b1fe067b3716291c5a08a1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:56:22 +0000 Subject: [PATCH 101/232] CPP: Simplify. --- .../boostorg/TlsSettingsMisconfiguration.ql | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 369dbf77973..6c2026c83d6 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -14,7 +14,9 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof ConstructorCall + exists(BoostorgAsio::SslContextClass c | + c.getAContructorCall() = source.asExpr() + ) } override predicate isSink(DataFlow::Node sink) { any() } @@ -22,23 +24,19 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists(BoostorgAsio::SslContextClass c, ExistsAnyFlowConfig anyFlowConfig - | - c.getAContructorCall() = cc and - exists(VariableAccess contextSetOptions | - anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) + exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions | + anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | + contextSetOptions = fcSetOptions.getQualifier() and + forall( + Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, + Expr optionArgumentSource + | + optionArgument = fcSetOptions.getArgument(0) and + optionArgConfig + .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + | + optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag ) ) ) @@ -54,7 +52,7 @@ predicate isOptionNotSet(ConstructorCall cc, int flag) { from BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource, Expr protocolSink, - BoostorgAsio::SslContextClass c, ConstructorCall cc, Expr e, string msg + ConstructorCall cc, Expr e, string msg where configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and From c2812197a96059247677c7bfd3f62aab9b675bf0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 18:16:12 +0000 Subject: [PATCH 102/232] CPP: Further speedup. --- .../Protocols/boostorg/TlsSettingsMisconfiguration.ql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 6c2026c83d6..85f4ca1a860 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -19,7 +19,12 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { any() } + override predicate isSink(DataFlow::Node sink) { + exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions | + f.getACallToThisFunction() = fcSetOptions and + fcSetOptions.getQualifier() = sink.asExpr() + ) + } } bindingset[flag] From 2bad9394b7d909186bb8977ce147982c36d00041 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 1 Nov 2019 15:24:22 -0700 Subject: [PATCH 103/232] [CPP-434] Squelch alerts for expressions inside macros; try to make Qhelp Jenkins-friendly. --- .../Arithmetic/SignedOverflowCheck.qhelp | 46 +++++++++---------- .../Arithmetic/SignedOverflowCheck.ql | 1 + .../SignedOverflowCheck.cpp | 7 +++ 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index da7f86f021b..302fbd4ed23 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -24,81 +24,81 @@ into unsigned form. The table below lists various expressions where signed overflow may occur, along with proposed rewritings. It should not be -considered as exhaustive. +considered exhaustive.

    - + - - + + - + - + - +
    Original Construct Alternate Construct(s) Notes
    - + - +
    unsigned short i, delta;
    i + delta < i
    - + - +
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      - + - +
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climitsMust include limits.h or climits; delta > 0
    - + - +
    int i, delta;
    i + delta < i
    - + - +
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climitsMust include limits.h or climits; delta > 0
      - + - +
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      - + - +
    unsigned int i, delta;
    i + delta < i
    Change in program semantics
    @@ -131,7 +131,7 @@ narrower short type, the addition is guaranteed not to overflow and is therefore defined. But the fact that n1 + delta never overflows means that the condition n1 + delta < n1 will never hold true, which likely is not what the programmer intended. (see also the -BadArithmeticOverflow.Check.ql query). +cpp/bad-addition-overflow-check query).

    @@ -147,6 +147,6 @@ the right-hand side does not need to be promoted to a signed int.

  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • -
  • W. Dietz,∗ P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • +
  • W. Dietz, P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 7ea5df5da64..bd79a114172 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -22,5 +22,6 @@ where ro.getAnOperand() = expr2 and globalValueNumber(expr1) = globalValueNumber(expr2) and add.getUnspecifiedType().(IntegralType).isSigned() and + not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index bbfb1c3fad8..e359fb098eb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -121,3 +121,10 @@ int overflow12b(int n) { // not deleted by gcc or clang return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow } + +#define MACRO(E1, E2) (E1) <= (E2)? -1: 1 + +int overflow12_macro(int n) { + return MACRO((unsigned)(n + 32), (unsigned)n); // GOOD: inside a macro expansion +} + From fb4dac597c819df53d29ecf6b9c19553e0a0d1a4 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sun, 3 Nov 2019 16:21:21 +0100 Subject: [PATCH 104/232] C++: Minimal caching of the IR type system This was the minimal amount of predicates I could easily cache without introducing extra cached stages. The predicates that are not cached here, like `CppType::getTypeSize` and `getCanonicalLanguageType`, appear to be cheap. I've tested that this avoids recomputation of the IR type system by running grep -c 'Starting to evaluate predicate CppType::CppType::getIRType_dispred' on the evaluator log for `IRSanity.ql`. It drops from 4 to 1. The pretty-printed DIL drops from 79,175 lines to 76,326 lines. --- cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll | 1 + cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 0abfa14023d..5534ed20914 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 88184d90345..e967dc9920c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -175,6 +175,7 @@ private IRType getIRTypeForPRValue(Type type) { ) } +cached private newtype TCppType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TFunctionGLValueType() or @@ -203,6 +204,7 @@ class CppType extends TCppType { * Gets the `IRType` that represents this `CppType`. Many different `CppType`s can map to a single * `IRType`. */ + cached IRType getIRType() { none() } /** From 508b09f565fa9338b8f77e73cbe2bb19ab31ce55 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 4 Nov 2019 13:43:39 +0100 Subject: [PATCH 105/232] C#: Address review comments --- change-notes/1.23/analysis-csharp.md | 4 ++-- .../src/Security Features/CWE-502/UnsafeDeserialization.qhelp | 2 +- .../CWE-502/UnsafeDeserializationUntrustedInput.qhelp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index f81007a2fc9..c60c32ba029 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -9,9 +9,9 @@ The following changes in version 1.23 affect C# analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. | -| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security | Finds flow of untrusted input to calls to unsafe deserializers. | +| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security, external/cwe/cwe-502 | Finds flow of untrusted input to calls to unsafe deserializers. | | Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. | -| Unsafe deserializer (`cs/unsafe-deserialization`) | security | Finds calls to unsafe deserializers. | +| Unsafe deserializer (`cs/unsafe-deserialization`) | security, external/cwe/cwe-502 | Finds calls to unsafe deserializers. | | Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. | ## Changes to existing queries diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp index 7acfd20fe3a..3c68b74a1d9 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp index ef946f40136..3ba934ba391 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    From 016808b92ea17a62abe3a29688cf6be02a97ec68 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 4 Nov 2019 17:00:12 +0000 Subject: [PATCH 106/232] JavaScript: Address review comments. --- change-notes/1.23/analysis-javascript.md | 1 + javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index aa9d2086d14..c87e16ce569 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -31,6 +31,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Double escaping or unescaping (`js/double-escaping`) | More results | This rule now detects additional escaping and unescaping functions. | | Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. | | Client-side cross-site scripting (`js/xss`) | More results, fewer false-positive results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized, and more sanitizers are detected. | | Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. | diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp index 02cce7c5911..6c36fde4b28 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp @@ -10,8 +10,8 @@ attacks such as cross-site scripting. One particular example of this is HTML ent where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as &lt; and the double-quote character as &quot;. -Other examples include backslash-escaping for including untrusted data in string literals and -percent-encoding for URI components. +Other examples include backslash escaping or JSON encoding for including untrusted data in string +literals, and percent-encoding for URI components.

    The reverse process of replacing escape sequences with the characters they represent is known as From 6cac9619d3faeaa47b1db702425731058517dcec Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:44:13 +0100 Subject: [PATCH 107/232] add missing not Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 77ec29ba9ee..59d88bc51a0 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -131,7 +131,7 @@ DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } /** * Holds if `call` is an Array or Lodash method accepting a callback `func`, * where the `call` expects a callback that returns an expression, - * but `func` does return a value. + * but `func` does not return a value. */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and From 8ebfe15f0d286139b370a0cc2f3016459c9b1520 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:54:43 +0100 Subject: [PATCH 108/232] apply doc feedback from mchammer01 Co-Authored-By: mc <42146119+mchammer01@users.noreply.github.com> --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 2232784d881..048ca6680fc 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -22,17 +22,17 @@ or slice.

    -In the following example a function extend is defined. The +A function extend is defined in the following example. The function uses the concat method to add elements to the arr array. However, the extend function has no -effect as the return value from concat is ignored. +effect as the return value from concat is ignored:

    Assigning the returned value from the call to concat to the -arr variable fixes the error. +arr variable fixes the error:

    From aa47e3f6d2ff7d45dac3d7b3a5c00b83d4da3931 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:52:29 +0100 Subject: [PATCH 109/232] update change-note to reflect changed query --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 90f46403f26..e3421a3de45 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -23,7 +23,7 @@ | Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. | | Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. | | Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. | -| Ignoring return from concat (`js/ignore-return-from-concat`) | maintainability, correctness | Highlights calls to the concat method on array where the return value is ignored. Results are shown on LGTM by default. | +| Ignoring result from pure array method (`js/ignore-array-result`) | maintainability, correctness | Highlights calls to array methods without side effects where the return value is ignored. Results are shown on LGTM by default. | ## Changes to existing queries From bdb81c268c22a92758c60cdea795459fab268f07 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:56:03 +0100 Subject: [PATCH 110/232] change tense --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 048ca6680fc..70e3cb4e5cc 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -5,7 +5,7 @@

    The concat, join and slice methods are -pure and do not modify any of the inputs or the array the method was called +pure and do not modify any of the inputs or the array the method is called on. It is therefore generally an error to ignore the return value from a call to one of these methods.

    From ce8ba86f2d35df8e302dc7240d3f8e9e771a64eb Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 4 Nov 2019 12:30:52 -0800 Subject: [PATCH 111/232] [CPP-434] Use a bullet list instead of a table in order to placate Jenkins. --- .../Arithmetic/SignedOverflowCheck.qhelp | 102 +++++------------- 1 file changed, 27 insertions(+), 75 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 302fbd4ed23..a6f8f4dc373 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,85 +22,36 @@ categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. -The table below lists various expressions where signed overflow may +The bullet list below lists various expressions where signed overflow may occur, along with proposed rewritings. It should not be considered exhaustive.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Original ConstructAlternate Construct(s)Notes
    - - - - - -
    unsigned short i, delta;
    i + delta < i
    - - - - - -
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      - - - - - -
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climits; delta > 0
    - - - - - -
    int i, delta;
    i + delta < i
    - - - - - -
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climits; delta > 0
      - - - - - -
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      - - - - - -
    unsigned int i, delta;
    i + delta < i
    Change in program semantics
    + +
  • Given unsigned short i, delta and i + delta < i, +it is possible to rewrite it as (unsigned short)(i + delta) < i. +Note that i + deltadoes not actually overflow, due to int promotion
  • + +
  • Given unsigned short i, delta and i + delta < i, +it is also possible to rewrite it as USHORT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included.
  • + +
  • Given int i, delta and i + delta < i, +it is possible to rewrite it as INT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included.
  • + +
  • Given int i, delta and i + delta < i, +it is also possible to rewrite it as (unsigned)i + delta < i. +Note that program semantics are affected by this change.
  • + +
  • Given int i, delta and i + delta < i, +it is also possible to rewrite it as unsigned int i, delta and +i + delta < i. Note that program semantics are +affected by this change.
  • +
    +

    In the following example, even though delta has been declared @@ -142,6 +93,7 @@ so that unsigned short "wrap around" may now be observed. Furthermore, since the left-hand side is now of type unsigned short, the right-hand side does not need to be promoted to a signed int.

    +
    From 398896a4b21127b2d286d9fc2bd456b2456959bd Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 4 Nov 2019 16:44:31 -0800 Subject: [PATCH 112/232] [CPP-434] Change list items to ordinary paragraphs in the Recommendation section. --- .../Arithmetic/SignedOverflowCheck.qhelp | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index a6f8f4dc373..4d5dfabef14 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,34 +22,35 @@ categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. -The bullet list below lists various expressions where signed overflow may -occur, along with proposed rewritings. It should not be +Below we list examples of expressions where signed overflow may +occur, along with proposed solutions. The list should not be considered exhaustive.

    -
  • Given unsigned short i, delta and i + delta < i, +

    +Given unsigned short i, delta and i + delta < i, it is possible to rewrite it as (unsigned short)(i + delta) < i. -Note that i + deltadoes not actually overflow, due to int promotion

  • +Note that i + deltadoes not actually overflow, due to int promotion -
  • Given unsigned short i, delta and i + delta < i, +Given unsigned short i, delta and i + delta < i, it is also possible to rewrite it as USHORT_MAX - delta. It must be true that delta > 0 and the limits.h or climits -header has been included.
  • +header has been included. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is possible to rewrite it as INT_MAX - delta. It must be true that delta > 0 and the limits.h or climits -header has been included.
  • +header has been included. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is also possible to rewrite it as (unsigned)i + delta < i. -Note that program semantics are affected by this change.
  • +Note that program semantics are affected by this change. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is also possible to rewrite it as unsigned int i, delta and i + delta < i. Note that program semantics are -affected by this change.
  • - +affected by this change. +

    From df3c70e57e1613c6ad1096e3028924634c612196 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 5 Nov 2019 10:40:14 +0100 Subject: [PATCH 113/232] add js/ignore-array-result to correctness-core suite --- javascript/config/suites/javascript/correctness-core | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/config/suites/javascript/correctness-core b/javascript/config/suites/javascript/correctness-core index 6a53405e1c3..d6b91e83a07 100644 --- a/javascript/config/suites/javascript/correctness-core +++ b/javascript/config/suites/javascript/correctness-core @@ -37,5 +37,6 @@ + semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions ++ semmlecode-javascript-queries/Statements/IgnoreArrayResult.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/InconsistentLoopOrientation.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/UnreachableStatement.ql: /Correctness/Statements From d8f3a2c55037421e30a5d02cb7273af53e3cf9e7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 12:58:39 +0000 Subject: [PATCH 114/232] JS: Add lvalue of for..of loop as a PropRead --- .../semmle/javascript/dataflow/DataFlow.qll | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37..07920cba3c9 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -741,7 +741,8 @@ module DataFlow { PropReadAsSourceNode() { this = TPropNode(any(PropertyPattern p)) or this instanceof RestPatternNode or - this instanceof ElementPatternNode + this instanceof ElementPatternNode or + this = lvalueNode(any(ForOfStmt stmt).getLValue()) } } @@ -826,6 +827,24 @@ module DataFlow { override string getPropertyName() { result = astNode.getImportedName() } } + /** + * The left-hand side of a `for..of` statement, seen as a property read + * on the object being iterated over. + */ + private class ForOfLvalueAsPropRead extends PropRead { + ForOfStmt stmt; + + ForOfLvalueAsPropRead() { + this = lvalueNode(stmt.getLValue()) + } + + override Node getBase() { result = stmt.getIterationDomain().flow() } + + override Expr getPropertyNameExpr() { none() } + + override string getPropertyName() { none() } + } + /** * A data flow node representing an unused parameter. * From d8ac0abb7f26879e59d7f6addd8cbe995aeedf5b Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 10:06:21 +0000 Subject: [PATCH 115/232] JS: Add test --- .../ql/test/library-tests/DataFlow/flowStep.expected | 5 +++++ .../ql/test/library-tests/DataFlow/incomplete.expected | 5 +++++ .../ql/test/library-tests/DataFlow/parameters.expected | 1 + javascript/ql/test/library-tests/DataFlow/sources.expected | 7 +++++++ javascript/ql/test/library-tests/DataFlow/sources.js | 5 +++++ 5 files changed, 23 insertions(+) diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index a6446732fbe..107dcfb98c7 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -7,6 +7,11 @@ | sources.js:3:11:3:11 | x | sources.js:4:10:4:10 | x | | sources.js:4:10:4:13 | x+19 | sources.js:3:1:5:6 | (functi ... \\n})(23) | | sources.js:5:4:5:5 | 23 | sources.js:3:11:3:11 | x | +| sources.js:9:14:9:18 | array | sources.js:10:19:10:23 | array | +| sources.js:9:14:9:18 | array | sources.js:11:23:11:27 | array | +| sources.js:10:12:10:14 | key | sources.js:10:28:10:30 | key | +| sources.js:11:12:11:18 | key | sources.js:11:32:11:34 | key | +| sources.js:11:14:11:16 | key | sources.js:11:12:11:18 | key | | tst.js:1:1:1:1 | x | tst.js:28:2:28:1 | x | | tst.js:1:1:1:1 | x | tst.js:32:1:32:0 | x | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | diff --git a/javascript/ql/test/library-tests/DataFlow/incomplete.expected b/javascript/ql/test/library-tests/DataFlow/incomplete.expected index aee8fd44421..35413033fe7 100644 --- a/javascript/ql/test/library-tests/DataFlow/incomplete.expected +++ b/javascript/ql/test/library-tests/DataFlow/incomplete.expected @@ -8,6 +8,11 @@ | sources.js:1:6:1:11 | exceptional return of anonymous function | call | | sources.js:3:1:5:6 | exceptional return of (functi ... \\n})(23) | call | | sources.js:3:2:5:1 | exceptional return of anonymous function | call | +| sources.js:9:1:12:1 | exceptional return of function foo | call | +| sources.js:9:14:9:18 | array | call | +| sources.js:10:12:10:14 | key | heap | +| sources.js:11:12:11:18 | key | heap | +| sources.js:11:14:11:16 | key | heap | | tst.js:1:10:1:11 | fs | import | | tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | call | | tst.js:16:2:20:1 | exceptional return of function f | call | diff --git a/javascript/ql/test/library-tests/DataFlow/parameters.expected b/javascript/ql/test/library-tests/DataFlow/parameters.expected index b7746f41c8a..31bab07c4e2 100644 --- a/javascript/ql/test/library-tests/DataFlow/parameters.expected +++ b/javascript/ql/test/library-tests/DataFlow/parameters.expected @@ -1,5 +1,6 @@ | sources.js:1:6:1:6 | x | | sources.js:3:11:3:11 | x | +| sources.js:9:14:9:18 | array | | tst.js:16:13:16:13 | a | | tst.js:32:12:32:12 | b | | tst.js:87:11:87:24 | { p: x, ...o } | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.expected b/javascript/ql/test/library-tests/DataFlow/sources.expected index 185cc89e4ad..37a54027371 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.expected +++ b/javascript/ql/test/library-tests/DataFlow/sources.expected @@ -13,6 +13,12 @@ | sources.js:3:2:5:1 | functio ... x+19;\\n} | | sources.js:3:11:3:11 | x | | sources.js:7:1:7:3 | /x/ | +| sources.js:9:1:9:0 | this | +| sources.js:9:1:12:1 | functio ... ey; }\\n} | +| sources.js:9:14:9:18 | array | +| sources.js:10:12:10:14 | key | +| sources.js:11:12:11:18 | { key } | +| sources.js:11:14:11:16 | key | | tst.js:1:1:1:0 | this | | tst.js:1:1:1:24 | import ... m 'fs'; | | tst.js:1:10:1:11 | fs | @@ -60,6 +66,7 @@ | tst.js:72:9:72:9 | p | | tst.js:72:9:72:11 | p() | | tst.js:75:9:75:21 | import('foo') | +| tst.js:80:10:80:10 | v | | tst.js:83:11:83:28 | [ for (v of o) v ] | | tst.js:85:11:85:28 | ( for (v of o) v ) | | tst.js:87:1:96:2 | (functi ... r: 0\\n}) | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.js b/javascript/ql/test/library-tests/DataFlow/sources.js index 653c5fc129c..7a5bb869efe 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.js +++ b/javascript/ql/test/library-tests/DataFlow/sources.js @@ -5,3 +5,8 @@ new (x => x); })(23); /x/; + +function foo(array) { + for (let key of array) { key; } + for (let { key } of array) { key; } +} From c373be0dee9b4c8b4edbfb5980b1b0b3f5586bde Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 10:26:04 +0000 Subject: [PATCH 116/232] JS: Update TaintBarriers test --- .../library-tests/TaintBarriers/SanitizingGuard.expected | 5 ----- .../ql/test/library-tests/TaintBarriers/TaintedSink.expected | 1 - .../ql/test/library-tests/TaintBarriers/isBarrier.expected | 1 + javascript/ql/test/library-tests/TaintBarriers/tst.js | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected index c58a7c511d1..010375e1ab8 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected @@ -44,14 +44,11 @@ | tst.js:236:9:236:24 | isWhitelisted(v) | ExampleConfiguration | true | tst.js:236:23:236:23 | v | | tst.js:240:9:240:28 | config.allowValue(v) | ExampleConfiguration | true | tst.js:240:27:240:27 | v | | tst.js:252:16:252:36 | whiteli ... ains(x) | ExampleConfiguration | true | tst.js:252:35:252:35 | x | -| tst.js:254:9:254:12 | f(v) | ExampleConfiguration | true | tst.js:254:11:254:11 | v | | tst.js:261:25:261:45 | whiteli ... ains(y) | ExampleConfiguration | true | tst.js:261:44:261:44 | y | -| tst.js:264:9:264:12 | g(v) | ExampleConfiguration | true | tst.js:264:11:264:11 | v | | tst.js:271:25:271:45 | whiteli ... ains(z) | ExampleConfiguration | true | tst.js:271:44:271:44 | z | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:16:281:17 | x2 | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:22:281:25 | null | | tst.js:281:30:281:51 | whiteli ... ins(x2) | ExampleConfiguration | true | tst.js:281:49:281:50 | x2 | -| tst.js:283:9:283:13 | f2(v) | ExampleConfiguration | true | tst.js:283:12:283:12 | v | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:16:290:17 | x3 | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:22:290:25 | null | | tst.js:290:30:290:51 | whiteli ... ins(x3) | ExampleConfiguration | true | tst.js:290:49:290:50 | x3 | @@ -61,7 +58,6 @@ | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:25:327:26 | x7 | | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:31:327:34 | null | | tst.js:327:39:327:60 | whiteli ... ins(x7) | ExampleConfiguration | true | tst.js:327:58:327:59 | x7 | -| tst.js:330:9:330:13 | f7(v) | ExampleConfiguration | true | tst.js:330:12:330:12 | v | | tst.js:337:25:337:46 | whiteli ... ins(x8) | ExampleConfiguration | true | tst.js:337:44:337:45 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:16:338:17 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:22:338:25 | null | @@ -70,6 +66,5 @@ | tst.js:356:16:356:27 | x10 !== null | ExampleConfiguration | false | tst.js:356:24:356:27 | null | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:32:356:34 | x10 | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:40:356:48 | undefined | -| tst.js:358:9:358:14 | f10(v) | ExampleConfiguration | false | tst.js:358:13:358:13 | v | | tst.js:370:9:370:29 | o.p == ... listed" | ExampleConfiguration | true | tst.js:370:9:370:11 | o.p | | tst.js:377:11:377:32 | o[p] == ... listed" | ExampleConfiguration | true | tst.js:377:11:377:14 | o[p] | diff --git a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected index 050f80bc071..54b35166b15 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected @@ -53,7 +53,6 @@ | tst.js:333:14:333:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:341:14:341:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:343:14:343:14 | v | tst.js:248:13:248:20 | SOURCE() | -| tst.js:350:14:350:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:352:14:352:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:359:14:359:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:368:10:368:12 | o.p | tst.js:367:13:367:20 | SOURCE() | diff --git a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected index 50804043f95..f650c93185c 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected @@ -37,6 +37,7 @@ | tst.js:265:14:265:14 | v | ExampleConfiguration | | tst.js:284:14:284:14 | v | ExampleConfiguration | | tst.js:331:14:331:14 | v | ExampleConfiguration | +| tst.js:350:14:350:14 | v | ExampleConfiguration | | tst.js:356:16:356:27 | x10 | ExampleConfiguration | | tst.js:356:32:356:34 | x10 | ExampleConfiguration | | tst.js:361:14:361:14 | v | ExampleConfiguration | diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js index 78986d6af37..a7a05590540 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/tst.js +++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js @@ -347,7 +347,7 @@ function IndirectSanitizer () { return unknown() && whitelist.contains(x9) && unknown(); } if (f9(v)) { - SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED + SINK(v); } else { SINK(v); } From 48c7d1d7c1218ad0b022bab561e69c74905876ce Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:20:16 +0100 Subject: [PATCH 117/232] C++: add *_template_parameter_value() tuples --- cpp/ql/src/semmlecode.cpp.dbscheme | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme b/cpp/ql/src/semmlecode.cpp.dbscheme index 98a075d5495..bd182f697bf 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme +++ b/cpp/ql/src/semmlecode.cpp.dbscheme @@ -731,6 +731,11 @@ class_template_argument( int index: int ref, int arg_type: @type ref ); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); is_proxy_class_for( unique int id: @usertype ref, @@ -755,6 +760,11 @@ function_template_argument( int index: int ref, int arg_type: @type ref ); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); is_variable_template(unique int id: @variable ref); variable_instantiation( @@ -766,6 +776,11 @@ variable_template_argument( int index: int ref, int arg_type: @type ref ); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); /* Fixed point types From df7d21220be83026d76636877c98693fffc08ef0 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:20:48 +0100 Subject: [PATCH 118/232] C++: Basic lib support for template param values --- cpp/ql/src/semmle/code/cpp/Class.qll | 9 +++++++++ cpp/ql/src/semmle/code/cpp/Declaration.qll | 7 +++++++ cpp/ql/src/semmle/code/cpp/Function.qll | 10 ++++++++++ cpp/ql/src/semmle/code/cpp/Variable.qll | 9 +++++++++ 4 files changed, 35 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5ac4f52392e..44e8b4e65ef 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -614,6 +614,15 @@ class Class extends UserType { class_template_argument(underlyingElement(this), i, unresolveElement(result)) } + /** + * Gets the `i`th template argument value used to instantiate this class from a + * class template. When called on a class template, this will return the + * `i`th template parameter value. + */ + override Expr getTemplateArgumentValue(int i) { + class_template_argument_value(underlyingElement(this), i, unresolveElement(result)) + } + /** * Holds if this class/struct is polymorphic (has a virtual function, or * inherits one). diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 5d13bf4883a..a3a93aaca96 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -203,6 +203,13 @@ abstract class Declaration extends Locatable, @declaration { */ Type getTemplateArgument(int index) { none() } + /** + * Gets the `i`th template argument value used to instantiate this declaration + * from a template. When called on a template, this will return the `i`th template + * parameter value if it exists. + */ + Expr getTemplateArgumentValue(int index) { none() } + /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 94d11d63575..be031f2b915 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -352,6 +352,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { function_template_argument(underlyingElement(this), index, unresolveElement(result)) } + /** + * Gets the value of the `i`th template argument used to instantiate this + * function from a function template if that argument was a 'non-type' + * argument. When called on a function template, this with return the value + * of the `i`th template parameter. + */ + override Expr getTemplateArgumentValue(int index) { + function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } + /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 6fd33d9a037..deae1069aab 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -164,6 +164,15 @@ class Variable extends Declaration, @variable { variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } + /** + * Gets the `i`th template argument value used to instantiate this variable from a + * variable template. When called on a variable template, this will return the + * `i`th template parameter value. + */ + override Expr getTemplateArgumentValue(int index) { + variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } + /** * Holds if this is a compiler-generated variable. For example, a * [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for) From faf5ba432b2306d09d77965c48a84edc1c245d94 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:22:03 +0100 Subject: [PATCH 119/232] C++: Update expected test results --- .../library-tests/ir/ir/PrintAST.expected | 50 +++++++++---------- .../test/library-tests/ir/ir/raw_ir.expected | 23 +++++++++ .../ptr_to_member/segfault/exprs.expected | 4 ++ .../templates/CPP-202/template_args.expected | 4 +- .../templates/CPP-204/element.expected | 6 +++ 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 19a4288a4c4..e61fe2b440f 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -67,31 +67,7 @@ bad_asts.cpp: # 5| params: #-----| 0: [Parameter] p#0 #-----| Type = [RValueReferenceType] S && -# 9| [MemberFunction] int Bad::S::MemberFunction(int) -# 9| params: -# 9| 0: [Parameter] y -# 9| Type = [IntType] int -# 9| body: [Block] { ... } -# 10| 0: [ReturnStmt] return ... -# 10| 0: [AddExpr] ... + ... -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 0: [AddExpr] ... + ... -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 0: [Literal] Unknown literal -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 1: [PointerFieldAccess] x -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue(load) -#-----| -1: [ThisExpr] this -#-----| Type = [PointerType] S * -#-----| ValueCategory = prvalue(load) -# 10| 1: [VariableAccess] y -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue(load) -# 9| [TopLevelFunction] int MemberFunction(int) +# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -116,6 +92,30 @@ bad_asts.cpp: # 10| 1: [VariableAccess] y # 10| Type = [IntType] int # 10| ValueCategory = prvalue(load) +# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) +# 9| params: +# 9| 0: [Parameter] y +# 9| Type = [IntType] int +# 9| body: [Block] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [AddExpr] ... + ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| 0: [AddExpr] ... + ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| 0: [Literal] Unknown literal +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| 1: [PointerFieldAccess] x +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) +#-----| -1: [ThisExpr] this +#-----| Type = [PointerType] S * +#-----| ValueCategory = prvalue(load) +# 10| 1: [VariableAccess] y +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) # 14| [TopLevelFunction] void Bad::CallBadMemberFunction() # 14| params: # 14| body: [Block] { ... } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 90c3061114e..f0c96d2bfa0 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,4 +1,27 @@ bad_asts.cpp: +# 9| int Bad::S::MemberFunction(int) +# 9| Block 0 +# 9| v0_0(void) = EnterFunction : +# 9| mu0_1(unknown) = AliasedDefinition : +# 9| mu0_2(unknown) = UnmodeledDefinition : +# 9| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[y] : +# 9| mu0_5(int) = InitializeParameter[y] : &:r0_4 +# 10| r0_6(glval) = VariableAddress[#return] : +# 10| r0_7(int) = Constant[6] : +#-----| r0_8(S *) = CopyValue : r0_3 +# 10| r0_9(glval) = FieldAddress[x] : r0_8 +# 10| r0_10(int) = Load : &:r0_9, ~mu0_2 +# 10| r0_11(int) = Add : r0_7, r0_10 +# 10| r0_12(glval) = VariableAddress[y] : +# 10| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 10| r0_14(int) = Add : r0_11, r0_13 +# 10| mu0_15(int) = Store : &:r0_6, r0_14 +# 9| r0_16(glval) = VariableAddress[#return] : +# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 9| v0_18(void) = UnmodeledUse : mu* +# 9| v0_19(void) = ExitFunction : + # 14| void Bad::CallBadMemberFunction() # 14| Block 0 # 14| v0_0(void) = EnterFunction : diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected index 7af2f7c8c17..e745ca0142d 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected @@ -1,3 +1,7 @@ +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:48:25:55 | __second | segfault.cpp:15:7:15:11 | tuple | diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index 0f20692d443..ae10f9ddf63 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | __va_list_tag | | -| test.cpp:3:8:3:9 | s1<> | | -| test.cpp:3:8:3:9 | s1<> | | +| test.cpp:3:8:3:9 | s1<> | bool | +| test.cpp:3:8:3:9 | s1<> | bool | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:7:8:7:9 | s3> | (unnamed) | diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.expected b/cpp/ql/test/library-tests/templates/CPP-204/element.expected index 6cb84a117d5..b1662c2a3b3 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.expected +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.expected @@ -1,6 +1,12 @@ | file://:0:0:0:0 | | | file://:0:0:0:0 | 0 | | file://:0:0:0:0 | (global namespace) | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | __va_list_tag & | | file://:0:0:0:0 | __va_list_tag && | From 6334ad92c5de06fa362f51e4727d3da5397f11ba Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:25:15 +0100 Subject: [PATCH 120/232] C++: Add DB Upgrade script. --- .../old.dbscheme | 1918 ++++++++++++++++ .../semmlecode.cpp.dbscheme | 1933 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3853 insertions(+) create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme new file mode 100644 index 00000000000..98a075d5495 --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme @@ -0,0 +1,1918 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..bd182f697bf --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme @@ -0,0 +1,1933 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties new file mode 100644 index 00000000000..3388d1abe28 --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties @@ -0,0 +1,2 @@ +description: Add support for value template paramters. +compatibility: partial From 4ab87291f35bb831dae94d314f91308bd4c0c2d1 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 15:29:16 +0100 Subject: [PATCH 121/232] C++: Further use of TemplateArgumentValue --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 6 ++++++ cpp/ql/src/semmle/code/cpp/exprs/Call.qll | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index a3a93aaca96..a10faf0f918 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -197,6 +197,12 @@ abstract class Declaration extends Locatable, @declaration { */ final Type getATemplateArgument() { result = getTemplateArgument(_) } + /** + * Gets a template argument used to instantiate this declaration from a template. + * When called on a template, this will return a template parameter value. + */ + final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } + /** * Gets the `i`th template argument used to instantiate this declaration from a * template. When called on a template, this will return the `i`th template parameter. diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 882918316f6..85807cf0d14 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -141,15 +141,27 @@ class FunctionCall extends Call, @funbindexpr { /** Gets an explicit template argument for this call. */ Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + /** Gets an explicit template argument value for this call. */ + Expr getAnExplicitTemplateArgumentValue() { result = getExplicitTemplateArgumentValue(_) } + /** Gets a template argument for this call. */ Type getATemplateArgument() { result = getTarget().getATemplateArgument() } + /** Gets a template argument value for this call. */ + Expr getATemplateArgumentValue() { result = getTarget().getATemplateArgumentValue() } + /** Gets the nth explicit template argument for this call. */ Type getExplicitTemplateArgument(int n) { n < getNumberOfExplicitTemplateArguments() and result = getTemplateArgument(n) } + /** Gets the nth explicit template argument value for this call. */ + Expr getExplicitTemplateArgumentValue(int n) { + n < getNumberOfExplicitTemplateArguments() and + result = getTemplateArgumentValue(n) + } + /** Gets the number of explicit template arguments for this call. */ int getNumberOfExplicitTemplateArguments() { if numtemplatearguments(underlyingElement(this), _) @@ -160,9 +172,15 @@ class FunctionCall extends Call, @funbindexpr { /** Gets the number of template arguments for this call. */ int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + /** Gets the number of template argument which are values for this call. */ + int getNumberOfTemplateArgumentValues() { result = count(int i | exists(getTemplateArgumentValue(i))) } + /** Gets the nth template argument for this call (indexed from 0). */ Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + /** Gets the nth template argument value for this call (indexed from 0). */ + Expr getTemplateArgumentValue(int n) { result = getTarget().getTemplateArgumentValue(n) } + /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { exists(int i | From 469832668fae1aa5202bf8881af4b7796949f14c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 15:30:41 +0100 Subject: [PATCH 122/232] C++: Add some simple non-type template tests --- .../templates/nontype_instantiations/classes/test.cpp | 4 ++++ .../templates/nontype_instantiations/classes/test.expected | 2 ++ .../templates/nontype_instantiations/classes/test.ql | 4 ++++ .../templates/nontype_instantiations/functions/test.cpp | 5 +++++ .../templates/nontype_instantiations/functions/test.expected | 2 ++ .../templates/nontype_instantiations/functions/test.ql | 4 ++++ 6 files changed, 21 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp new file mode 100644 index 00000000000..4f16f623daf --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp @@ -0,0 +1,4 @@ +template +class Int { }; + +Int<10> i; diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected new file mode 100644 index 00000000000..524097b88d6 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected @@ -0,0 +1,2 @@ +| test.cpp:2:7:2:9 | Int<10> | file://:0:0:0:0 | int | test.cpp:4:5:4:6 | 10 | +| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql new file mode 100644 index 00000000000..347bb2dba00 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Class c +select c, c.getATemplateArgument(), c.getATemplateArgumentValue() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp new file mode 100644 index 00000000000..625258906db --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp @@ -0,0 +1,5 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +int addToSelf() { return i + i; }; + +int bar() { return addToSelf<10>(); } diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected new file mode 100644 index 00000000000..70e845e7b59 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected @@ -0,0 +1,2 @@ +| test.cpp:3:5:3:5 | addToSelf | file://:0:0:0:0 | int | test.cpp:5:30:5:31 | 10 | +| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql new file mode 100644 index 00000000000..4dd6e754cd6 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Function f +select f, f.getATemplateArgument(), f.getATemplateArgumentValue() From 57cd9b3990f2396e36c3d38c53db8ca4e6f70e79 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Mon, 21 Oct 2019 17:12:20 +0100 Subject: [PATCH 123/232] C++: Update test results We now support getting the name used for non-type template parameters --- .../ptr_to_member/segfault/exprs.expected | 8 ++++---- .../library-tests/templates/CPP-204/element.expected | 12 ++++++------ .../nontype_instantiations/classes/test.expected | 2 +- .../nontype_instantiations/functions/test.expected | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected index e745ca0142d..e5539a762ab 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected @@ -1,7 +1,7 @@ -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | __i | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:48:25:55 | __second | segfault.cpp:15:7:15:11 | tuple | diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.expected b/cpp/ql/test/library-tests/templates/CPP-204/element.expected index b1662c2a3b3..44384471af9 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.expected +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.expected @@ -1,12 +1,12 @@ | file://:0:0:0:0 | | | file://:0:0:0:0 | 0 | | file://:0:0:0:0 | (global namespace) | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | B | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | Y | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | __va_list_tag & | | file://:0:0:0:0 | __va_list_tag && | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected index 524097b88d6..ffa9bfb2cf4 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected @@ -1,2 +1,2 @@ | test.cpp:2:7:2:9 | Int<10> | file://:0:0:0:0 | int | test.cpp:4:5:4:6 | 10 | -| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | +| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | i | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected index 70e845e7b59..493e9f03b20 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected @@ -1,2 +1,2 @@ | test.cpp:3:5:3:5 | addToSelf | file://:0:0:0:0 | int | test.cpp:5:30:5:31 | 10 | -| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | +| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | i | From ca898d4be04ec3d899637e2e9e1627c5f5fd5541 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 22 Oct 2019 10:54:14 +0100 Subject: [PATCH 124/232] C++: Further nontype template testcases. --- .../nontype_instantiations/general/test.cpp | 19 +++++++++++++++++++ .../general/test.expected | 10 ++++++++++ .../nontype_instantiations/general/test.ql | 4 ++++ 3 files changed, 33 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp new file mode 100644 index 00000000000..1baabe3ca30 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp @@ -0,0 +1,19 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +struct C { }; + +static const int one1 = 1, one2 = 1; +C c = C(); +C e; + +template +struct D { }; + +D a; +D b; + +template +struct E { }; + +E z; + diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected new file mode 100644 index 00000000000..70dfdbc3edf --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected @@ -0,0 +1,10 @@ +| test.cpp:3:8:3:8 | C<1> | file://:0:0:0:0 | int | test.cpp:5:25:5:25 | 1 | +| test.cpp:3:8:3:8 | C<2> | file://:0:0:0:0 | int | file://:0:0:0:0 | 2 | +| test.cpp:3:8:3:8 | C | file://:0:0:0:0 | int | file://:0:0:0:0 | x | +| test.cpp:10:8:10:8 | D | test.cpp:9:19:9:19 | T | file://:0:0:0:0 | X | +| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | int | test.cpp:12:8:12:8 | 2 | +| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | long | file://:0:0:0:0 | 2 | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | T * | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | test.cpp:15:19:15:19 | T | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int | file://:0:0:0:0 | 0 | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int * | file://:0:0:0:0 | 0 | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql new file mode 100644 index 00000000000..8915d6523b6 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Declaration d +select d, d.getATemplateArgument(), d.getATemplateArgumentValue() From f1c3ce04d1ae8a17a37dcea8010872ebe3377760 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 22 Oct 2019 10:54:58 +0100 Subject: [PATCH 125/232] C++: Correct spelling mistake --- .../98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties index 3388d1abe28..495bdeebdac 100644 --- a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties @@ -1,2 +1,2 @@ -description: Add support for value template paramters. +description: Add support for value template parameters. compatibility: partial From 809d97de02f362e10381d2fc23b0c989705d7c40 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Wed, 23 Oct 2019 16:29:32 +0100 Subject: [PATCH 126/232] C++: Print print nontype template params --- cpp/ql/src/semmle/code/cpp/Print.qll | 10 +++++++++- cpp/ql/test/library-tests/ir/ir/PrintAST.expected | 7 ++++--- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index ab979d89b03..7be1537e83b 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -35,6 +35,14 @@ private string getParameterTypeString(Type parameterType) { else result = parameterType.(DumpType).getTypeIdentityString() } +private string getTemplateArgumentString(Declaration d, int i) { + if exists(d.getTemplateArgumentValue(i)) + then + result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + " " + d.getTemplateArgumentValue(i) + else + result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() +} + /** * A `Declaration` extended to add methods for generating strings useful only for dumps and debugging. */ @@ -56,7 +64,7 @@ abstract private class DumpDeclaration extends Declaration { strictconcat(int i | exists(this.getTemplateArgument(i)) | - this.getTemplateArgument(i).(DumpType).getTypeIdentityString(), ", " order by i + getTemplateArgumentString(this, i), ", " order by i ) + ">" else result = "" } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e61fe2b440f..dab6a40fae6 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -67,7 +67,7 @@ bad_asts.cpp: # 5| params: #-----| 0: [Parameter] p#0 #-----| Type = [RValueReferenceType] S && -# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) +# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -92,7 +92,7 @@ bad_asts.cpp: # 10| 1: [VariableAccess] y # 10| Type = [IntType] int # 10| ValueCategory = prvalue(load) -# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) +# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -104,8 +104,9 @@ bad_asts.cpp: # 10| 0: [AddExpr] ... + ... # 10| Type = [IntType] int # 10| ValueCategory = prvalue -# 10| 0: [Literal] Unknown literal +# 10| 0: [Literal] t # 10| Type = [IntType] int +# 10| Value = [Literal] t # 10| ValueCategory = prvalue # 10| 1: [PointerFieldAccess] x # 10| Type = [IntType] int diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index f0c96d2bfa0..b38e63e6e76 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,5 +1,5 @@ bad_asts.cpp: -# 9| int Bad::S::MemberFunction(int) +# 9| int Bad::S::MemberFunction(int) # 9| Block 0 # 9| v0_0(void) = EnterFunction : # 9| mu0_1(unknown) = AliasedDefinition : From afeaa6254d4fb367c02bad6e0edb12963402bbd4 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 29 Oct 2019 14:06:15 +0000 Subject: [PATCH 127/232] C++: Improve Template Value docs. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 33 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index a10faf0f918..b3d12efe1e9 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -193,19 +193,34 @@ abstract class Declaration extends Locatable, @declaration { /** * Gets a template argument used to instantiate this declaration from a template. - * When called on a template, this will return a template parameter. + * When called on a template, this will return a template parameter type for + * both typed and non-typed parameters. */ final Type getATemplateArgument() { result = getTemplateArgument(_) } /** * Gets a template argument used to instantiate this declaration from a template. - * When called on a template, this will return a template parameter value. + * When called on a template, this will return a non-typed template + * parameter value. */ final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a - * template. When called on a template, this will return the `i`th template parameter. + * template. When called on a template, this will return the `i`th template + * parameter's type. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgument(0)` return `T`, and + * `getTemplateArgument(1)` return `T`. + * + * `Foo bar; + * + * Will have `getTemplateArgument())` return `int`, and + * `getTemplateArgument(1)` return `int`. */ Type getTemplateArgument(int index) { none() } @@ -213,6 +228,18 @@ abstract class Declaration extends Locatable, @declaration { * Gets the `i`th template argument value used to instantiate this declaration * from a template. When called on a template, this will return the `i`th template * parameter value if it exists. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgumentValue(1)` return `X`, and no result for + * `getTemplateArgumentValue(0)`. + * + * `Foo bar; + * + * Will have `getTemplateArgumentValue(1)` return `10`, and no result for + * `getTemplateArgumentValue(0)`. */ Expr getTemplateArgumentValue(int index) { none() } From 45ec8527c3c03812e2d02bfd8abb4de4a91a945a Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 29 Oct 2019 16:21:41 +0000 Subject: [PATCH 128/232] C++: Update expected test output. --- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b38e63e6e76..a188c1b3629 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -20,7 +20,8 @@ bad_asts.cpp: # 9| r0_16(glval) = VariableAddress[#return] : # 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 # 9| v0_18(void) = UnmodeledUse : mu* -# 9| v0_19(void) = ExitFunction : +# 9| v0_19(void) = AliasedUse : ~mu0_2 +# 9| v0_20(void) = ExitFunction : # 14| void Bad::CallBadMemberFunction() # 14| Block 0 From 6fe22a76da7dd14eda5b002df5d3788c2f366652 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 1 Nov 2019 14:31:51 +0000 Subject: [PATCH 129/232] C++: Change API for exposing template parameters. Note that Declaration::getTemplateArgumentType() and Declaration::getTemplateArgumentValue() need to be public so that they can be overriden in derived classes. --- cpp/ql/src/semmle/code/cpp/Class.qll | 4 +- cpp/ql/src/semmle/code/cpp/Declaration.qll | 51 ++++++++++++++----- cpp/ql/src/semmle/code/cpp/Function.qll | 2 +- cpp/ql/src/semmle/code/cpp/Print.qll | 8 +-- cpp/ql/src/semmle/code/cpp/Type.qll | 2 +- cpp/ql/src/semmle/code/cpp/Variable.qll | 2 +- cpp/ql/src/semmle/code/cpp/exprs/Call.qll | 21 ++++---- .../templates/CPP-202/template_args.expected | 4 +- .../nontype_instantiations/classes/test.ql | 2 +- .../nontype_instantiations/functions/test.ql | 2 +- .../general/test.expected | 23 +++++---- .../nontype_instantiations/general/test.ql | 14 ++++- 12 files changed, 86 insertions(+), 49 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 44e8b4e65ef..5ccf6193c4f 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -610,7 +610,7 @@ class Class extends UserType { * class template. When called on a class template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int i) { + override Type getTemplateArgumentType(int i) { class_template_argument(underlyingElement(this), i, unresolveElement(result)) } @@ -632,7 +632,7 @@ class Class extends UserType { } override predicate involvesTemplateParameter() { - getATemplateArgument().involvesTemplateParameter() + getATemplateArgument().(Type).involvesTemplateParameter() } /** Holds if this class, struct or union was declared 'final'. */ diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index b3d12efe1e9..9c8ce250d8d 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -196,33 +196,36 @@ abstract class Declaration extends Locatable, @declaration { * When called on a template, this will return a template parameter type for * both typed and non-typed parameters. */ - final Type getATemplateArgument() { result = getTemplateArgument(_) } + final Locatable getATemplateArgument() { result = getTemplateArgument(_) } /** * Gets a template argument used to instantiate this declaration from a template. * When called on a template, this will return a non-typed template * parameter value. */ - final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } + final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a - * template. When called on a template, this will return the `i`th template - * parameter's type. + * template. * * For example: * * `template class Foo;` * * Will have `getTemplateArgument(0)` return `T`, and - * `getTemplateArgument(1)` return `T`. + * `getTemplateArgument(1)` return `X`. * * `Foo bar; * * Will have `getTemplateArgument())` return `int`, and - * `getTemplateArgument(1)` return `int`. + * `getTemplateArgument(1)` return `1`. */ - Type getTemplateArgument(int index) { none() } + final Locatable getTemplateArgument(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentValue(index) + else result = getTemplateArgumentType(index) + } /** * Gets the `i`th template argument value used to instantiate this declaration @@ -233,20 +236,44 @@ abstract class Declaration extends Locatable, @declaration { * * `template class Foo;` * - * Will have `getTemplateArgumentValue(1)` return `X`, and no result for - * `getTemplateArgumentValue(0)`. + * Will have `getTemplateArgumentKind(1)` return `T`, and no result for + * `getTemplateArgumentKind(0)`. * * `Foo bar; * - * Will have `getTemplateArgumentValue(1)` return `10`, and no result for - * `getTemplateArgumentValue(0)`. + * Will have `getTemplateArgumentKind(1)` return `int`, and no result for + * `getTemplateArgumentKind(0)`. */ - Expr getTemplateArgumentValue(int index) { none() } + final Locatable getTemplateArgumentKind(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentType(index) + else none() + } /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + + /** + * INTERNAL: Do not use. + * + * Gets a Type for a template argument. May be the template argument itself + * or the type of a non-type template argument. + * + * Use `getTemplateArgument` or `getTemplateKind` instead. + */ + Type getTemplateArgumentType(int index) { none() } + + /** + * INTERNAL: Do not use. + * + * Gets an Expression representing the value of a non-type template + * argument. + * + * Use `getTemplateArgument` or `getTemplateKind` instead. + */ + Expr getTemplateArgumentValue(int index) { none() } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index be031f2b915..5436c3ba218 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -348,7 +348,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * function template. When called on a function template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int index) { + override Type getTemplateArgumentType(int index) { function_template_argument(underlyingElement(this), index, unresolveElement(result)) } diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index 7be1537e83b..e3ad19f6028 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -36,11 +36,11 @@ private string getParameterTypeString(Type parameterType) { } private string getTemplateArgumentString(Declaration d, int i) { - if exists(d.getTemplateArgumentValue(i)) + if exists(d.getTemplateArgumentKind(i)) then - result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + " " + d.getTemplateArgumentValue(i) - else - result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + result = d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " + + d.getTemplateArgument(i) + else result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() } /** diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 10a1b6b1724..ea1e7fd5026 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -210,7 +210,7 @@ class Type extends Locatable, @type { // A function call that provides an explicit template argument that refers to T uses T. // We exclude calls within instantiations, since they do not appear directly in the source. exists(FunctionCall c | - c.getAnExplicitTemplateArgument().refersTo(this) and + c.getAnExplicitTemplateArgument().(Type).refersTo(this) and result = c and not c.getEnclosingFunction().isConstructedFrom(_) ) diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index deae1069aab..689f1c3bfa5 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -160,7 +160,7 @@ class Variable extends Declaration, @variable { * variable template. When called on a variable template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int index) { + override Type getTemplateArgumentType(int index) { variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 85807cf0d14..22a25969a8f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -139,27 +139,27 @@ class FunctionCall extends Call, @funbindexpr { override string getCanonicalQLClass() { result = "FunctionCall" } /** Gets an explicit template argument for this call. */ - Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } /** Gets an explicit template argument value for this call. */ - Expr getAnExplicitTemplateArgumentValue() { result = getExplicitTemplateArgumentValue(_) } + Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) } /** Gets a template argument for this call. */ - Type getATemplateArgument() { result = getTarget().getATemplateArgument() } + Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() } /** Gets a template argument value for this call. */ - Expr getATemplateArgumentValue() { result = getTarget().getATemplateArgumentValue() } + Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() } /** Gets the nth explicit template argument for this call. */ - Type getExplicitTemplateArgument(int n) { + Locatable getExplicitTemplateArgument(int n) { n < getNumberOfExplicitTemplateArguments() and result = getTemplateArgument(n) } /** Gets the nth explicit template argument value for this call. */ - Expr getExplicitTemplateArgumentValue(int n) { + Locatable getExplicitTemplateArgumentKind(int n) { n < getNumberOfExplicitTemplateArguments() and - result = getTemplateArgumentValue(n) + result = getTemplateArgumentKind(n) } /** Gets the number of explicit template arguments for this call. */ @@ -172,14 +172,11 @@ class FunctionCall extends Call, @funbindexpr { /** Gets the number of template arguments for this call. */ int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } - /** Gets the number of template argument which are values for this call. */ - int getNumberOfTemplateArgumentValues() { result = count(int i | exists(getTemplateArgumentValue(i))) } - /** Gets the nth template argument for this call (indexed from 0). */ - Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } /** Gets the nth template argument value for this call (indexed from 0). */ - Expr getTemplateArgumentValue(int n) { result = getTarget().getTemplateArgumentValue(n) } + Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) } /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index ae10f9ddf63..f38eef610e4 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | __va_list_tag | | -| test.cpp:3:8:3:9 | s1<> | bool | -| test.cpp:3:8:3:9 | s1<> | bool | +| test.cpp:3:8:3:9 | s1<> | {...} | +| test.cpp:3:8:3:9 | s1<> | (null) | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:7:8:7:9 | s3> | (unnamed) | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql index 347bb2dba00..900424eb501 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql @@ -1,4 +1,4 @@ import cpp from Class c -select c, c.getATemplateArgument(), c.getATemplateArgumentValue() +select c, c.getATemplateArgumentKind(), c.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql index 4dd6e754cd6..98f8a4112d4 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql @@ -1,4 +1,4 @@ import cpp from Function f -select f, f.getATemplateArgument(), f.getATemplateArgumentValue() +select f, f.getATemplateArgumentKind(), f.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected index 70dfdbc3edf..fa5df86f68f 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected @@ -1,10 +1,13 @@ -| test.cpp:3:8:3:8 | C<1> | file://:0:0:0:0 | int | test.cpp:5:25:5:25 | 1 | -| test.cpp:3:8:3:8 | C<2> | file://:0:0:0:0 | int | file://:0:0:0:0 | 2 | -| test.cpp:3:8:3:8 | C | file://:0:0:0:0 | int | file://:0:0:0:0 | x | -| test.cpp:10:8:10:8 | D | test.cpp:9:19:9:19 | T | file://:0:0:0:0 | X | -| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | int | test.cpp:12:8:12:8 | 2 | -| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | long | file://:0:0:0:0 | 2 | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | T * | file://:0:0:0:0 | X | -| test.cpp:16:8:16:8 | E | test.cpp:15:19:15:19 | T | file://:0:0:0:0 | X | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int | file://:0:0:0:0 | 0 | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int * | file://:0:0:0:0 | 0 | +| test.cpp:3:8:3:8 | C<1> | 0 | int | test.cpp:5:25:5:25 | 1 | +| test.cpp:3:8:3:8 | C<2> | 0 | int | file://:0:0:0:0 | 2 | +| test.cpp:3:8:3:8 | C | 0 | int | file://:0:0:0:0 | x | +| test.cpp:10:8:10:8 | D | 0 | | test.cpp:9:19:9:19 | T | +| test.cpp:10:8:10:8 | D | 1 | T | file://:0:0:0:0 | X | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | int | +| test.cpp:10:8:10:8 | D | 1 | int | test.cpp:12:8:12:8 | 2 | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | long | +| test.cpp:10:8:10:8 | D | 1 | long | file://:0:0:0:0 | 2 | +| test.cpp:16:8:16:8 | E | 0 | | test.cpp:15:19:15:19 | T | +| test.cpp:16:8:16:8 | E | 1 | T * | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | 0 | | file://:0:0:0:0 | int | +| test.cpp:16:8:16:8 | E | 1 | int * | file://:0:0:0:0 | 0 | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql index 8915d6523b6..68d597e0f98 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql @@ -1,4 +1,14 @@ import cpp -from Declaration d -select d, d.getATemplateArgument(), d.getATemplateArgumentValue() +string maybeGetTemplateArgumentKind(Declaration d, int i) { + ( + if exists(d.getTemplateArgumentKind(i)) + then result = d.getTemplateArgumentKind(i).toString() + else result = "" + ) and + i = [0 .. d.getNumberOfTemplateArguments()] +} + +from Declaration d, int i +where i >= 0 and i < d.getNumberOfTemplateArguments() +select d, i, maybeGetTemplateArgumentKind(d, i), d.getTemplateArgument(i) From 6b4506dbea2edc9113c39238041d5a337087142c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 1 Nov 2019 14:35:48 +0000 Subject: [PATCH 130/232] C++: Update schema stats --- cpp/ql/src/semmlecode.cpp.dbscheme.stats | 10940 +++++++++++---------- 1 file changed, 5769 insertions(+), 5171 deletions(-) diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme.stats b/cpp/ql/src/semmlecode.cpp.dbscheme.stats index bd1964b0d4f..3a73724456a 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/src/semmlecode.cpp.dbscheme.stats @@ -1,15 +1,15 @@ @compilation -10588 +10177 @externalDataElement -72 +70 @duplication -185332 +185440 @similarity @@ -17,7 +17,7 @@ @external_package -133 +128 @svnentry @@ -25,67 +25,67 @@ @location_default -9664446 +9335283 @location_stmt -2176932 +2178211 @location_expr -9745314 +9746017 @diagnostic -76160 +73204 @file -66167 +63599 @folder -12107 +11637 @macroinvocation -40814994 +39320374 @function -3565918 +3552236 @fun_decl -3657006 +3635139 @var_decl -5579181 +5495954 @type_decl -1469165 +1413769 @namespace_decl -151627 +145743 @using -320601 +308161 @static_assert -132358 +131017 @parameter -4779409 +4724692 @membervariable -325099 +321201 @globalvariable @@ -93,47 +93,47 @@ @localvariable -527101 +521758 @enumconstant -94487 +94097 @builtintype -559 +537 @derivedtype -4572495 +4651908 @decltype -45841 +44063 @usertype -4363319 +4337028 @mangledname -532986 +514256 @type_mention -1699359 +1682135 @routinetype -444572 +436132 @ptrtomember -12180 +13227 @specifier -547 +525 @gnuattribute @@ -141,11 +141,11 @@ @stdattribute -369 +365 @declspec -58441 +57849 @msattribute @@ -153,7 +153,7 @@ @alignas -267 +257 @attribute_arg_empty @@ -161,55 +161,55 @@ @attribute_arg_token -15930 +15768 @attribute_arg_constant -111500 +111565 @attribute_arg_type -60 +58 @derivation -370309 +392220 @frienddecl -231178 +222208 @comment -1743633 +1675974 @namespace -8497 +8167 @specialnamequalifyingelement -12 +11 @namequalifier -1125621 +1116919 @value -8776796 +8788031 @initialiser -1685017 +1668506 @literal -4374193 +4381545 @errorexpr -48066 +46201 @address_of @@ -217,15 +217,15 @@ @reference_to -1077837 +1039133 @indirect -294638 +294811 @ref_indirect -1267903 +1225212 @array_to_pointer @@ -233,31 +233,31 @@ @vacuous_destructor_call -4449 +4288 @assume -3328 +3294 @parexpr -3001187 +3002950 @arithnegexpr -654789 +654792 @unaryplusexpr -206 +198 @complementexpr -28027 +28043 @notexpr -357915 +358125 @conjugation @@ -265,51 +265,51 @@ @realpartexpr -72 +70 @imagpartexpr -72 +70 @postincrexpr -43039 +43064 @postdecrexpr -5401 +5404 @preincrexpr -63954 +61508 @predecrexpr -26586 +25554 @conditionalexpr -154429 +154519 @addexpr -209503 +209626 @subexpr -134974 +135053 @mulexpr -91616 +91670 @divexpr -63973 +64010 @remexpr -4657 +4660 @jmulexpr @@ -337,59 +337,59 @@ @paddexpr -87252 +87303 @psubexpr -23151 +23165 @pdiffexpr -25868 +24865 @lshiftexpr -347564 +347768 @rshiftexpr -59286 +59321 @andexpr -236938 +237077 @orexpr -145217 +143745 @xorexpr -37281 +37303 @eqexpr -212621 +212746 @neexpr -88456 +88508 @gtexpr -43936 +43962 @ltexpr -54831 +54863 @geexpr -22361 +22374 @leexpr -213875 +214001 @minexpr @@ -401,7 +401,7 @@ @assignexpr -551713 +552037 @assignaddexpr @@ -413,15 +413,15 @@ @assignmulexpr -7597 +7302 @assigndivexpr -2297 +2208 @assignremexpr -303 +292 @assignlshiftexpr @@ -433,39 +433,39 @@ @assignandexpr -7740 +7744 @assignorexpr -18663 +18674 @assignxorexpr -21992 +22005 @assignpaddexpr -13214 +13080 @assignpsubexpr -583 +577 @andlogicalexpr -116840 +116908 @orlogicalexpr -57827 +57861 @commaexpr -10721 +10329 @subscriptexpr -165754 +165851 @virtfunptrexpr @@ -473,15 +473,15 @@ @callexpr -248513 +239197 @vastartexpr -3710 +3673 @vaargexpr -1094 +1051 @vaendexpr @@ -493,63 +493,63 @@ @varaccess -5376400 +5325591 @thisaccess -1181340 +1169367 @new_expr -29515 +28370 @delete_expr -6564 +6309 @throw_expr -23777 +22855 @condition_decl -7646 +7349 @braced_init_list -133 +128 @type_id -4899 +4708 @runtime_sizeof -281622 +281787 @runtime_alignof -1560 +1561 @sizeof_pack -267 +502 @expr_stmt -160546 +160640 @routineexpr -2309113 +2232038 @type_operand -127928 +128003 @offsetofexpr -35356 +35377 @hasassignexpr @@ -597,11 +597,11 @@ @isbaseofexpr -19 +39 @isclassexpr -6 +215 @isconvtoexpr @@ -609,15 +609,15 @@ @isemptyexpr -5 +175 @isenumexpr -3 +23 @ispodexpr -3 +11 @ispolyexpr @@ -629,7 +629,7 @@ @typescompexpr -46285 +46312 @intaddrexpr @@ -637,11 +637,11 @@ @hastrivialdestructor -97 +105 @uuidof -856 +848 @aggregateliteral @@ -649,11 +649,11 @@ @delete_array_expr -1495 +1437 @new_array_expr -5364 +5310 @foldexpr @@ -661,59 +661,59 @@ @ctordirectinit -93264 +89645 @ctorvirtualinit -6904 +6636 @ctorfieldinit -209661 +201538 @ctordelegatinginit -741 +712 @dtordirectdestruct -30828 +30111 @dtorvirtualdestruct -2698 +2594 @dtorfielddestruct -32542 +31279 @static_cast -224735 +226064 @reinterpret_cast -31207 +30891 @const_cast -5847 +5643 @dynamic_cast -1094 +1051 @c_style_cast -4242732 +4244118 @lambdaexpr -12641 +12513 @param_ref -53208 +51144 @noopexpr @@ -745,7 +745,7 @@ @istrivialexpr -2565 +2512 @isstandardlayoutexpr @@ -753,7 +753,7 @@ @istriviallycopyableexpr -48 +46 @isliteraltypeexpr @@ -813,11 +813,11 @@ @isfinalexpr -2 +175 @noexceptexpr -449 +432 @builtinshufflevector @@ -825,11 +825,11 @@ @builtinchooseexpr -7028 +7032 @builtinaddressof -4388 +4218 @vec_fill @@ -845,67 +845,67 @@ @lambdacapture -21730 +21509 @stmt_expr -1284462 +1271443 @stmt_if -524558 +524866 @stmt_while -32907 +31630 @stmt_goto -111432 +111498 @stmt_label -85508 +85558 @stmt_return -1197201 +1154730 @stmt_block -1398281 +1348007 @stmt_end_test_while -149900 +149988 @stmt_for -32387 +32059 @stmt_switch_case -281530 +281695 @stmt_switch -55225 +55258 @stmt_asm -251715 +251863 @stmt_try_block -18964 +18228 @stmt_microsoft_try -171 +169 @stmt_decl -647378 +623601 @stmt_set_vla_size @@ -917,27 +917,27 @@ @stmt_assigned_goto -9137 +9142 @stmt_empty -103681 +102630 @stmt_continue -8603 +8608 @stmt_break -232406 +232543 @stmt_range_based_for -24 +23 @stmt_handler -21888 +21666 @stmt_constexpr_if @@ -945,51 +945,51 @@ @ppd_plain_include -321707 +309224 @ppd_define -349947 +336367 @ppd_if -171077 +164439 @ppd_ifdef -66823 +64230 @ppd_ifndef -91793 +88231 @ppd_elif -22768 +21885 @ppd_else -63638 +61169 @ppd_endif -329694 +316901 @ppd_undef -21152 +20331 @ppd_line -12523 +12530 @ppd_error -48 +46 @ppd_pragma -37040 +36665 @ppd_objc_import @@ -997,7 +997,7 @@ @ppd_include_next -97 +93 @ppd_warning @@ -1005,7 +1005,7 @@ @link_target -644 +619 @xmldtd @@ -1034,15 +1034,15 @@ compilations -10588 +10177 id -10588 +10177 cwd -12 +11 @@ -1056,7 +1056,7 @@ 1 2 -10588 +10177 @@ -1072,7 +1072,7 @@ 871 872 -12 +11 @@ -1082,11 +1082,11 @@ compilation_args -394124 +394355 id -4637 +4640 num @@ -1094,7 +1094,7 @@ arg -20097 +20109 @@ -1113,7 +1113,7 @@ 87 88 -3527 +3529 88 @@ -1149,7 +1149,7 @@ 86 87 -3529 +3531 87 @@ -1322,12 +1322,12 @@ 1 2 -19123 +19134 2 2575 -974 +975 @@ -1343,7 +1343,7 @@ 1 2 -19748 +19760 2 @@ -1358,19 +1358,19 @@ compilation_compiling_files -10588 +10177 id -10588 +10177 num -12 +11 file -5373 +5164 @@ -1384,7 +1384,7 @@ 1 2 -10588 +10177 @@ -1400,7 +1400,7 @@ 1 2 -10588 +10177 @@ -1416,7 +1416,7 @@ 871 872 -12 +11 @@ -1432,7 +1432,7 @@ 442 443 -12 +11 @@ -1448,17 +1448,17 @@ 1 2 -303 +292 2 3 -5044 +4849 3 14 -24 +23 @@ -1474,7 +1474,7 @@ 1 2 -5373 +5164 @@ -1484,23 +1484,23 @@ compilation_time -42255 +40616 id -10563 +10154 num -12 +11 kind -48 +46 seconds -12375 +11965 @@ -1514,7 +1514,7 @@ 1 2 -10563 +10154 @@ -1530,7 +1530,7 @@ 4 5 -10563 +10154 @@ -1544,14 +1544,19 @@ 12 +2 +3 +58 + + 3 4 -3160 +2792 4 5 -7403 +7302 @@ -1567,7 +1572,7 @@ 869 870 -12 +11 @@ -1583,7 +1588,7 @@ 4 5 -12 +11 @@ -1597,9 +1602,9 @@ 12 -1018 -1019 -12 +1024 +1025 +11 @@ -1615,7 +1620,7 @@ 869 870 -48 +46 @@ -1631,7 +1636,7 @@ 1 2 -48 +46 @@ -1645,24 +1650,24 @@ 12 -6 -7 -12 +7 +8 +11 -9 -10 -12 +10 +11 +11 -561 -562 -12 +560 +561 +11 -597 -598 -12 +591 +592 +11 @@ -1678,27 +1683,27 @@ 1 2 -7755 +7501 2 3 -2613 +2617 3 4 -1045 +759 4 -324 -936 +8 +899 -417 -614 -24 +8 +632 +186 @@ -1714,7 +1719,7 @@ 1 2 -12375 +11965 @@ -1730,12 +1735,17 @@ 1 2 -10490 +10305 2 3 -1884 +1635 + + +3 +4 +23 @@ -1745,23 +1755,23 @@ diagnostic_for -940397 +903906 diagnostic -940397 +73204 compilation -10223 +9826 file_number -12 +11 file_number_diagnostic_number -7208 +6929 @@ -1775,7 +1785,17 @@ 1 2 -940397 +9861 + + +2 +3 +60456 + + +118 +840 +2886 @@ -1791,7 +1811,7 @@ 1 2 -940397 +73204 @@ -1807,7 +1827,12 @@ 1 2 -940397 +73181 + + +2 +3 +23 @@ -1823,37 +1848,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1869,7 +1894,7 @@ 1 2 -10223 +9826 @@ -1885,37 +1910,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1931,7 +1956,7 @@ 6265 6266 -12 +11 @@ -1947,7 +1972,7 @@ 841 842 -12 +11 @@ -1963,7 +1988,7 @@ 593 594 -12 +11 @@ -1979,47 +2004,47 @@ 1 2 -2954 +2839 2 5 -656 +630 5 6 -1057 +1016 7 14 -571 +549 15 16 -60 +58 17 18 -632 +607 18 23 -486 +467 26 40 -583 +560 42 842 -206 +198 @@ -2035,52 +2060,52 @@ 4 9 -619 +595 10 11 -1057 +1016 14 27 -571 +549 30 31 -60 +58 34 35 -632 +607 36 45 -486 +467 52 79 -583 +560 84 85 -194 +186 254 255 -2893 +2780 272 842 -109 +105 @@ -2096,7 +2121,7 @@ 1 2 -7208 +6929 @@ -2106,19 +2131,19 @@ compilation_finished -10588 +10177 id -10588 +10177 cpu_seconds -8436 +7957 elapsed_seconds -182 +186 @@ -2132,7 +2157,7 @@ 1 2 -10588 +10177 @@ -2148,7 +2173,7 @@ 1 2 -10588 +10177 @@ -2164,17 +2189,17 @@ 1 2 -7184 +6730 2 3 -850 +712 3 -12 -401 +9 +514 @@ -2190,12 +2215,12 @@ 1 2 -8023 +7560 2 3 -413 +397 @@ -2211,67 +2236,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 +11 -4 -5 -12 - - -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +27 +28 +11 53 54 -12 +11 -124 -125 -12 +120 +121 +11 -134 -135 -12 +125 +126 +11 -230 -231 -12 +233 +234 +11 -258 -259 -12 +263 +264 +11 @@ -2287,67 +2307,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 +11 -4 -5 -12 - - -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +26 +27 +11 -49 -50 -12 +51 +52 +11 -100 -101 -12 +92 +93 +11 118 119 -12 +11 -172 -173 -12 +163 +164 +11 -217 -218 -12 +215 +216 +11 @@ -2357,23 +2372,23 @@ externalData -145 +140 id -72 +70 path -12 +11 column -24 +23 value -145 +140 @@ -2387,7 +2402,7 @@ 1 2 -72 +70 @@ -2403,7 +2418,7 @@ 2 3 -72 +70 @@ -2419,7 +2434,7 @@ 2 3 -72 +70 @@ -2435,7 +2450,7 @@ 6 7 -12 +11 @@ -2451,7 +2466,7 @@ 2 3 -12 +11 @@ -2467,7 +2482,7 @@ 12 13 -12 +11 @@ -2483,7 +2498,7 @@ 6 7 -24 +23 @@ -2499,7 +2514,7 @@ 1 2 -24 +23 @@ -2515,7 +2530,7 @@ 6 7 -24 +23 @@ -2531,7 +2546,7 @@ 1 2 -145 +140 @@ -2547,7 +2562,7 @@ 1 2 -145 +140 @@ -2563,7 +2578,7 @@ 1 2 -145 +140 @@ -2573,41 +2588,41 @@ snapshotDate -12 +11 snapshotDate -12 +11 sourceLocationPrefix -12 +11 prefix -12 +11 duplicateCode -185332 +185440 id -185332 +185440 relativePath -761 +762 equivClass -76596 +76641 @@ -2621,7 +2636,7 @@ 1 2 -185332 +185440 @@ -2637,7 +2652,7 @@ 1 2 -185332 +185440 @@ -2765,27 +2780,27 @@ 1 2 -20462 +20474 2 3 -32635 +32655 3 4 -10716 +10723 4 5 -6015 +6019 5 9 -5954 +5957 9 @@ -2806,7 +2821,7 @@ 1 2 -75730 +75775 2 @@ -3122,27 +3137,27 @@ tokens -39620249 +39643528 id -279171 +279335 offset -21169 +21181 beginLine -785436 +785898 beginColumn -1302 +1303 endLine -785436 +785898 endColumn @@ -3160,72 +3175,72 @@ 100 101 -8596 +8601 101 102 -27640 +27656 102 105 -22613 +22626 105 108 -24506 +24520 108 111 -13844 +13852 111 114 -23787 +23801 114 116 -22681 +22694 116 124 -23658 +23672 124 132 -21660 +21673 132 154 -21347 +21360 154 186 -21323 +21335 186 202 -23418 +23432 202 416 -20978 +20991 416 3446 -3115 +3117 @@ -3246,47 +3261,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3302,42 +3317,42 @@ 2 26 -22933 +22946 26 31 -22318 +22331 31 32 -2642 +2643 32 33 -163572 +163668 33 51 -21310 +21323 51 61 -22472 +22485 61 80 -21058 +21071 80 132 -2863 +2865 @@ -3358,47 +3373,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3414,42 +3429,42 @@ 2 26 -21667 +21679 26 31 -24352 +24366 31 32 -1622 +1623 32 33 -163861 +163957 33 54 -22103 +22116 54 63 -20942 +20954 63 82 -21488 +21501 82 133 -3133 +3135 @@ -3465,17 +3480,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3485,37 +3500,37 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 250 -1597 +1598 251 982 -1591 +1592 986 45432 -1929 +1930 @@ -3531,17 +3546,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3551,42 +3566,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3602,47 +3617,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1886 +1887 7 12 -1837 +1838 12 15 -1640 +1641 15 23 -1591 +1592 23 68 -1609 +1610 68 161 -1591 +1592 161 @@ -3663,17 +3678,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3683,42 +3698,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3734,47 +3749,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1911 +1912 7 12 -1825 +1826 12 15 -1609 +1610 15 24 -1677 +1678 24 74 -1616 +1617 74 169 -1591 +1592 170 @@ -3795,37 +3810,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -3841,52 +3856,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -3902,47 +3917,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -3958,7 +3973,7 @@ 1 2 -785436 +785898 @@ -3974,47 +3989,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -4430,37 +4445,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -4476,52 +4491,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -4537,7 +4552,7 @@ 1 2 -785436 +785898 @@ -4553,47 +4568,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -4609,47 +4624,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -5039,23 +5054,23 @@ external_packages -133 +128 id -133 +128 namespace -12 +11 package_name -133 +128 version -133 +128 @@ -5069,7 +5084,7 @@ 1 2 -133 +128 @@ -5085,7 +5100,7 @@ 1 2 -133 +128 @@ -5101,7 +5116,7 @@ 1 2 -133 +128 @@ -5117,7 +5132,7 @@ 11 12 -12 +11 @@ -5133,7 +5148,7 @@ 11 12 -12 +11 @@ -5149,7 +5164,7 @@ 11 12 -12 +11 @@ -5165,7 +5180,7 @@ 1 2 -133 +128 @@ -5181,7 +5196,7 @@ 1 2 -133 +128 @@ -5197,7 +5212,7 @@ 1 2 -133 +128 @@ -5213,7 +5228,7 @@ 1 2 -133 +128 @@ -5229,7 +5244,7 @@ 1 2 -133 +128 @@ -5245,7 +5260,7 @@ 1 2 -133 +128 @@ -5255,15 +5270,15 @@ header_to_external_package -9093 +8740 fileid -9093 +8740 package -133 +128 @@ -5277,7 +5292,7 @@ 1 2 -9093 +8740 @@ -5293,42 +5308,42 @@ 1 2 -36 +35 2 3 -12 +11 15 16 -24 +23 63 64 -12 +11 71 72 -12 +11 85 86 -12 +11 243 244 -12 +11 251 252 -12 +11 @@ -6546,31 +6561,31 @@ locations_default -9664446 +9335283 id -9664446 +9335283 container -78275 +75237 startLine -161084 +154834 startColumn -6017 +5818 endLine -160902 +154658 endColumn -8169 +11182 @@ -6584,7 +6599,7 @@ 1 2 -9664446 +9335283 @@ -6600,7 +6615,7 @@ 1 2 -9664446 +9335283 @@ -6616,7 +6631,7 @@ 1 2 -9664446 +9335283 @@ -6632,7 +6647,7 @@ 1 2 -9664446 +9335283 @@ -6648,7 +6663,7 @@ 1 2 -9664446 +9335283 @@ -6664,62 +6679,62 @@ 1 2 -12752 +12257 2 19 -6625 +6368 19 25 -6090 +5818 25 31 -6066 +5830 31 41 -6491 +6204 41 54 -6138 +5854 54 72 -6175 +5877 72 -99 -5968 +98 +5690 -99 -137 -5944 +98 +136 +5702 -137 -221 -5895 +136 +216 +5690 -221 -431 -5871 +216 +417 +5655 -431 +417 19703 -4254 +4288 @@ -6735,62 +6750,62 @@ 1 2 -12752 +12257 2 15 -6503 +6251 15 20 -6758 +6496 20 25 -6102 +5842 25 32 -6710 +6461 32 41 -6284 +6052 41 53 -6321 +6064 53 70 -5932 +5690 70 96 -5908 +5678 96 152 -5883 +5667 152 -325 -5871 +322 +5643 -325 +324 8863 -3245 +3131 @@ -6806,62 +6821,62 @@ 1 2 -12752 +12257 2 4 -6722 +6461 4 8 -7087 +6812 8 11 -5895 +5632 11 14 -6418 +6099 14 18 -6880 +6601 18 23 -6394 +6134 23 29 -6455 +6227 29 37 -6260 +6029 37 50 -6224 +6052 50 78 -5944 +5737 78 -167 -1239 +168 +1191 @@ -6877,62 +6892,62 @@ 1 2 -12752 +12257 2 15 -6479 +6227 15 20 -6795 +6531 20 25 -6029 +5772 25 32 -6710 +6473 32 41 -6297 +6052 41 53 -6309 +6052 53 70 -6017 +5772 70 96 -5920 +5690 96 153 -5932 +5725 153 332 -5883 +5643 332 8863 -3148 +3038 @@ -6948,62 +6963,62 @@ 1 2 -12752 +12257 2 14 -6236 +5994 14 19 -6710 +6414 19 23 -6224 +5994 23 27 -6005 +5690 27 32 -6187 +5994 32 38 -6005 +5690 38 45 -6138 +5830 45 54 -5920 +5713 54 65 -5993 +5807 65 -79 -5883 +80 +5842 -79 -184 -4218 +80 +336 +4007 @@ -7019,62 +7034,62 @@ 1 2 -31193 +29982 2 3 -19802 +19034 3 4 -18234 +17527 4 5 -10260 +9861 5 6 -9129 +8775 6 7 -6734 +6473 7 9 -14344 +13787 9 13 -13943 +13390 13 30 -12350 +11871 30 112 -12119 +11637 112 -2168 -12083 +2116 +11614 -2193 +2135 6440 -887 +876 @@ -7090,42 +7105,42 @@ 1 2 -57268 +55046 2 3 -35496 +34119 3 4 -11341 +10901 4 5 -8983 +8635 5 8 -14794 +14220 8 26 -12363 +11871 26 115 -12095 +11637 115 6440 -8740 +8401 @@ -7141,57 +7156,57 @@ 1 2 -32287 +31034 2 3 -19693 +18929 3 4 -20544 +19747 4 5 -9737 +9359 5 6 -9384 +9020 6 7 -6856 +6590 7 9 -14612 +14033 9 13 -14028 +13495 13 27 -12436 +11953 27 60 -12132 +11637 60 153 -9372 +9032 @@ -7207,22 +7222,22 @@ 1 2 -119911 +115246 2 3 -18976 +18239 3 7 -13530 +13016 7 184 -8667 +8331 @@ -7238,57 +7253,57 @@ 1 2 -32311 +31057 2 3 -19584 +18824 3 4 -19024 +18286 4 5 -10247 +9850 5 6 -9409 +9043 6 7 -6637 +6379 7 9 -14636 +14068 9 13 -13700 +13168 13 28 -12144 +11673 28 -68 -12119 +69 +11813 -68 -190 -11269 +69 +258 +10668 @@ -7304,57 +7319,57 @@ 1 2 -948 +934 2 3 -1142 +1074 3 5 -534 +537 5 8 -547 +514 8 16 -474 +467 16 -38 -461 +37 +444 -39 -126 -461 +37 +119 +444 -135 -517 -461 +125 +511 +444 -553 -5009 -461 +518 +4987 +444 -5423 -19562 -461 +5021 +19113 +444 -23702 -199709 -60 +19590 +199744 +70 @@ -7370,47 +7385,47 @@ 1 2 -2589 +2500 2 3 -522 +525 3 6 -474 +455 6 15 -486 +467 15 55 -461 +444 59 -223 -461 +226 +444 229 -1196 -461 +1198 +444 -1266 +1275 2344 -461 +444 -2536 +2542 6440 -97 +93 @@ -7426,57 +7441,57 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -929 -461 +196 +829 +444 -957 -1965 -461 +851 +1958 +444 -1969 +1958 6490 -303 +327 @@ -7492,55 +7507,55 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -931 -461 +205 +828 +444 -958 -1966 -461 +851 +1962 +467 -1969 +1965 6462 303 @@ -7558,42 +7573,42 @@ 1 2 -2735 +2640 2 3 -522 +525 3 7 -547 +525 7 13 -474 +455 13 29 -498 +479 29 -51 -474 +54 +455 -51 -90 -461 +54 +109 +444 -91 +110 428 -303 +292 @@ -7609,62 +7624,62 @@ 1 2 -30670 +29480 2 3 -20240 +19455 3 4 -17979 +17281 4 5 -10430 +10025 5 6 -8898 +8553 6 7 -6868 +6601 7 9 -14368 +13811 9 13 -13992 +13437 13 30 -12302 +11824 30 111 -12144 +11649 111 -2100 -12071 +2058 +11602 -2100 +2083 6440 -936 +934 @@ -7680,42 +7695,42 @@ 1 2 -56758 +54555 2 3 -35654 +34271 3 4 -11341 +10901 4 5 -9105 +8751 5 7 -11949 +11474 7 19 -12338 +11859 19 76 -12083 +11614 76 6440 -11670 +11229 @@ -7731,22 +7746,22 @@ 1 2 -118792 +114171 2 3 -19267 +18508 3 7 -12983 +12502 7 46 -9858 +9476 @@ -7762,57 +7777,57 @@ 1 2 -31752 +30520 2 3 -20082 +19303 3 4 -20252 +19466 4 5 -9992 +9604 5 6 -9263 +8903 6 7 -6977 +6707 7 9 -14599 +14021 9 13 -14101 +13565 13 27 -12350 +11871 27 60 -12107 +11626 60 153 -9421 +9067 @@ -7828,57 +7843,57 @@ 1 2 -31801 +30567 2 3 -19973 +19197 3 4 -18745 +18017 4 5 -10490 +10083 5 6 -9263 +8903 6 7 -6710 +6449 7 9 -14526 +13963 9 13 -14174 +13612 13 29 -12350 +11871 29 71 -12132 +11602 71 -190 -10734 +258 +10387 @@ -7894,52 +7909,47 @@ 1 2 -2309 +4428 2 3 -1094 +1180 3 4 -607 +888 4 -7 -753 +6 +1004 -7 -17 -656 +6 +13 +841 -17 -49 -619 +13 +61 +841 -55 -236 -619 +61 +698 +841 -241 -4440 -619 +705 +10765 +841 -4617 -11969 -619 - - -12066 -25444 -267 +11014 +25447 +315 @@ -7955,47 +7965,42 @@ 1 2 -3257 +5106 2 3 -1033 +1285 3 4 -583 +1028 4 -9 -644 +7 +969 -9 -29 -619 +7 +33 +841 -29 -166 -619 +33 +376 +841 -172 -1667 -619 +387 +2684 +841 -1667 -2846 -619 - - -2870 +2688 6440 -170 +268 @@ -8011,52 +8016,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +899 4 -7 -741 +6 +1004 -7 -17 -632 +6 +14 +852 -17 -45 -619 +14 +57 +852 -45 -189 -619 +58 +510 +841 -192 -1191 -619 +518 +2401 +841 -1218 -2414 -619 - - -2469 +2415 4808 -243 +245 @@ -8072,42 +8072,42 @@ 1 2 -3367 +5141 2 3 -1130 +1343 3 4 -595 +1028 4 -11 -668 +7 +969 -11 +7 23 -632 +852 23 -40 -632 +47 +864 -40 -68 -632 +47 +81 +864 -68 -82 -510 +81 +83 +116 @@ -8123,52 +8123,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +911 4 -7 -741 +6 +993 -7 -17 -644 +6 +13 +841 -17 -46 -619 +13 +56 +841 -46 -194 -619 +56 +501 +841 -202 -1220 -619 +505 +2374 +841 -1252 -2470 -619 - - -2481 +2398 4808 -230 +268 @@ -8178,31 +8173,31 @@ locations_stmt -2176932 +2178211 id -2176932 +2178211 container -3078 +3080 startLine -296727 +296902 startColumn -1228 +1229 endLine -294872 +295045 endColumn -1493 +1494 @@ -8216,7 +8211,7 @@ 1 2 -2176932 +2178211 @@ -8232,7 +8227,7 @@ 1 2 -2176932 +2178211 @@ -8248,7 +8243,7 @@ 1 2 -2176932 +2178211 @@ -8264,7 +8259,7 @@ 1 2 -2176932 +2178211 @@ -8280,7 +8275,7 @@ 1 2 -2176932 +2178211 @@ -8493,7 +8488,7 @@ 38 48 -251 +252 48 @@ -8534,7 +8529,7 @@ 6 15 -251 +252 15 @@ -8681,37 +8676,37 @@ 1 2 -113847 +113914 2 3 -78993 +79039 3 4 -31327 +31345 4 6 -24942 +24957 6 16 -22619 +22632 16 129 -22275 +22288 129 222 -2722 +2723 @@ -8727,32 +8722,32 @@ 1 2 -175967 +176070 2 3 -51906 +51936 3 5 -22552 +22565 5 13 -22373 +22386 13 125 -22257 +22270 125 176 -1671 +1672 @@ -8768,32 +8763,32 @@ 1 2 -130943 +131019 2 3 -73506 +73549 3 4 -30767 +30785 4 7 -26583 +26598 7 16 -22312 +22325 16 45 -12615 +12623 @@ -8809,27 +8804,27 @@ 1 2 -192251 +192364 2 3 -47310 +47337 3 4 -21765 +21778 4 9 -23264 +23278 9 30 -12136 +12143 @@ -8845,32 +8840,32 @@ 1 2 -156444 +156536 2 3 -62371 +62408 3 4 -20782 +20794 4 9 -24659 +24674 9 30 -22398 +22411 30 73 -10071 +10077 @@ -9266,37 +9261,37 @@ 1 2 -116305 +116374 2 3 -72848 +72891 3 4 -31996 +32015 4 6 -25618 +25633 6 16 -23031 +23044 16 126 -22121 +22134 126 228 -2949 +2951 @@ -9312,27 +9307,27 @@ 1 2 -175604 +175707 2 3 -52066 +52096 3 5 -22207 +22220 5 14 -23375 +23389 14 173 -21617 +21630 @@ -9348,27 +9343,27 @@ 1 2 -194592 +194706 2 3 -42314 +42339 3 4 -20677 +20689 4 8 -22760 +22774 8 32 -14526 +14535 @@ -9384,32 +9379,32 @@ 1 2 -133173 +133251 2 3 -67871 +67910 3 4 -32611 +32630 4 7 -26503 +26518 7 16 -22183 +22196 16 46 -12529 +12536 @@ -9425,32 +9420,32 @@ 1 2 -156272 +156364 2 3 -62230 +62266 3 4 -21132 +21144 4 9 -23756 +23770 9 33 -22318 +22331 33 73 -9162 +9167 @@ -9830,15 +9825,15 @@ locations_expr -9745314 +9746017 id -9745314 +9746017 container -3559 +3563 startLine @@ -9868,7 +9863,7 @@ 1 2 -9745314 +9746017 @@ -9884,7 +9879,7 @@ 1 2 -9745314 +9746017 @@ -9900,7 +9895,7 @@ 1 2 -9745314 +9746017 @@ -9916,7 +9911,7 @@ 1 2 -9745314 +9746017 @@ -9932,7 +9927,7 @@ 1 2 -9745314 +9746017 @@ -9953,67 +9948,67 @@ 4 11 -280 +284 11 -36 -267 +37 +272 -36 -112 -270 +37 +114 +269 -112 -207 +114 +210 +269 + + +210 +328 268 -207 -326 +328 +498 268 -326 -493 -267 +499 +771 +269 -493 -760 -267 +772 +1223 +268 -760 -1208 -267 +1223 +1918 +268 -1210 -1899 -267 +1918 +3307 +268 -1900 -3251 -267 +3322 +7569 +268 -3258 -7330 -267 +7607 +160039 +268 -7359 -51115 -267 - - -51126 +170837 491727 -16 +3 @@ -10029,17 +10024,17 @@ 1 3 -300 +296 3 7 -315 +319 7 17 -271 +272 17 @@ -10049,47 +10044,47 @@ 35 59 -279 +278 59 88 -270 +271 88 138 -268 +271 138 -206 -267 +207 +271 -206 -336 +207 +339 268 -336 -525 +339 +532 268 -525 -946 -267 +532 +949 +268 -947 -2013 -267 +951 +2069 +268 -2019 +2076 142752 -248 +242 @@ -10105,67 +10100,67 @@ 1 3 -308 +307 3 7 -293 +296 7 17 -273 +274 17 -35 -267 +36 +283 -35 -51 -278 +36 +52 +287 -51 -63 -289 +52 +64 +297 -63 -73 -290 +64 +74 +279 -73 -83 +74 +84 +296 + + +84 +93 +270 + + +93 +106 282 -83 -92 -276 +106 +122 +271 -92 -104 -270 +122 +150 +268 -104 -120 -276 - - -120 -145 -270 - - -145 +150 330 -187 +153 @@ -10181,17 +10176,17 @@ 1 3 -300 +296 3 7 -312 +316 7 17 -274 +275 17 @@ -10201,17 +10196,17 @@ 35 59 -278 +277 59 89 -275 +277 89 139 -271 +273 139 @@ -10230,18 +10225,18 @@ 547 -971 -267 +973 +269 -972 -2152 -267 +975 +2167 +268 -2152 +2170 143560 -242 +239 @@ -10257,7 +10252,7 @@ 1 3 -278 +279 3 @@ -10267,57 +10262,57 @@ 7 19 -278 +281 19 -41 -268 +42 +275 -41 +42 60 -279 +272 60 -72 -267 +73 +294 -72 -83 -280 +73 +84 +277 -83 -94 -283 +84 +95 +291 -94 -105 -292 - - -105 -119 -278 - - -119 -136 +95 +106 279 -136 -162 -269 +106 +120 +282 -162 +120 +138 +275 + + +138 +166 +270 + + +166 416 -210 +190 @@ -10667,22 +10662,22 @@ 16130 -46279 +46280 29 -48722 -86671 +48729 +86681 29 -87010 -224371 +87033 +224378 29 -237409 -710014 +237411 +710028 6 @@ -10743,17 +10738,17 @@ 1424 -2061 +2063 29 -2064 -2425 +2066 +2429 29 -2427 -2796 +2429 +2797 22 @@ -11336,18 +11331,18 @@ 35 -20304 -51564 +20305 +51570 35 -54934 +54937 117747 35 -117846 -185890 +117863 +185908 35 @@ -11408,12 +11403,12 @@ 1983 -2458 +2459 35 -2468 -2637 +2470 +2640 32 @@ -11469,7 +11464,7 @@ 2070 -5989 +5990 35 @@ -11616,7 +11611,7 @@ 2067 -5989 +5990 35 @@ -11647,23 +11642,23 @@ numlines -544741 +523603 element_id -537168 +516324 num_lines -10272 +9873 num_code -7938 +7630 num_comment -4364 +4194 @@ -11677,12 +11672,12 @@ 1 2 -529679 +509126 2 7 -7488 +7197 @@ -11698,12 +11693,12 @@ 1 2 -529740 +509184 2 7 -7427 +7139 @@ -11719,12 +11714,12 @@ 1 2 -537083 +516242 2 3 -85 +81 @@ -11740,393 +11735,41 @@ 1 2 -4655 +4475 2 3 -1325 +1273 3 4 -765 +736 4 6 -838 +806 6 12 -814 +782 12 24 -778 +747 24 118 -778 +747 118 7658 -316 - - - - - - -num_lines -num_code - - -12 - - -1 -2 -4728 - - -2 -3 -1337 - - -3 -4 -802 - - -4 -6 -850 - - -6 -11 -923 - - -11 -18 -790 - - -18 -29 -790 - - -29 -32 -48 - - - - - - -num_lines -num_comment - - -12 - - -1 -2 -4716 - - -2 -3 -1337 - - -3 -4 -826 - - -4 -6 -838 - - -6 -10 -802 - - -10 -16 -899 - - -16 -26 -814 - - -26 -27 -36 - - - - - - -num_code -element_id - - -12 - - -1 -2 -3184 - - -2 -3 -1239 - - -3 -4 -632 - - -4 -6 -607 - - -6 -10 -619 - - -10 -21 -619 - - -21 -67 -595 - - -68 -7861 -437 - - - - - - -num_code -num_lines - - -12 - - -1 -2 -3209 - - -2 -3 -1264 - - -3 -4 -644 - - -4 -6 -607 - - -6 -10 -692 - - -10 -21 -644 - - -21 -34 -607 - - -34 -42 -267 - - - - - - -num_code -num_comment - - -12 - - -1 -2 -3233 - - -2 -3 -1227 - - -3 -4 -680 - - -4 -6 -619 - - -6 -10 -680 - - -10 -19 -668 - - -19 -28 -595 - - -28 -33 -230 - - - - - - -num_comment -element_id - - -12 - - -1 -2 -2030 - - -2 -3 -559 - - -3 -4 -328 - - -4 -7 -340 - - -7 -14 -340 - - -14 -38 -328 - - -39 -280 -328 - - -283 -35679 -109 - - - - - - -num_comment -num_lines - - -12 - - -1 -2 -2042 - - -2 -3 -571 - - -3 -5 -389 - - -5 -8 -364 - - -8 -18 -364 - - -18 -58 -328 - - -61 -118 303 @@ -12134,6 +11777,358 @@ +num_lines +num_code + + +12 + + +1 +2 +4545 + + +2 +3 +1285 + + +3 +4 +771 + + +4 +6 +817 + + +6 +11 +888 + + +11 +18 +759 + + +18 +29 +759 + + +29 +32 +46 + + + + + + +num_lines +num_comment + + +12 + + +1 +2 +4533 + + +2 +3 +1285 + + +3 +4 +794 + + +4 +6 +806 + + +6 +10 +771 + + +10 +16 +864 + + +16 +26 +782 + + +26 +27 +35 + + + + + + +num_code +element_id + + +12 + + +1 +2 +3061 + + +2 +3 +1191 + + +3 +4 +607 + + +4 +6 +584 + + +6 +10 +595 + + +10 +21 +595 + + +21 +67 +572 + + +68 +7861 +420 + + + + + + +num_code +num_lines + + +12 + + +1 +2 +3084 + + +2 +3 +1215 + + +3 +4 +619 + + +4 +6 +584 + + +6 +10 +666 + + +10 +21 +619 + + +21 +34 +584 + + +34 +42 +257 + + + + + + +num_code +num_comment + + +12 + + +1 +2 +3108 + + +2 +3 +1180 + + +3 +4 +654 + + +4 +6 +595 + + +6 +10 +654 + + +10 +19 +642 + + +19 +28 +572 + + +28 +33 +222 + + + + + + +num_comment +element_id + + +12 + + +1 +2 +1951 + + +2 +3 +537 + + +3 +4 +315 + + +4 +7 +327 + + +7 +14 +327 + + +14 +38 +315 + + +39 +280 +315 + + +283 +35679 +105 + + + + + + +num_comment +num_lines + + +12 + + +1 +2 +1963 + + +2 +3 +549 + + +3 +5 +373 + + +5 +8 +350 + + +8 +18 +350 + + +18 +58 +315 + + +61 +118 +292 + + + + + + num_comment num_code @@ -12143,37 +12138,37 @@ 1 2 -2042 +1963 2 3 -571 +549 3 5 -389 +373 5 8 -364 +350 8 17 -340 +327 17 52 -328 +315 56 108 -328 +315 @@ -12183,31 +12178,31 @@ diagnostics -76160 +73204 id -76160 +73204 severity -36 +35 error_tag -97 +93 error_message -121 +116 full_error_message -65948 +63389 location -145 +140 @@ -12221,7 +12216,7 @@ 1 2 -76160 +73204 @@ -12237,7 +12232,7 @@ 1 2 -76160 +73204 @@ -12253,7 +12248,7 @@ 1 2 -76160 +73204 @@ -12269,7 +12264,7 @@ 1 2 -76160 +73204 @@ -12285,7 +12280,7 @@ 1 2 -76160 +73204 @@ -12301,17 +12296,17 @@ 1 2 -12 +11 2 3 -12 +11 6262 6263 -12 +11 @@ -12327,12 +12322,12 @@ 1 2 -24 +23 6 7 -12 +11 @@ -12348,12 +12343,12 @@ 1 2 -24 +23 8 9 -12 +11 @@ -12369,17 +12364,17 @@ 1 2 -12 +11 2 3 -12 +11 5422 5423 -12 +11 @@ -12395,17 +12390,17 @@ 1 2 -12 +11 2 3 -12 +11 9 10 -12 +11 @@ -12421,32 +12416,32 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12462,7 +12457,7 @@ 1 2 -97 +93 @@ -12478,12 +12473,12 @@ 1 2 -85 +81 3 4 -12 +11 @@ -12499,27 +12494,27 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 4996 4997 -12 +11 @@ -12535,17 +12530,17 @@ 1 2 -60 +58 2 3 -24 +23 5 6 -12 +11 @@ -12561,42 +12556,42 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12612,7 +12607,7 @@ 1 2 -121 +116 @@ -12628,7 +12623,7 @@ 1 2 -121 +116 @@ -12644,37 +12639,37 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 4996 4997 -12 +11 @@ -12690,17 +12685,17 @@ 1 2 -85 +81 2 3 -24 +23 5 6 -12 +11 @@ -12716,12 +12711,12 @@ 1 2 -65936 +63377 841 842 -12 +11 @@ -12737,7 +12732,7 @@ 1 2 -65948 +63389 @@ -12753,7 +12748,7 @@ 1 2 -65948 +63389 @@ -12769,7 +12764,7 @@ 1 2 -65948 +63389 @@ -12785,7 +12780,7 @@ 1 2 -65948 +63389 @@ -12801,12 +12796,12 @@ 1 2 -133 +128 6254 6255 -12 +11 @@ -12822,7 +12817,7 @@ 1 2 -145 +140 @@ -12838,12 +12833,12 @@ 1 2 -133 +128 3 4 -12 +11 @@ -12859,12 +12854,12 @@ 1 2 -133 +128 5 6 -12 +11 @@ -12880,12 +12875,12 @@ 1 2 -133 +128 5414 5415 -12 +11 @@ -12895,27 +12890,27 @@ files -66167 +63599 id -66167 +63599 name -66167 +63599 simple -45148 +43397 ext -109 +105 fromSource -12 +11 @@ -12929,7 +12924,7 @@ 1 2 -66167 +63599 @@ -12945,7 +12940,7 @@ 1 2 -66167 +63599 @@ -12961,7 +12956,7 @@ 1 2 -66167 +63599 @@ -12977,7 +12972,7 @@ 1 2 -66167 +63599 @@ -12993,7 +12988,7 @@ 1 2 -66167 +63599 @@ -13009,7 +13004,7 @@ 1 2 -66167 +63599 @@ -13025,7 +13020,7 @@ 1 2 -66167 +63599 @@ -13041,7 +13036,7 @@ 1 2 -66167 +63599 @@ -13057,22 +13052,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13088,22 +13083,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13119,17 +13114,17 @@ 1 2 -40322 +38758 2 3 -4193 +4031 3 6 -632 +607 @@ -13145,7 +13140,7 @@ 1 2 -45148 +43397 @@ -13161,47 +13156,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13217,47 +13212,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13273,47 +13268,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 75 76 -12 +11 112 113 -12 +11 428 429 -12 +11 658 659 -12 +11 2838 2839 -12 +11 @@ -13329,7 +13324,7 @@ 1 2 -109 +105 @@ -13345,7 +13340,7 @@ 5443 5444 -12 +11 @@ -13361,7 +13356,7 @@ 5443 5444 -12 +11 @@ -13377,7 +13372,7 @@ 3714 3715 -12 +11 @@ -13393,7 +13388,7 @@ 9 10 -12 +11 @@ -13403,19 +13398,19 @@ folders -12107 +11637 id -12107 +11637 name -12107 +11637 simple -3476 +3341 @@ -13429,7 +13424,7 @@ 1 2 -12107 +11637 @@ -13445,7 +13440,7 @@ 1 2 -12107 +11637 @@ -13461,7 +13456,7 @@ 1 2 -12107 +11637 @@ -13477,7 +13472,7 @@ 1 2 -12107 +11637 @@ -13493,27 +13488,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13529,27 +13524,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13559,15 +13554,15 @@ containerparent -78250 +75214 parent -12107 +11637 child -78250 +75214 @@ -13581,42 +13576,42 @@ 1 2 -5506 +5293 2 3 -1568 +1507 3 4 -668 +642 4 6 -1118 +1074 6 10 -899 +864 10 14 -960 +923 14 30 -923 +888 30 153 -461 +444 @@ -13632,7 +13627,7 @@ 1 2 -78250 +75214 @@ -13642,23 +13637,23 @@ fileannotations -5688625 +5467887 id -5348 +5141 kind -24 +23 name -60186 +57851 value -49318 +47404 @@ -13672,12 +13667,12 @@ 1 2 -145 +140 2 3 -5202 +5001 @@ -13693,62 +13688,62 @@ 1 96 -401 +385 96 219 -401 +385 221 285 -401 +385 285 444 -401 +385 445 521 -401 +385 526 619 -425 +408 619 708 -401 +385 708 895 -401 +385 896 928 -97 +93 930 931 -1531 +1472 1076 1667 -401 +385 1689 2272 -85 +81 @@ -13764,57 +13759,57 @@ 1 108 -401 +385 108 269 -401 +385 269 356 -401 +385 371 630 -401 +385 630 729 -401 +385 733 948 -401 +385 948 1062 -401 +385 1079 1494 -279 +268 1495 1496 -1531 +1472 1496 1865 -401 +385 1963 4058 -328 +315 @@ -13830,12 +13825,12 @@ 428 429 -12 +11 440 441 -12 +11 @@ -13851,12 +13846,12 @@ 2 3 -12 +11 4949 4950 -12 +11 @@ -13872,12 +13867,12 @@ 1 2 -12 +11 4057 4058 -12 +11 @@ -13893,62 +13888,62 @@ 1 2 -9871 +9487 2 3 -6491 +6239 3 6 -4996 +4802 6 8 -4935 +4743 8 14 -4850 +4662 14 18 -4424 +4253 18 21 -4619 +4440 21 34 -4862 +4673 34 128 -4813 +4627 129 236 -4595 +4416 236 395 -4558 +4381 395 440 -1167 +1121 @@ -13964,7 +13959,7 @@ 1 2 -60186 +57851 @@ -13980,62 +13975,62 @@ 1 2 -11038 +10609 2 3 -8728 +8389 3 4 -2808 +2699 4 6 -4352 +4183 6 10 -5470 +5258 10 14 -3586 +3446 14 17 -4643 +4463 17 22 -4643 +4463 22 40 -4558 +4381 40 83 -4582 +4405 83 163 -4534 +4358 164 1933 -1239 +1191 @@ -14051,67 +14046,67 @@ 1 2 -7524 +7232 2 5 -2419 +2325 5 8 -3573 +3435 8 21 -3804 +3657 21 23 -2735 +2629 23 25 -4461 +4288 25 40 -3586 +3446 40 195 -3890 +3739 195 207 -3902 +3750 207 273 -4048 +3891 273 327 -3744 +3598 328 407 -4315 +4148 407 441 -1312 +1261 @@ -14127,12 +14122,12 @@ 1 2 -49306 +47393 2 3 -12 +11 @@ -14148,67 +14143,67 @@ 1 2 -7549 +7256 2 5 -2795 +2687 5 8 -3610 +3470 8 16 -4060 +3902 16 18 -3343 +3213 18 21 -4072 +3914 21 31 -4461 +4288 31 42 -4023 +3867 42 54 -3768 +3622 54 81 -3780 +3633 81 109 -3829 +3680 109 133 -3756 +3610 133 149 -267 +257 @@ -14218,15 +14213,15 @@ inmacroexpansion -57126596 +57160160 id -15544516 +15553649 inv -2493763 +2495229 @@ -14240,42 +14235,42 @@ 1 2 -3895411 +3897700 2 3 -2466113 +2467562 3 4 -2018102 +2019287 4 5 -1769908 +1770948 5 6 -1845270 +1846354 6 7 -884925 +885445 7 8 -1535759 +1536661 8 6265 -1129025 +1129688 @@ -14291,52 +14286,52 @@ 1 2 -651228 +651611 2 3 -350884 +351091 3 4 -145822 +145908 4 5 -276335 +276498 5 8 -230677 +230812 8 11 -202111 +202230 11 19 -210471 +210594 19 34 -192538 +192651 34 167 -188020 +188130 167 153127 -45673 +45699 @@ -14346,15 +14341,15 @@ affectedbymacroexpansion -35527526 +35548400 id -4083475 +4085874 inv -3282712 +3284641 @@ -14368,42 +14363,42 @@ 1 2 -1341531 +1342319 2 3 -719304 +719727 3 4 -682963 +683364 4 6 -320945 +321133 6 10 -313534 +313718 10 24 -308059 +308240 24 64 -309945 +310127 64 9803 -87190 +87242 @@ -14419,72 +14414,72 @@ 1 2 -253184 +253333 2 3 -209979 +210102 3 4 -202347 +202466 4 5 -258125 +258276 5 6 -301422 +301599 6 7 -247881 +248027 7 8 -231148 +231284 8 9 -228002 +228136 9 10 -182499 +182606 10 12 -285679 +285847 12 16 -297410 +297584 16 23 -275398 +275560 23 60 -248963 +249109 60 526 -60669 +60704 @@ -14494,23 +14489,23 @@ macroinvocations -40814994 +39320374 id -40814994 +39320374 macro_id -89374 +85906 location -836970 +804492 kind -24 +23 @@ -14524,7 +14519,7 @@ 1 2 -40814994 +39320374 @@ -14540,7 +14535,7 @@ 1 2 -40814994 +39320374 @@ -14556,7 +14551,7 @@ 1 2 -40814994 +39320374 @@ -14572,52 +14567,52 @@ 1 2 -19267 +18286 2 3 -16946 +16475 3 4 -3744 +3598 4 6 -7925 +7630 6 11 -7658 +7326 11 21 -7160 +6823 21 41 -6758 +6555 41 -104 -6710 +107 +6485 -104 -454 -6710 +107 +450 +6449 -454 -201153 -6491 +453 +201240 +6274 @@ -14633,37 +14628,37 @@ 1 2 -47483 +45640 2 3 -11803 +11345 3 4 -5895 +5667 4 6 -7682 +7384 6 13 -7403 +7115 13 65 -6734 +6473 65 3614 -2370 +2278 @@ -14679,12 +14674,12 @@ 1 2 -82566 +79362 2 3 -6807 +6543 @@ -14700,42 +14695,42 @@ 1 2 -314219 +299713 2 3 -186394 +180341 3 4 -44431 +42999 4 5 -58533 +56378 5 8 -67687 +65247 8 16 -64113 +61777 16 46 -64830 +62536 46 -262302 -36761 +262546 +35498 @@ -14751,12 +14746,12 @@ 1 2 -783044 +752659 2 353 -53925 +51833 @@ -14772,7 +14767,7 @@ 1 2 -836970 +804492 @@ -14788,12 +14783,12 @@ 37566 37567 -12 +11 -3319916 -3319917 -12 +3327545 +3327546 +11 @@ -14809,12 +14804,12 @@ 2199 2200 -12 +11 5713 5714 -12 +11 @@ -14830,12 +14825,12 @@ 6537 6538 -12 +11 62313 62314 -12 +11 @@ -14845,15 +14840,15 @@ macroparent -35822215 +34476404 id -35822215 +34476404 parent_id -27895299 +26856682 @@ -14867,7 +14862,7 @@ 1 2 -35822215 +34476404 @@ -14883,17 +14878,17 @@ 1 2 -21477676 +20687700 2 3 -5474478 +5262423 3 88 -943144 +906558 @@ -14903,15 +14898,15 @@ macrolocationbind -4016679 +4019039 id -2801506 +2803152 location -2004363 +2005541 @@ -14925,22 +14920,22 @@ 1 2 -2200726 +2202019 2 3 -339324 +339524 3 7 -231800 +231936 7 57 -29655 +29673 @@ -14956,22 +14951,22 @@ 1 2 -1602305 +1603246 2 3 -171008 +171108 3 8 -155504 +155595 8 723 -75546 +75590 @@ -14981,19 +14976,19 @@ macro_argument_unexpanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -345935 +332512 @@ -15007,22 +15002,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15038,22 +15033,22 @@ 1 2 -8880284 +8550795 2 3 -13152746 +12678071 3 4 -6885304 +6640869 4 67 -2213625 +2138677 @@ -15069,17 +15064,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15095,17 +15090,17 @@ 2 3 -705 +677 13 1002 -60 +58 6617 19688 -36 +35 @@ -15121,62 +15116,62 @@ 1 2 -42535 +39868 2 3 -69291 +64826 3 4 -15621 +15435 4 5 -46376 +44296 5 8 -26513 +26980 8 12 -15560 +15447 12 16 -24531 +23275 16 22 -26403 +25414 22 -42 -26257 +41 +25075 -42 -113 -25978 +41 +101 +24970 -113 -51881 -25953 +101 +4363 +24958 -51881 -580841 -911 +4608 +581891 +1963 @@ -15192,17 +15187,17 @@ 1 2 -250082 +240378 2 3 -84450 +81173 3 9 -11402 +10960 @@ -15212,19 +15207,19 @@ macro_argument_expanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -209491 +201362 @@ -15238,22 +15233,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15269,22 +15264,22 @@ 1 2 -12795323 +12315365 2 3 -11169279 +10770085 3 4 -5961987 +5753415 4 9 -1205370 +1169546 @@ -15300,17 +15295,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15326,17 +15321,17 @@ 1 2 -692 +666 2 75 -60 +58 867 13964 -48 +46 @@ -15352,62 +15347,57 @@ 1 2 -25820 +23871 2 3 -42583 +40791 3 4 -6758 +6636 4 -5 -15791 - - -5 6 -3367 +18450 6 7 -24555 +23743 7 9 -16702 +16475 9 15 -19146 +17597 15 31 -15851 +15984 31 -87 -15912 +86 +15108 -87 -393 -15742 +86 +365 +15225 -396 -1164221 -7257 +365 +1165688 +7478 @@ -15423,22 +15413,22 @@ 1 2 -105651 +101551 2 3 -87976 +84562 3 6 -15779 +15166 6 66 -85 +81 @@ -15448,19 +15438,19 @@ functions -3565918 +3552236 id -3565918 +3552236 name -315848 +303954 kind -85 +81 @@ -15474,7 +15464,7 @@ 1 2 -3565918 +3552236 @@ -15490,7 +15480,7 @@ 1 2 -3565918 +3552236 @@ -15506,27 +15496,27 @@ 1 2 -214682 +206387 2 3 -31266 +29924 3 5 -28360 +27435 5 13 -23826 +23100 13 -109484 -17711 +118759 +17106 @@ -15542,12 +15532,12 @@ 1 2 -314231 +302400 2 3 -1616 +1554 @@ -15563,37 +15553,37 @@ 32 33 -12 +11 -477 -478 -12 +478 +479 +11 2735 2736 -12 +11 -5928 -5929 -12 +6052 +6053 +11 -43779 -43780 -12 +43879 +43880 +11 -108979 -108980 -12 +109948 +109949 +11 -131406 -131407 -12 +140883 +140884 +11 @@ -15609,37 +15599,37 @@ 11 12 -12 +11 42 43 -12 +11 -228 -229 -12 +229 +230 +11 -1485 -1486 -12 +1494 +1495 +11 2735 2736 -12 +11 -2858 -2859 -12 +2879 +2880 +11 18756 18757 -12 +11 @@ -15649,15 +15639,15 @@ function_entry_point -1068501 +1030977 id -1065255 +1027857 entry_point -1068501 +1030977 @@ -15671,12 +15661,12 @@ 1 2 -1062313 +1025030 2 9 -2941 +2827 @@ -15692,7 +15682,7 @@ 1 2 -1068501 +1030977 @@ -15702,15 +15692,15 @@ function_return_type -3577065 +3562951 id -3565347 +3551686 return_type -1033588 +1048715 @@ -15724,12 +15714,12 @@ 1 2 -3554126 +3540901 2 6 -11220 +10784 @@ -15745,17 +15735,17 @@ 1 2 -319945 +309177 2 3 -649566 +677865 3 -81742 -64076 +82133 +61671 @@ -15765,60 +15755,60 @@ purefunctions -21018 +20805 id -21018 +20805 function_deleted -51251 +49379 id -51251 +49379 function_defaulted -9554 +9184 id -9554 +9184 fun_decls -3668324 +3646017 id -3657006 +3635139 function -3484737 +3469555 type_id -1026294 +1041634 name -281968 +271389 location -875943 +843835 @@ -15832,7 +15822,7 @@ 1 2 -3657006 +3635139 @@ -15848,12 +15838,12 @@ 1 2 -3646053 +3624611 2 6 -10952 +10527 @@ -15869,7 +15859,7 @@ 1 2 -3657006 +3635139 @@ -15885,7 +15875,7 @@ 1 2 -3657006 +3635139 @@ -15901,12 +15891,12 @@ 1 2 -3343699 +3333988 2 9 -141038 +135566 @@ -15922,12 +15912,12 @@ 1 2 -3466345 +3451876 2 6 -18392 +17678 @@ -15943,7 +15933,7 @@ 1 2 -3484737 +3469555 @@ -15959,12 +15949,12 @@ 1 2 -3389832 +3378332 2 9 -94905 +91222 @@ -15980,17 +15970,17 @@ 1 2 -305953 +295716 2 3 -648059 +676381 3 -87017 -72282 +87408 +69535 @@ -16006,17 +15996,17 @@ 1 2 -318972 +308231 2 3 -644096 +672572 3 -80918 -63225 +81309 +60830 @@ -16032,12 +16022,12 @@ 1 2 -956638 +974669 2 -7429 -69656 +7459 +66965 @@ -16053,17 +16043,17 @@ 1 2 -921129 +940538 2 5 -81642 +78474 5 -22296 -23522 +22349 +22621 @@ -16079,32 +16069,32 @@ 1 2 -169351 +162826 2 3 -32554 +31420 3 4 -18866 +17994 4 7 -25650 +24841 7 19 -21261 +20518 19 -109747 -14283 +119022 +13787 @@ -16120,32 +16110,32 @@ 1 2 -181155 +174172 2 3 -31412 +30099 3 4 -16654 +16171 4 7 -22623 +21862 7 -26 -21383 +25 +20366 -26 -109468 -8740 +25 +118743 +8716 @@ -16161,17 +16151,17 @@ 1 2 -246046 +236860 2 5 -23170 +22271 5 -56245 -12752 +60936 +12257 @@ -16187,27 +16177,27 @@ 1 2 -180486 +173599 2 3 -47823 +46213 3 4 -18040 +17340 4 8 -22696 +21815 8 -8793 -12922 +8910 +12420 @@ -16223,27 +16213,27 @@ 1 2 -589769 +567012 2 3 -147895 +142319 3 5 -69790 +67350 5 -179 -65766 +141 +63307 -179 -3027 -2723 +142 +3039 +3844 @@ -16259,22 +16249,22 @@ 1 2 -602727 +579468 2 3 -164743 +158514 3 9 -69753 +67747 9 -3027 -38718 +3039 +38103 @@ -16290,17 +16280,17 @@ 1 2 -773854 +744445 2 4 -68209 +65890 4 -1514 -33879 +1520 +33500 @@ -16316,12 +16306,12 @@ 1 2 -848299 +817018 2 134 -27643 +26816 @@ -16331,22 +16321,22 @@ fun_def -1296860 +1250592 id -1296860 +1250592 fun_specialized -6505 +6439 id -6505 +6439 @@ -16364,11 +16354,11 @@ fun_decl_specifiers -512313 +512614 id -274687 +274848 name @@ -16386,17 +16376,17 @@ 1 2 -72048 +72090 2 3 -167651 +167750 3 4 -34987 +35007 @@ -16583,26 +16573,26 @@ fun_decl_empty_throws -1416734 +1471304 fun_decl -1416734 +1471304 fun_decl_noexcept -16569 +15937 fun_decl -15693 +15096 constant -16435 +15809 @@ -16616,12 +16606,12 @@ 1 2 -14818 +14255 2 3 -875 +841 @@ -16637,12 +16627,12 @@ 1 2 -16301 +15680 2 3 -133 +128 @@ -16652,26 +16642,26 @@ fun_decl_empty_noexcept -364559 +350681 fun_decl -364559 +350681 fun_decl_typedef_type -194 +186 fun_decl -194 +186 typedeftype_id -97 +93 @@ -16685,7 +16675,7 @@ 1 2 -194 +186 @@ -16701,7 +16691,7 @@ 2 3 -97 +93 @@ -16711,19 +16701,19 @@ param_decl_bind -4830661 +4766932 id -4830661 +4766932 index -389 +373 fun_decl -3158896 +3153051 @@ -16737,7 +16727,7 @@ 1 2 -4830661 +4766932 @@ -16753,7 +16743,7 @@ 1 2 -4830661 +4766932 @@ -16769,57 +16759,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16835,57 +16825,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16901,22 +16891,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16932,22 +16922,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16957,27 +16947,27 @@ var_decls -5602108 +5518014 id -5579181 +5495954 variable -5340611 +5266618 type_id -2038268 +2068405 name -139592 +134175 location -1358468 +1305755 @@ -16991,7 +16981,7 @@ 1 2 -5579181 +5495954 @@ -17007,12 +16997,12 @@ 1 2 -5556716 +5474337 2 7 -22465 +21616 @@ -17028,7 +17018,7 @@ 1 2 -5579181 +5495954 @@ -17044,12 +17034,12 @@ 1 2 -5579132 +5495907 2 3 -48 +46 @@ -17065,12 +17055,12 @@ 1 2 -5146145 +5079674 2 9 -194466 +186943 @@ -17086,12 +17076,12 @@ 1 2 -5290709 +5218605 2 7 -49902 +48012 @@ -17107,12 +17097,12 @@ 1 2 -5321866 +5248600 2 3 -18745 +18017 @@ -17128,12 +17118,12 @@ 1 2 -5225490 +5155963 2 9 -115121 +110654 @@ -17149,22 +17139,22 @@ 1 2 -1580700 +1627085 2 3 -244952 +236522 3 -9 -154629 +10 +155430 -9 -5708 -57986 +10 +5721 +49367 @@ -17180,22 +17170,22 @@ 1 2 -1607080 +1652441 2 3 -234777 +226741 3 -11 -155359 +13 +156353 -11 -5254 -41052 +13 +5267 +32869 @@ -17211,17 +17201,17 @@ 1 2 -1850925 +1888086 2 5 -162458 +156341 5 770 -24884 +23977 @@ -17237,17 +17227,17 @@ 1 2 -1771751 +1811867 2 4 -165132 +159052 4 3604 -101384 +97485 @@ -17263,42 +17253,42 @@ 1 2 -58861 +56530 2 3 -20860 +20039 3 4 -12290 +11801 4 6 -12715 +12268 6 10 -11524 +11088 10 22 -10673 +10270 22 255 -10490 +10083 263 -149390 -2176 +159500 +2091 @@ -17314,37 +17304,37 @@ 1 2 -62277 +59814 2 3 -20118 +19314 3 4 -13359 +12841 4 6 -11949 +11532 6 11 -11499 +11077 11 28 -10515 +10095 28 -148426 -9871 +158536 +9499 @@ -17360,32 +17350,32 @@ 1 2 -84973 +81606 2 3 -18149 +17445 3 4 -9676 +9347 4 7 -11706 +11275 7 28 -10576 +10165 28 -111448 -4510 +120730 +4335 @@ -17401,32 +17391,32 @@ 1 2 -80329 +77212 2 3 -21273 +20448 3 4 -7780 +7478 4 7 -12423 +11941 7 21 -10563 +10154 21 9993 -7220 +6940 @@ -17442,22 +17432,22 @@ 1 2 -1008108 +967927 2 3 -144734 +139422 3 6 -124044 +119546 6 -114124 -81581 +123459 +78860 @@ -17473,22 +17463,22 @@ 1 2 -1060320 +1018112 2 3 -107961 +103970 3 6 -111863 +107943 6 -113877 -78323 +123212 +75728 @@ -17504,17 +17494,17 @@ 1 2 -1166129 +1119863 2 3 -93045 +89797 3 -104379 -99293 +113652 +96095 @@ -17530,12 +17520,12 @@ 1 2 -1348524 +1296197 2 52 -9943 +9558 @@ -17545,11 +17535,11 @@ var_def -2573394 +2477557 id -2573394 +2477557 @@ -17619,19 +17609,19 @@ type_decls -1469165 +1413769 id -1469165 +1413769 type_id -1433996 +1379965 location -1203571 +1156868 @@ -17645,7 +17635,7 @@ 1 2 -1469165 +1413769 @@ -17661,7 +17651,7 @@ 1 2 -1469165 +1413769 @@ -17677,12 +17667,12 @@ 1 2 -1408431 +1355392 2 24 -25564 +24572 @@ -17698,12 +17688,12 @@ 1 2 -1409866 +1356771 2 24 -24130 +23194 @@ -17719,12 +17709,12 @@ 1 2 -1142582 +1098234 2 469 -60988 +58633 @@ -17740,12 +17730,12 @@ 1 2 -1144223 +1099812 2 469 -59347 +57056 @@ -17755,45 +17745,45 @@ type_def -1035654 +995467 id -1035654 +995467 type_decl_top -297552 +286006 type_decl -297552 +286006 namespace_decls -151627 +145743 id -151627 +145743 namespace_id -8485 +8155 location -135422 +130167 bodylocation -135787 +130518 @@ -17807,7 +17797,7 @@ 1 2 -151627 +145743 @@ -17823,7 +17813,7 @@ 1 2 -151627 +145743 @@ -17839,7 +17829,7 @@ 1 2 -151627 +145743 @@ -17855,42 +17845,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17906,42 +17896,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17957,42 +17947,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3742 -158 +151 @@ -18008,12 +17998,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18029,12 +18019,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18050,12 +18040,12 @@ 1 2 -134595 +129373 2 3 -826 +794 @@ -18071,12 +18061,12 @@ 1 2 -126900 +121976 2 11 -8886 +8541 @@ -18092,12 +18082,12 @@ 1 2 -126900 +121976 2 9 -8886 +8541 @@ -18113,12 +18103,12 @@ 1 2 -135349 +130097 2 5 -437 +420 @@ -18128,19 +18118,19 @@ usings -320601 +308161 id -320601 +308161 element_id -49002 +47101 location -26464 +25437 @@ -18154,7 +18144,7 @@ 1 2 -320601 +308161 @@ -18170,7 +18160,7 @@ 1 2 -320601 +308161 @@ -18186,17 +18176,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18212,17 +18202,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18238,22 +18228,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18269,22 +18259,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18294,15 +18284,15 @@ using_container -485187 +466360 parent -8667 +8331 child -301029 +289348 @@ -18316,47 +18306,47 @@ 1 2 -3379 +3248 2 3 -559 +537 3 6 -668 +642 6 15 -656 +630 16 31 -705 +677 31 143 -291 +280 178 179 -1397 +1343 179 182 -765 +736 182 501 -243 +233 @@ -18372,22 +18362,22 @@ 1 2 -217478 +209039 2 3 -55773 +53609 3 6 -22659 +21780 6 47 -5117 +4919 @@ -18397,23 +18387,23 @@ static_asserts -132358 +131017 id -132358 +131017 condition -132358 +131017 message -30094 +29789 location -16938 +16766 @@ -18427,7 +18417,7 @@ 1 2 -132358 +131017 @@ -18443,7 +18433,7 @@ 1 2 -132358 +131017 @@ -18459,7 +18449,7 @@ 1 2 -132358 +131017 @@ -18475,7 +18465,7 @@ 1 2 -132358 +131017 @@ -18491,7 +18481,7 @@ 1 2 -132358 +131017 @@ -18507,7 +18497,7 @@ 1 2 -132358 +131017 @@ -18523,32 +18513,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18564,32 +18554,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18605,12 +18595,12 @@ 1 2 -27912 +27629 2 33 -2181 +2159 @@ -18626,32 +18616,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18661,12 +18651,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18682,32 +18672,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18717,12 +18707,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18738,22 +18728,22 @@ 1 2 -4475 +4429 2 3 -6063 +6002 3 4 -6208 +6145 4 7 -191 +189 @@ -18763,23 +18753,23 @@ params -4803552 +4749557 id -4779409 +4724692 function -3118318 +3117564 index -389 +373 type_id -1865866 +1906163 @@ -18793,12 +18783,12 @@ 1 2 -4778668 +4723979 2 69 -741 +712 @@ -18814,7 +18804,7 @@ 1 2 -4779409 +4724692 @@ -18830,12 +18820,12 @@ 1 2 -4757747 +4702211 2 7 -21662 +22481 @@ -18851,22 +18841,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18882,22 +18872,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18913,22 +18903,22 @@ 1 2 -2314438 +2335471 2 3 -493113 +480884 3 5 -270978 +262941 5 20 -39787 +38267 @@ -18944,57 +18934,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256345 -256346 -12 +266636 +266637 +11 @@ -19010,57 +19000,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256516 -256517 -12 +266807 +266808 +11 @@ -19076,57 +19066,57 @@ 1 2 -158 +151 3 7 -24 +23 8 20 -24 +23 36 40 -24 +23 42 45 -24 +23 61 105 -24 +23 173 257 -24 +23 406 661 -24 +23 1178 2710 -24 +23 -7491 -16702 -24 +7492 +16795 +23 -135733 -135734 -12 +145286 +145287 +11 @@ -19142,22 +19132,22 @@ 1 2 -1495095 +1547921 2 3 -199608 +193171 3 -13 -141671 +18 +144002 -13 -5275 -29491 +18 +5288 +21067 @@ -19173,22 +19163,22 @@ 1 2 -1517195 +1569164 2 3 -187245 +181276 3 -17 -140893 +25 +143324 -17 -4798 -20532 +25 +4811 +12397 @@ -19204,12 +19194,12 @@ 1 2 -1751170 +1795906 2 33 -114695 +110257 @@ -19219,15 +19209,15 @@ overrides -161127 +159494 new -126169 +124890 old -15666 +15507 @@ -19241,12 +19231,12 @@ 1 2 -91218 +90293 2 3 -34944 +34590 3 @@ -19267,37 +19257,37 @@ 1 2 -8232 +8148 2 3 -2043 +2022 3 4 -883 +874 4 5 -1278 +1265 5 10 -1245 +1233 10 43 -1179 +1167 44 218 -804 +795 @@ -19307,19 +19297,19 @@ membervariables -329658 +325582 id -325099 +321201 type_id -145086 +139772 name -59068 +56776 @@ -19333,12 +19323,12 @@ 1 2 -320637 +316912 2 7 -4461 +4288 @@ -19354,7 +19344,7 @@ 1 2 -325099 +321201 @@ -19370,22 +19360,22 @@ 1 2 -118391 +113949 2 3 -13396 +12934 3 11 -10989 +10656 11 -1212 -2309 +1715 +2231 @@ -19401,17 +19391,17 @@ 1 2 -125916 +121310 2 3 -9883 +9511 3 266 -9287 +8950 @@ -19427,32 +19417,32 @@ 1 2 -31217 +29971 2 3 -9056 +8705 3 4 -5944 +5725 4 6 -4485 +4311 6 15 -4534 +4358 15 -1317 -3829 +1953 +3704 @@ -19468,32 +19458,32 @@ 1 2 -38256 +36736 2 3 -7524 +7232 3 4 -4035 +3891 4 7 -4765 +4592 7 -319 -4437 +291 +4264 -323 +318 605 -48 +58 @@ -19674,19 +19664,19 @@ localvariables -527180 +521836 id -527101 +521758 type_id -48087 +47599 name -76217 +75444 @@ -19700,12 +19690,12 @@ 1 2 -527022 +521680 2 3 -79 +78 @@ -19721,7 +19711,7 @@ 1 2 -527101 +521758 @@ -19737,32 +19727,32 @@ 1 2 -26759 +26487 2 3 -6841 +6772 3 4 -2893 +2864 4 6 -4119 +4077 6 13 -3862 +3823 13 4908 -3611 +3575 @@ -19778,22 +19768,22 @@ 1 2 -36072 +35706 2 3 -4969 +4919 3 5 -4323 +4279 5 1158 -2722 +2694 @@ -19809,32 +19799,32 @@ 1 2 -43526 +43085 2 3 -13096 +12963 3 4 -5140 +5088 4 7 -6821 +6752 7 31 -5767 +5708 31 6112 -1865 +1846 @@ -19850,17 +19840,17 @@ 1 2 -64564 +63910 2 3 -6472 +6406 3 819 -5180 +5127 @@ -19870,11 +19860,11 @@ autoderivation -19759 +19559 var -19759 +19559 derivation_type @@ -19892,7 +19882,7 @@ 1 2 -19759 +19559 @@ -19938,31 +19928,31 @@ enumconstants -94487 +94097 id -94487 +94097 parent -7539 +8031 index -7678 +7600 type_id -7394 +7887 name -73851 +73102 location -76856 +76077 @@ -19976,7 +19966,7 @@ 1 2 -94487 +94097 @@ -19992,7 +19982,7 @@ 1 2 -94487 +94097 @@ -20008,7 +19998,7 @@ 1 2 -94487 +94097 @@ -20024,7 +20014,7 @@ 1 2 -94487 +94097 @@ -20040,7 +20030,7 @@ 1 2 -94487 +94097 @@ -20056,47 +20046,47 @@ 1 2 -1041 +1598 2 3 -830 +822 3 4 -2484 +2459 4 5 -586 +580 5 6 -586 +580 6 -8 -540 +9 +730 -8 -13 -659 +9 +16 +613 -13 -46 -573 +16 +392 +606 -46 +426 1166 -237 +39 @@ -20112,47 +20102,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 +9 +704 -8 -13 -632 +9 +17 +626 -13 -49 -566 - - -50 +17 1166 -224 +600 @@ -20168,12 +20153,12 @@ 1 2 -6788 +7287 2 3 -751 +743 @@ -20189,47 +20174,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 +9 +704 -8 -13 -632 +9 +17 +626 -13 -49 -566 - - -50 +17 1166 -224 +600 @@ -20245,47 +20225,47 @@ 1 2 -1080 +1637 2 3 -843 +835 3 4 -2484 +2459 4 5 -586 +580 5 6 -566 +561 6 -8 -514 +9 +704 -8 -13 -659 +9 +16 +613 -13 -46 -566 +16 +427 +606 -46 +466 1166 -237 +32 @@ -20301,47 +20281,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 30 -606 +600 30 -1166 -355 +1253 +352 @@ -20357,47 +20337,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 29 -606 +600 29 -1145 -355 +1232 +352 @@ -20413,47 +20393,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 28 -606 +600 28 -1123 -355 +1210 +352 @@ -20469,47 +20449,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 674 -355 +352 @@ -20525,47 +20505,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 774 -355 +352 @@ -20581,47 +20561,47 @@ 1 2 -1041 +1598 2 3 -810 +802 3 4 -2458 +2433 4 5 -566 +561 5 6 -566 +561 6 -8 -520 +9 +704 -8 -13 -639 +9 +16 +600 -13 -46 -560 +16 +470 +593 -46 +479 1166 -230 +32 @@ -20637,7 +20617,7 @@ 1 2 -7388 +7881 137 @@ -20658,47 +20638,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 +9 +678 -8 -13 -612 +9 +17 +613 -13 -51 -560 - - -52 +17 1166 -210 +580 @@ -20714,47 +20689,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 +9 +678 -8 -13 -612 +9 +17 +613 -13 -51 -560 - - -52 +17 1166 -210 +580 @@ -20770,47 +20740,47 @@ 1 2 -1080 +1637 2 3 -823 +815 3 4 -2458 +2433 4 5 -566 +561 5 6 -547 +541 6 -8 -494 +9 +678 -8 -13 -639 +9 +16 +600 -13 -47 -560 +16 +470 +593 -48 +621 1166 -224 +26 @@ -20826,17 +20796,17 @@ 1 2 -66396 +65723 2 3 -6927 +6856 3 239 -527 +521 @@ -20852,17 +20822,17 @@ 1 2 -67049 +66369 2 3 -6274 +6210 3 239 -527 +521 @@ -20878,12 +20848,12 @@ 1 2 -68762 +68065 2 13 -5088 +5036 @@ -20899,17 +20869,17 @@ 1 2 -61941 +61313 2 3 -11382 +11267 3 239 -527 +521 @@ -20925,12 +20895,12 @@ 1 2 -71346 +70623 2 23 -2504 +2479 @@ -20946,12 +20916,12 @@ 1 2 -71531 +70773 2 229 -5325 +5304 @@ -20967,12 +20937,12 @@ 1 2 -71643 +70884 2 229 -5213 +5193 @@ -20988,12 +20958,12 @@ 1 2 -73211 +72469 2 17 -3644 +3607 @@ -21009,17 +20979,17 @@ 1 2 -66535 +65828 2 3 -10090 +9994 3 229 -230 +254 @@ -21035,12 +21005,12 @@ 1 2 -76685 +75907 2 27 -171 +169 @@ -21050,31 +21020,31 @@ builtintypes -559 +537 id -559 +537 name -559 +537 kind -559 +537 size -85 +81 sign -36 +35 alignment -60 +58 @@ -21088,7 +21058,7 @@ 1 2 -559 +537 @@ -21104,7 +21074,7 @@ 1 2 -559 +537 @@ -21120,7 +21090,7 @@ 1 2 -559 +537 @@ -21136,7 +21106,7 @@ 1 2 -559 +537 @@ -21152,7 +21122,7 @@ 1 2 -559 +537 @@ -21168,7 +21138,7 @@ 1 2 -559 +537 @@ -21184,7 +21154,7 @@ 1 2 -559 +537 @@ -21200,7 +21170,7 @@ 1 2 -559 +537 @@ -21216,7 +21186,7 @@ 1 2 -559 +537 @@ -21232,7 +21202,7 @@ 1 2 -559 +537 @@ -21248,7 +21218,7 @@ 1 2 -559 +537 @@ -21264,7 +21234,7 @@ 1 2 -559 +537 @@ -21280,7 +21250,7 @@ 1 2 -559 +537 @@ -21296,7 +21266,7 @@ 1 2 -559 +537 @@ -21312,7 +21282,7 @@ 1 2 -559 +537 @@ -21328,37 +21298,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21374,37 +21344,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21420,37 +21390,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21466,12 +21436,12 @@ 1 2 -24 +23 3 4 -60 +58 @@ -21487,12 +21457,12 @@ 1 2 -60 +58 2 3 -24 +23 @@ -21508,17 +21478,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21534,17 +21504,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21560,17 +21530,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21586,12 +21556,12 @@ 5 6 -24 +23 7 8 -12 +11 @@ -21607,7 +21577,7 @@ 5 6 -36 +35 @@ -21623,27 +21593,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21659,27 +21629,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21695,27 +21665,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21731,12 +21701,12 @@ 1 2 -12 +11 2 3 -48 +46 @@ -21752,7 +21722,7 @@ 3 4 -60 +58 @@ -21762,23 +21732,23 @@ derivedtypes -4572495 +4651908 id -4572495 +4651908 name -2240442 +2328554 kind -97 +93 type_id -2743147 +2780308 @@ -21792,7 +21762,7 @@ 1 2 -4572495 +4651908 @@ -21808,7 +21778,7 @@ 1 2 -4572495 +4651908 @@ -21824,7 +21794,7 @@ 1 2 -4572495 +4651908 @@ -21840,17 +21810,17 @@ 1 2 -1640327 +1709696 2 3 -479376 +500222 3 -42612 -120737 +43371 +118634 @@ -21866,12 +21836,12 @@ 1 2 -2240417 +2328530 2 3 -24 +23 @@ -21887,17 +21857,17 @@ 1 2 -1640607 +1709965 2 3 -479097 +499954 3 -42594 -120737 +43353 +118634 @@ -21913,42 +21883,42 @@ 21 22 -12 +11 61 62 -12 +11 2051 2052 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97759 -97760 -12 +102765 +102766 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -21964,42 +21934,42 @@ 1 2 -12 +11 13 14 -12 +11 38 39 -12 +11 1152 1153 -12 +11 -13367 -13368 -12 +15027 +15028 +11 -36098 -36099 -12 +39331 +39332 +11 -50248 -50249 -12 +53789 +53790 +11 -83386 -83387 -12 +89933 +89934 +11 @@ -22015,42 +21985,42 @@ 12 13 -12 +11 21 22 -12 +11 969 970 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97431 -97432 -12 +102434 +102435 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -22066,22 +22036,22 @@ 1 2 -1661856 +1683160 2 3 -405550 +392781 3 4 -615674 +646083 4 202 -60064 +58283 @@ -22097,22 +22067,22 @@ 1 2 -1663206 +1684457 2 3 -405380 +392618 3 4 -614495 +644949 4 198 -60064 +58283 @@ -22128,22 +22098,22 @@ 1 2 -1663534 +1684784 2 3 -406814 +393985 3 4 -614446 +644902 4 7 -58350 +56635 @@ -22153,19 +22123,19 @@ pointerishsize -3358396 +3426426 id -3358396 +3426426 size -24 +23 alignment -12 +11 @@ -22179,7 +22149,7 @@ 1 2 -3358396 +3426426 @@ -22195,7 +22165,7 @@ 1 2 -3358396 +3426426 @@ -22211,12 +22181,12 @@ 21 22 -12 +11 -276244 -276245 -12 +293219 +293220 +11 @@ -22232,7 +22202,7 @@ 1 2 -24 +23 @@ -22246,9 +22216,9 @@ 12 -276265 -276266 -12 +293240 +293241 +11 @@ -22264,7 +22234,7 @@ 2 3 -12 +11 @@ -22274,23 +22244,23 @@ arraysizes -18830 +18099 id -18830 +18099 num_elements -2394 +2301 bytesize -2783 +2675 alignment -85 +81 @@ -22304,7 +22274,7 @@ 1 2 -18830 +18099 @@ -22320,7 +22290,7 @@ 1 2 -18830 +18099 @@ -22336,7 +22306,7 @@ 1 2 -18830 +18099 @@ -22352,37 +22322,37 @@ 1 2 -182 +175 2 3 -1422 +1367 3 4 -85 +81 4 5 -182 +175 5 13 -182 +175 13 25 -182 +175 38 116 -158 +151 @@ -22398,27 +22368,27 @@ 1 2 -1762 +1694 2 3 -243 +233 3 4 -133 +128 4 6 -182 +175 6 11 -72 +70 @@ -22434,27 +22404,27 @@ 1 2 -1774 +1705 2 3 -255 +245 3 4 -158 +151 4 7 -182 +175 7 8 -24 +23 @@ -22470,42 +22440,42 @@ 1 2 -170 +163 2 3 -1556 +1495 3 4 -133 +128 4 6 -218 +210 6 9 -218 +210 9 17 -218 +210 17 53 -218 +210 55 75 -48 +46 @@ -22521,22 +22491,22 @@ 1 2 -2115 +2033 2 3 -389 +373 3 6 -243 +233 6 7 -36 +35 @@ -22552,22 +22522,22 @@ 1 2 -2176 +2091 2 3 -303 +292 3 5 -255 +245 5 7 -48 +46 @@ -22583,37 +22553,37 @@ 17 18 -12 +11 18 19 -12 +11 33 34 -12 +11 50 51 -12 +11 181 182 -12 +11 389 390 -12 +11 861 862 -12 +11 @@ -22629,37 +22599,37 @@ 4 5 -12 +11 5 6 -12 +11 13 14 -12 +11 16 17 -12 +11 39 40 -12 +11 40 41 -12 +11 190 191 -12 +11 @@ -22675,37 +22645,37 @@ 1 2 -12 +11 2 3 -12 +11 14 15 -12 +11 17 18 -12 +11 41 42 -12 +11 53 54 -12 +11 191 192 -12 +11 @@ -22715,15 +22685,15 @@ typedefbase -1919913 +1867884 id -1919913 +1867884 type_id -899600 +871937 @@ -22737,7 +22707,7 @@ 1 2 -1919913 +1867884 @@ -22753,22 +22723,22 @@ 1 2 -698168 +676919 2 3 -93312 +90264 3 6 -72975 +70856 6 -5423 -35144 +5485 +33897 @@ -22778,23 +22748,23 @@ decltypes -45841 +44063 id -45841 +44063 expr -43325 +41644 base_type -6479 +6227 parentheses_would_change_meaning -24 +23 @@ -22808,7 +22778,7 @@ 1 2 -45841 +44063 @@ -22824,7 +22794,7 @@ 1 2 -45841 +44063 @@ -22840,7 +22810,7 @@ 1 2 -45841 +44063 @@ -22856,12 +22826,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22877,12 +22847,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22898,7 +22868,7 @@ 1 2 -43325 +41644 @@ -22914,17 +22884,17 @@ 1 2 -3622 +3482 2 3 -2552 +2453 3 277 -303 +292 @@ -22940,22 +22910,22 @@ 1 2 -2540 +2442 2 3 -3282 +3154 3 12 -522 +502 13 2445 -133 +128 @@ -22971,7 +22941,7 @@ 1 2 -6479 +6227 @@ -22987,12 +22957,12 @@ 8 9 -12 +11 1082 1083 -12 +11 @@ -23008,12 +22978,12 @@ 8 9 -12 +11 3556 3557 -12 +11 @@ -23029,12 +22999,12 @@ 8 9 -12 +11 525 526 -12 +11 @@ -23044,19 +23014,19 @@ usertypes -4363319 +4337028 id -4363319 +4337028 name -899429 +917472 kind -133 +128 @@ -23070,7 +23040,7 @@ 1 2 -4363319 +4337028 @@ -23086,7 +23056,7 @@ 1 2 -4363319 +4337028 @@ -23102,22 +23072,22 @@ 1 2 -596127 +606962 2 3 -199888 +203676 3 8 -67589 +69886 8 -31201 -35824 +32070 +36947 @@ -23133,12 +23103,12 @@ 1 2 -842355 +861619 2 10 -57074 +55852 @@ -23154,57 +23124,57 @@ 23 24 -12 +11 372 373 -12 +11 773 774 -12 +11 -1526 -1527 -12 +1856 +1857 +11 -4123 -4124 -12 +4195 +4196 +11 14604 14605 -12 +11 -17528 -17529 -12 +17544 +17545 +11 -20287 -20288 -12 +20425 +20426 +11 -75247 -75248 -12 +75551 +75552 +11 -81118 -81119 -12 +90575 +90576 +11 -143330 -143331 -12 +145253 +145254 +11 @@ -23220,52 +23190,52 @@ 16 17 -12 +11 38 39 -24 +23 404 405 -12 +11 548 549 -12 +11 -776 -777 -12 +777 +778 +11 -2846 -2847 -12 +2848 +2849 +11 4545 4546 -12 +11 -9121 -9122 -12 +9129 +9130 +11 11659 11660 -12 +11 -49218 -49219 -12 +53824 +53825 +11 @@ -23275,19 +23245,19 @@ usertypesize -1364814 +1420908 id -1364814 +1420908 size -1641 +1577 alignment -97 +93 @@ -23301,7 +23271,7 @@ 1 2 -1364814 +1420908 @@ -23317,7 +23287,7 @@ 1 2 -1364814 +1420908 @@ -23333,52 +23303,52 @@ 1 2 -474 +455 2 3 -218 +210 3 4 -72 +70 4 5 -109 +105 5 8 -121 +116 8 12 -109 +105 12 16 -133 +128 16 36 -133 +128 37 170 -133 +128 260 -86086 -133 +95028 +128 @@ -23394,17 +23364,17 @@ 1 2 -1349 +1297 2 3 -194 +186 3 6 -97 +93 @@ -23420,42 +23390,42 @@ 1 2 -12 +11 3 4 -12 +11 7 8 -12 +11 50 51 -12 +11 54 55 -12 +11 -1916 -1917 -12 +2246 +2247 +11 -9656 -9657 -12 +9717 +9718 +11 -100584 -100585 -12 +109526 +109527 +11 @@ -23471,37 +23441,37 @@ 1 2 -24 +23 3 4 -12 +11 8 9 -12 +11 12 13 -12 +11 17 18 -12 +11 25 26 -12 +11 106 107 -12 +11 @@ -23511,26 +23481,26 @@ usertype_final -1331 +1317 id -1331 +1317 usertype_uuid -4897 +4847 id -4897 +4847 uuid -4897 +4847 @@ -23544,7 +23514,7 @@ 1 2 -4897 +4847 @@ -23560,7 +23530,7 @@ 1 2 -4897 +4847 @@ -23570,15 +23540,15 @@ mangled_name -4359684 +4333558 id -4359684 +4333558 mangled_name -532986 +514256 @@ -23592,7 +23562,7 @@ 1 2 -4359684 +4333558 @@ -23608,32 +23578,32 @@ 1 2 -325269 +310895 2 3 -68246 +66497 3 4 -35958 +35217 4 -8 -45307 +7 +39225 -8 -34 -40237 +7 +23 +38664 -34 -8470 -17967 +23 +8589 +23755 @@ -23643,59 +23613,59 @@ is_pod_class -1041477 +1104649 id -1041477 +1104649 is_standard_layout_class -1118962 +1180366 id -1118962 +1180366 is_complete -1345984 +1398952 id -1345984 +1398952 is_class_template -246617 +238660 id -246617 +238660 class_instantiation -1108921 +1176522 to -1107195 +1174863 from -72513 +72363 @@ -23709,12 +23679,12 @@ 1 2 -1105566 +1173297 2 4 -1628 +1565 @@ -23730,47 +23700,47 @@ 1 2 -21601 +21289 2 3 -12897 +12771 3 4 -7488 +7314 4 5 -4789 +4942 5 7 -5871 +5994 7 11 -6503 +6438 11 20 -5555 +5585 20 -89 -5470 +87 +5456 -89 -2079 -2334 +87 +3629 +2570 @@ -23780,19 +23750,19 @@ class_template_argument -2800063 +3135757 type_id -1339675 +1428725 index -1361 +1308 arg_type -921287 +904899 @@ -23806,27 +23776,27 @@ 1 2 -593732 +586000 2 3 -438105 +428957 3 4 -175599 +258501 4 7 -108629 +129501 7 113 -23607 +25764 @@ -23842,22 +23812,22 @@ 1 2 -619710 +613658 2 3 -445691 +442173 3 4 -187999 +272382 4 113 -86274 +100511 @@ -23873,37 +23843,37 @@ 1 2 -12 +11 2 3 -863 +829 3 26 -109 +105 29 64 -109 +105 69 -427 -109 +435 +105 -594 -8438 -109 +616 +9263 +105 -11951 -101100 -48 +13601 +119714 +46 @@ -23919,37 +23889,37 @@ 1 2 -12 +11 2 3 -863 +829 3 14 -121 +116 14 26 -109 +105 29 -147 -109 +148 +105 -191 -3560 -109 +198 +3591 +105 -11321 -39550 -36 +11582 +41130 +35 @@ -23965,22 +23935,27 @@ 1 2 -571096 +550198 2 3 -205784 +200100 3 -5 -75369 +4 +54918 -5 -5259 -69036 +4 +10 +70727 + + +10 +11421 +28954 @@ -23996,17 +23971,253 @@ 1 2 -805922 +786767 2 3 -96011 +98069 3 22 -19353 +20062 + + + + + + + + +class_template_argument_value +362635 + + +type_id +233565 + + +index +163 + + +arg_value +345447 + + + + +type_id +index + + +12 + + +1 +2 +209845 + + +2 +3 +14512 + + +3 +14 +9207 + + + + + + +type_id +arg_value + + +12 + + +1 +2 +197436 + + +2 +3 +17971 + + +3 +22 +17527 + + +24 +173 +630 + + + + + + +index +type_id + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +25 +26 +11 + + +206 +207 +11 + + +389 +390 +11 + + +552 +553 +11 + + +1312 +1313 +11 + + +5393 +5394 +11 + + +5423 +5424 +11 + + +9668 +9669 +11 + + + + + + +index +arg_value + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +42 +43 +11 + + +311 +312 +11 + + +514 +515 +11 + + +715 +716 +11 + + +1585 +1586 +11 + + +6302 +6303 +11 + + +8160 +8161 +11 + + +11875 +11876 +11 + + + + + + +arg_value +type_id + + +12 + + +1 +2 +328387 + + +2 +4 +17059 + + + + + + +arg_value +index + + +12 + + +1 +2 +345447 @@ -24016,15 +24227,15 @@ is_proxy_class_for -50120 +49017 id -50120 +49017 templ_param_id -50120 +49017 @@ -24038,7 +24249,7 @@ 1 2 -50120 +49017 @@ -24054,7 +24265,7 @@ 1 2 -50120 +49017 @@ -24064,19 +24275,19 @@ type_mentions -1699359 +1682135 id -1699359 +1682135 type_id -68077 +67387 location -1668455 +1651543 kind @@ -24094,7 +24305,7 @@ 1 2 -1699359 +1682135 @@ -24110,7 +24321,7 @@ 1 2 -1699359 +1682135 @@ -24126,7 +24337,7 @@ 1 2 -1699359 +1682135 @@ -24142,37 +24353,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24188,37 +24399,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24234,12 +24445,12 @@ 1 2 -66818 +66141 2 3 -1258 +1246 @@ -24255,12 +24466,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24276,12 +24487,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24297,7 +24508,7 @@ 1 2 -1668455 +1651543 @@ -24370,26 +24581,26 @@ is_function_template -1058083 +1023581 id -1058083 +1023581 function_instantiation -739463 +719194 to -739463 +719194 from -136103 +134923 @@ -24403,7 +24614,7 @@ 1 2 -739463 +719194 @@ -24419,37 +24630,32 @@ 1 2 -63018 +64125 2 3 -32396 +31385 3 4 -8193 +7898 4 -5 -9299 +6 +12467 -5 -10 -10940 +6 +15 +10434 -10 -57 -10223 - - -58 +15 645 -2030 +8611 @@ -24459,19 +24665,19 @@ function_template_argument -1910796 +1981225 function_id -1112422 +1088560 index -243 +233 arg_type -369847 +359386 @@ -24485,22 +24691,22 @@ 1 2 -634796 +600045 2 3 -361033 +302330 3 -5 -84645 +4 +131242 -5 +4 21 -31947 +54941 @@ -24516,22 +24722,22 @@ 1 2 -657966 +618530 2 3 -332393 +293520 3 -5 -90905 +4 +116683 -5 +4 21 -31156 +59825 @@ -24547,102 +24753,102 @@ 4 5 -12 +11 7 8 -12 +11 17 18 -12 +11 39 40 -12 +11 65 66 -12 +11 152 153 -12 +11 -238 -239 -12 +241 +242 +11 -325 -326 -12 +328 +329 +11 -422 -423 -12 +425 +426 +11 -520 -521 -12 +523 +524 +11 -754 -755 -12 +758 +759 +11 -1007 -1008 -12 +1011 +1012 +11 -1259 -1260 -12 +1520 +1521 +11 -1514 -1515 -12 +1701 +1702 +11 -2559 -2560 -12 +2566 +2567 +11 -2804 -2805 -12 +2917 +2918 +11 -4818 -4819 -12 +5686 +5687 +11 -13309 -13310 -12 +17602 +17603 +11 -40569 -40570 -12 +42858 +42859 +11 -84931 -84932 -12 +88286 +88287 +11 @@ -24658,102 +24864,102 @@ 4 5 -12 +11 7 8 -12 +11 14 15 -12 +11 22 23 -12 +11 32 33 -12 +11 54 55 -12 +11 -57 -58 -12 +60 +61 +11 -61 -62 -12 +62 +63 +11 -75 -76 -12 +78 +79 +11 -90 -91 -12 +91 +92 +11 -137 -138 -12 +140 +141 +11 214 215 -12 +11 -238 -239 -12 +242 +243 +11 -316 -317 -12 +317 +318 +11 -517 -518 -12 +521 +522 +11 -695 -696 -12 +700 +701 +11 -1468 -1469 -12 +1491 +1492 +11 -3652 -3653 -12 +3698 +3699 +11 -8773 -8774 -12 +8798 +8799 +11 -17388 -17389 -12 +17653 +17654 +11 @@ -24769,27 +24975,27 @@ 1 2 -249547 +242738 2 3 -48698 +46902 3 6 -29783 +28756 6 -19 -27996 +20 +27704 -19 -906 -13821 +20 +1989 +13285 @@ -24805,17 +25011,238 @@ 1 2 -341230 +331740 2 5 -28129 +27131 5 -10 -486 +12 +514 + + + + + + + + +function_template_argument_value +209892 + + +function_id +113037 + + +index +163 + + +arg_value +181755 + + + + +function_id +index + + +12 + + +1 +2 +107207 + + +2 +14 +5830 + + + + + + +function_id +arg_value + + +12 + + +1 +2 +89610 + + +2 +3 +17106 + + +3 +113 +6321 + + + + + + +index +function_id + + +12 + + +3 +4 +70 + + +5 +6 +11 + + +6 +7 +11 + + +111 +112 +11 + + +441 +442 +11 + + +857 +858 +11 + + +2136 +2137 +11 + + +2428 +2429 +11 + + +4217 +4218 +11 + + + + + + +index +arg_value + + +12 + + +5 +6 +70 + + +7 +8 +11 + + +8 +9 +11 + + +157 +158 +11 + + +405 +406 +11 + + +973 +974 +11 + + +2523 +2524 +11 + + +4848 +4849 +11 + + +6604 +6605 +11 + + + + + + +arg_value +function_id + + +12 + + +1 +2 +153712 + + +2 +3 +27949 + + +3 +4 +93 + + + + + + +arg_value +index + + +12 + + +1 +2 +181755 @@ -24825,26 +25252,26 @@ is_variable_template -19778 +19011 id -19778 +19011 variable_instantiation -31837 +38057 to -31837 +38057 from -6734 +6929 @@ -24858,7 +25285,7 @@ 1 2 -31837 +38057 @@ -24874,37 +25301,37 @@ 1 2 -2382 +2383 2 3 -2030 +2033 3 4 -449 +432 4 5 -692 +782 5 9 -534 +560 9 -29 -534 +21 +525 -42 -214 -109 +24 +286 +210 @@ -24914,11 +25341,11 @@ variable_template_argument -5529 +5499 variable_id -843 +848 index @@ -24926,7 +25353,7 @@ arg_type -4257 +4214 @@ -24940,12 +25367,12 @@ 1 2 -692 +685 2 3 -112 +123 3 @@ -24966,12 +25393,12 @@ 1 2 -369 +371 2 3 -125 +130 3 @@ -24981,12 +25408,12 @@ 4 6 -72 +71 6 8 -72 +71 8 @@ -25025,13 +25452,13 @@ 6 -9 -10 +10 +11 6 -17 -18 +20 +21 6 @@ -25066,8 +25493,8 @@ 6 -137 -138 +139 +140 6 @@ -25089,17 +25516,17 @@ 1 2 -3532 +3490 2 3 -481 +476 3 11 -243 +247 @@ -25115,12 +25542,148 @@ 1 2 -4046 +3999 + + +2 +4 +215 + + + + + + + + +variable_template_argument_value +137 + + +variable_id +19 + + +index +13 + + +arg_value +137 + + + + +variable_id +index + + +12 + + +1 +2 +13 2 3 -210 +6 + + + + + + +variable_id +arg_value + + +12 + + +3 +4 +13 + + +15 +16 +6 + + + + + + +index +variable_id + + +12 + + +1 +2 +6 + + +3 +4 +6 + + + + + + +index +arg_value + + +12 + + +6 +7 +6 + + +15 +16 +6 + + + + + + +arg_value +variable_id + + +12 + + +1 +2 +137 + + + + + + +arg_value +index + + +12 + + +1 +2 +137 @@ -25130,15 +25693,15 @@ routinetypes -444572 +436132 id -444572 +436132 return_type -184814 +178086 @@ -25152,7 +25715,7 @@ 1 2 -444572 +436132 @@ -25168,22 +25731,22 @@ 1 2 -148344 +142985 2 3 -21030 +20191 3 -18 -13943 +17 +13367 -18 -7709 -1495 +17 +8001 +1542 @@ -25193,19 +25756,19 @@ routinetypeargs -741201 +726544 routine -362760 +357377 index -389 +373 type_id -209394 +208724 @@ -25219,27 +25782,27 @@ 1 2 -169412 +166448 2 3 -95355 +96574 3 4 -58144 +55888 4 6 -31351 +30298 6 33 -8497 +8167 @@ -25255,22 +25818,22 @@ 1 2 -194831 +190916 2 3 -95853 +97018 3 4 -49707 +47778 4 22 -22367 +21663 @@ -25286,62 +25849,62 @@ 1 2 -133 +128 2 7 -24 +23 10 16 -24 +23 19 33 -24 +23 52 74 -24 +23 93 115 -24 +23 139 199 -24 +23 269 364 -24 +23 473 700 -24 +23 1319 -3279 -24 +3293 +23 -8061 -15906 -24 +8075 +16341 +23 -29841 -29842 -12 +30585 +30586 +11 @@ -25357,62 +25920,62 @@ 1 2 -133 +128 2 5 -24 +23 6 10 -24 +23 11 22 -24 +23 33 37 -24 +23 38 42 -24 +23 44 83 -24 +23 124 183 -24 +23 248 346 -24 +23 463 950 -24 +23 -2463 -5546 -24 +2464 +5642 +23 -12306 -12307 -12 +12850 +12851 +11 @@ -25428,27 +25991,27 @@ 1 2 -123691 +124231 2 3 -40869 +41258 3 4 -13505 +13016 4 7 -17942 +17293 7 -1097 -13384 +1099 +12923 @@ -25464,17 +26027,17 @@ 1 2 -156830 +158176 2 3 -41161 +39576 3 33 -11402 +10971 @@ -25484,19 +26047,19 @@ ptrtomembers -12180 +13227 id -12180 +13227 type_id -10247 +10013 class_id -5519 +6601 @@ -25510,7 +26073,7 @@ 1 2 -12180 +13227 @@ -25526,7 +26089,7 @@ 1 2 -12180 +13227 @@ -25542,12 +26105,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25563,12 +26126,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25584,22 +26147,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25615,22 +26178,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25640,15 +26203,15 @@ specifiers -547 +525 id -547 +525 str -547 +525 @@ -25662,7 +26225,7 @@ 1 2 -547 +525 @@ -25678,7 +26241,7 @@ 1 2 -547 +525 @@ -25688,15 +26251,15 @@ typespecifiers -1464874 +1479986 type_id -1460193 +1472695 spec_id -85 +81 @@ -25710,12 +26273,12 @@ 1 2 -1455513 +1465403 2 3 -4680 +7291 @@ -25731,37 +26294,37 @@ 102 103 -12 +11 222 223 -12 +11 518 519 -12 +11 -718 -719 -12 +957 +958 +11 2323 2324 -12 +11 -19328 -19329 -12 +20241 +20242 +11 -97291 -97292 -12 +102297 +102298 +11 @@ -25771,15 +26334,15 @@ funspecifiers -11370456 +11412148 func_id -3511992 +3500391 spec_id -194 +186 @@ -25793,27 +26356,27 @@ 1 2 -342616 +329999 2 3 -464083 +448167 3 4 -909155 +883458 4 5 -1670402 +1717910 5 8 -125733 +120855 @@ -25829,82 +26392,82 @@ 22 23 -12 +11 169 170 -12 +11 491 492 -12 +11 -506 -507 -12 +598 +599 +11 632 633 -12 +11 5650 5651 -12 +11 9530 9531 -12 +11 10451 10452 -12 +11 -11821 -11822 -12 +11834 +11835 +11 14848 14849 -12 +11 -25330 -25331 -12 +26196 +26197 +11 -33532 -33533 -12 +33724 +33725 +11 -122462 -122463 -12 +131801 +131802 +11 -204591 -204592 -12 +214925 +214926 +11 -232301 -232302 -12 +242884 +242885 +11 -263009 -263010 -12 +272918 +272919 +11 @@ -25914,11 +26477,11 @@ varspecifiers -1124158 +1113938 var_id -935091 +926194 spec_id @@ -25936,17 +26499,17 @@ 1 2 -795258 +787198 2 3 -92279 +91911 3 5 -47553 +47084 @@ -25980,13 +26543,13 @@ 6 -8409 -8410 +8411 +8412 6 -8751 -8752 +8753 +8754 6 @@ -25995,13 +26558,13 @@ 6 -13352 -13353 +13439 +13440 6 -42323 -42324 +42412 +42413 6 @@ -26590,11 +27153,11 @@ attribute_args -118319 +118389 id -118319 +118389 kind @@ -26602,7 +27165,7 @@ attribute -116952 +117020 index @@ -26610,7 +27173,7 @@ location -58256 +58290 @@ -26624,7 +27187,7 @@ 1 2 -118319 +118389 @@ -26640,7 +27203,7 @@ 1 2 -118319 +118389 @@ -26656,7 +27219,7 @@ 1 2 -118319 +118389 @@ -26672,7 +27235,7 @@ 1 2 -118319 +118389 @@ -26772,12 +27335,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26793,7 +27356,7 @@ 1 2 -116431 +116499 2 @@ -26814,12 +27377,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26835,7 +27398,7 @@ 1 2 -116137 +116205 2 @@ -26955,22 +27518,22 @@ 1 2 -28468 +28485 2 3 -7516 +7521 3 4 -19458 +19469 4 25 -2812 +2814 @@ -26986,12 +27549,12 @@ 1 2 -52020 +52051 2 3 -6235 +6239 @@ -27007,22 +27570,22 @@ 1 2 -28452 +28469 2 3 -7534 +7539 3 4 -19454 +19466 4 25 -2814 +2815 @@ -27038,7 +27601,7 @@ 1 2 -58250 +58285 3 @@ -27053,15 +27616,15 @@ attribute_arg_value -118292 +118362 arg -118292 +118362 value -2257 +2258 @@ -27075,7 +27638,7 @@ 1 2 -118292 +118362 @@ -27091,7 +27654,7 @@ 1 2 -1808 +1809 2 @@ -27116,15 +27679,15 @@ attribute_arg_type -60 +58 arg -60 +58 type_id -36 +35 @@ -27138,7 +27701,7 @@ 1 2 -60 +58 @@ -27154,12 +27717,12 @@ 1 2 -12 +11 2 3 -24 +23 @@ -27222,15 +27785,15 @@ typeattributes -12119 +12701 type_id -10831 +11462 spec_id -12119 +12701 @@ -27244,12 +27807,12 @@ 1 2 -10296 +10948 2 34 -534 +514 @@ -27265,7 +27828,7 @@ 1 2 -12119 +12701 @@ -27275,15 +27838,15 @@ funcattributes -327044 +314529 func_id -174943 +168330 spec_id -327044 +314529 @@ -27297,22 +27860,22 @@ 1 2 -94078 +90603 2 3 -13554 +13028 3 4 -65134 +62606 4 14 -2176 +2091 @@ -27328,7 +27891,7 @@ 1 2 -327044 +314529 @@ -27444,15 +28007,15 @@ unspecifiedtype -9406353 +9451546 type_id -9406353 +9451546 unspecified_type_id -5062897 +5133540 @@ -27466,7 +28029,7 @@ 1 2 -9406353 +9451546 @@ -27482,22 +28045,17 @@ 1 2 -2733810 +2776289 2 3 -1943594 +1978655 3 -30 -379779 - - -30 -7873 -5713 +7936 +378596 @@ -27507,19 +28065,19 @@ member -5112192 +5066844 parent -809800 +833190 index -2966 +2851 child -5095258 +5050544 @@ -27533,47 +28091,47 @@ 1 2 -46948 +45126 2 3 -191658 +219789 3 4 -208336 +209109 4 5 -90285 +90638 5 7 -65073 +67210 7 9 -67212 +65539 9 15 -68221 +66497 15 -39 -62471 +45 +62758 -39 +45 245 -9591 +6520 @@ -27589,47 +28147,47 @@ 1 2 -46218 +44425 2 3 -191719 +219824 3 4 -202769 +203723 4 5 -93154 +93454 5 7 -65766 +67876 7 9 -67346 +65668 9 15 -68999 +67245 15 -38 -61462 +41 +62641 -38 +41 281 -12363 +8331 @@ -27645,62 +28203,62 @@ 1 2 -547 +525 2 5 -267 +257 5 9 -255 +245 9 18 -230 +222 23 100 -230 +222 122 186 -230 +222 188 293 -230 +222 296 374 -230 +222 375 542 -230 +222 572 3257 -230 +222 3427 -21556 -230 +22111 +222 -29162 -65993 -48 +30337 +70680 +46 @@ -27716,62 +28274,62 @@ 1 2 -534 +514 2 5 -218 +210 5 7 -230 +222 7 13 -230 +222 13 70 -230 +222 71 160 -230 +222 160 256 -230 +222 263 345 -230 +222 346 476 -243 +233 492 1685 -230 +222 1926 -8765 -230 +8775 +222 -10213 -66838 -121 +10226 +71530 +116 @@ -27787,7 +28345,7 @@ 1 2 -5095258 +5050544 @@ -27803,12 +28361,12 @@ 1 2 -5078555 +5034466 2 7 -16702 +16078 @@ -27818,15 +28376,15 @@ enclosingfunction -131751 +127164 child -131751 +127164 parent -74239 +71639 @@ -27840,7 +28398,7 @@ 1 2 -131751 +127164 @@ -27856,27 +28414,27 @@ 1 2 -39240 +37811 2 3 -21930 +21231 3 4 -7208 +6952 4 6 -5652 +5445 6 45 -206 +198 @@ -27886,27 +28444,27 @@ derivations -370309 +392220 derivation -370309 +392220 sub -346555 +367484 index -72 +70 super -237840 +236475 location -96351 +92613 @@ -27920,7 +28478,7 @@ 1 2 -370309 +392220 @@ -27936,7 +28494,7 @@ 1 2 -370309 +392220 @@ -27952,7 +28510,7 @@ 1 2 -370309 +392220 @@ -27968,7 +28526,7 @@ 1 2 -370309 +392220 @@ -27984,12 +28542,12 @@ 1 2 -326108 +345926 2 7 -20447 +21558 @@ -28005,12 +28563,12 @@ 1 2 -334933 +356161 2 7 -11621 +11322 @@ -28026,12 +28584,12 @@ 1 2 -326120 +345937 2 7 -20434 +21546 @@ -28047,12 +28605,12 @@ 1 2 -334921 +356150 2 7 -11633 +11334 @@ -28068,32 +28626,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -957 -958 -12 +970 +971 +11 -29236 -29237 -12 +32328 +32329 +11 @@ -28109,32 +28667,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -956 -957 -12 +969 +970 +11 -28508 -28509 -12 +31450 +31451 +11 @@ -28150,32 +28708,32 @@ 1 2 -12 +11 3 4 -12 +11 29 30 -12 +11 84 85 -12 +11 -441 -442 -12 +452 +453 +11 -19051 -19052 -12 +19713 +19714 +11 @@ -28191,32 +28749,32 @@ 1 2 -12 +11 4 5 -12 +11 17 18 -12 +11 51 52 -12 +11 254 255 -12 +11 7602 7603 -12 +11 @@ -28232,12 +28790,12 @@ 1 2 -222438 +221343 2 -766 -15402 +1134 +15131 @@ -28253,12 +28811,12 @@ 1 2 -222450 +221355 2 -766 -15390 +1134 +15120 @@ -28274,12 +28832,12 @@ 1 2 -237342 +235996 2 4 -498 +479 @@ -28295,12 +28853,12 @@ 1 2 -229780 +228634 2 439 -8059 +7840 @@ -28316,22 +28874,22 @@ 1 2 -74652 +70786 2 3 -9336 +8985 3 8 -7306 +7606 8 -682 -5057 +698 +5234 @@ -28347,22 +28905,22 @@ 1 2 -77193 +73146 2 3 -7002 +6858 3 -9 -7609 +8 +7443 -9 -682 -4546 +8 +698 +5164 @@ -28378,12 +28936,12 @@ 1 2 -96327 +92589 2 4 -24 +23 @@ -28399,22 +28957,22 @@ 1 2 -77655 +73882 2 3 -9056 +8833 3 -11 -7269 +10 +7326 -11 -682 -2370 +10 +698 +2570 @@ -28424,15 +28982,15 @@ derspecifiers -372947 +394756 der_id -370272 +392185 spec_id -48 +46 @@ -28446,12 +29004,12 @@ 1 2 -367598 +389615 2 3 -2674 +2570 @@ -28467,22 +29025,22 @@ 220 221 -12 +11 242 243 -12 +11 979 980 -12 +11 -29238 -29239 -12 +32343 +32344 +11 @@ -28492,15 +29050,15 @@ direct_base_offsets -282029 +307366 der_id -282029 +307366 offset -206 +210 @@ -28514,7 +29072,7 @@ 1 2 -282029 +307366 @@ -28530,62 +29088,67 @@ 1 2 -36 +46 2 3 -12 +11 4 5 -24 +23 5 6 -12 +11 6 7 -24 +11 7 8 -12 +23 8 9 -24 +11 + + +10 +11 +11 11 12 -12 +11 21 22 -12 +11 -78 -79 -12 +85 +86 +11 200 201 -12 +11 -22837 -22838 -12 +25931 +25932 +11 @@ -28595,19 +29158,19 @@ virtual_base_offsets -7026 +6753 sub -3890 +3739 super -534 +514 offset -267 +257 @@ -28621,22 +29184,22 @@ 1 2 -3063 +2944 2 4 -340 +327 4 7 -279 +268 7 11 -206 +198 @@ -28652,17 +29215,17 @@ 1 2 -3282 +3154 2 4 -328 +315 4 8 -279 +268 @@ -28678,52 +29241,52 @@ 1 2 -85 +81 2 3 -48 +46 3 4 -60 +58 4 5 -97 +93 5 7 -36 +35 8 13 -48 +46 13 15 -48 +46 15 23 -48 +46 24 60 -48 +46 196 197 -12 +11 @@ -28739,32 +29302,32 @@ 1 2 -303 +292 2 3 -85 +81 4 6 -36 +35 6 8 -48 +46 8 10 -48 +46 14 15 -12 +11 @@ -28780,57 +29343,57 @@ 2 3 -36 +35 4 5 -12 +11 5 6 -24 +23 6 8 -24 +23 8 9 -36 +35 10 12 -24 +23 14 19 -24 +23 20 27 -24 +23 28 31 -24 +23 36 97 -24 +23 97 98 -12 +11 @@ -28846,37 +29409,37 @@ 1 2 -85 +81 2 3 -36 +35 3 4 -48 +46 5 7 -24 +23 7 10 -24 +23 12 14 -24 +23 21 29 -24 +23 @@ -28886,23 +29449,23 @@ frienddecls -231178 +222208 id -231178 +222208 type_id -19511 +18753 decl_id -28810 +27692 location -8096 +7782 @@ -28916,7 +29479,7 @@ 1 2 -231178 +222208 @@ -28932,7 +29495,7 @@ 1 2 -231178 +222208 @@ -28948,7 +29511,7 @@ 1 2 -231178 +222208 @@ -28964,47 +29527,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29020,47 +29583,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29076,17 +29639,17 @@ 1 2 -17748 +17059 2 5 -1543 +1483 5 31 -218 +210 @@ -29102,37 +29665,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29148,37 +29711,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29194,12 +29757,12 @@ 1 2 -28215 +27120 2 46 -595 +572 @@ -29215,17 +29778,17 @@ 1 2 -6917 +6648 2 3 -1045 +1004 3 18239 -133 +128 @@ -29241,12 +29804,12 @@ 1 2 -7609 +7314 2 1215 -486 +467 @@ -29262,17 +29825,17 @@ 1 2 -6929 +6660 2 3 -1033 +993 3 1734 -133 +128 @@ -29282,19 +29845,19 @@ comments -1743633 +1675974 id -1743633 +1675974 contents -864492 +830947 location -1743633 +1675974 @@ -29308,7 +29871,7 @@ 1 2 -1743633 +1675974 @@ -29324,7 +29887,7 @@ 1 2 -1743633 +1675974 @@ -29340,17 +29903,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29366,17 +29929,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29392,7 +29955,7 @@ 1 2 -1743633 +1675974 @@ -29408,7 +29971,7 @@ 1 2 -1743633 +1675974 @@ -29418,15 +29981,15 @@ commentbinding -778436 +748230 id -679021 +652673 element -747438 +718434 @@ -29440,17 +30003,17 @@ 1 2 -616002 +592099 2 4 -58545 +56273 4 97 -4473 +4299 @@ -29466,12 +30029,12 @@ 1 2 -716439 +688638 2 3 -30998 +29796 @@ -29481,15 +30044,15 @@ exprconv -6445331 +6446816 converted -6445038 +6446523 conversion -6445331 +6446816 @@ -29503,7 +30066,7 @@ 1 2 -6444746 +6446231 2 @@ -29524,7 +30087,7 @@ 1 2 -6445331 +6446816 @@ -29534,30 +30097,30 @@ compgenerated -6720341 +6652484 id -6720341 +6652484 synthetic_destructor_call -59493 +57185 element -47422 +45582 i -340 +327 destructor_call -49573 +47650 @@ -29571,17 +30134,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29597,17 +30160,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29623,27 +30186,27 @@ 1 2 -255 +245 2 7 -24 +23 22 43 -24 +23 190 711 -24 +23 3901 3902 -12 +11 @@ -29659,27 +30222,27 @@ 1 2 -255 +245 2 7 -24 +23 21 37 -24 +23 146 550 -24 +23 3297 3298 -12 +11 @@ -29695,17 +30258,17 @@ 1 2 -43823 +42123 2 3 -3719 +3575 3 26 -2030 +1951 @@ -29721,7 +30284,7 @@ 1 2 -49573 +47650 @@ -29731,15 +30294,15 @@ namespaces -8497 +8167 id -8497 +8167 name -4570 +4393 @@ -29753,7 +30316,7 @@ 1 2 -8497 +8167 @@ -29769,17 +30332,17 @@ 1 2 -3841 +3692 2 3 -461 +444 3 139 -267 +257 @@ -29789,26 +30352,26 @@ namespace_inline -170 +163 id -170 +163 namespacembrs -1570027 +1616300 parentid -7913 +7606 memberid -1570027 +1616300 @@ -29822,62 +30385,67 @@ 1 2 -875 +829 2 3 -826 +794 3 4 -644 +385 4 -6 -680 - - -6 -9 +5 607 -9 -16 -680 +5 +8 +666 -16 -27 -607 +8 +14 +677 -27 -46 -619 - - -46 -85 -607 - - -85 -169 -607 - - -169 -444 +14 +22 595 -475 -29073 -559 +22 +42 +595 + + +42 +63 +572 + + +63 +127 +572 + + +127 +304 +572 + + +321 +1041 +572 + + +1101 +32701 +163 @@ -29893,7 +30461,7 @@ 1 2 -1570027 +1616300 @@ -29903,19 +30471,19 @@ exprparents -13615303 +13481241 expr_id -13615112 +13481052 child_index -3163 +3131 parent_id -9644209 +9549204 @@ -29929,7 +30497,7 @@ 1 2 -13615105 +13481045 2 @@ -29950,12 +30518,12 @@ 1 2 -13614927 +13480869 2 4 -184 +182 @@ -29971,37 +30539,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 46 -243 +241 46 56 -237 +234 56 3660 -237 +234 6434 -1187727 -46 +1188148 +45 @@ -30017,37 +30585,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 31 -243 +241 31 41 -237 +234 41 3645 -237 +234 6419 -1187740 -46 +1188161 +45 @@ -30063,17 +30631,17 @@ 1 2 -6840662 +6772879 2 3 -2212086 +2190858 3 1681 -591461 +585466 @@ -30089,17 +30657,17 @@ 1 2 -6840682 +6772898 2 3 -2212066 +2190839 3 480 -591461 +585466 @@ -30109,22 +30677,22 @@ expr_isload -5063114 +5014574 expr_id -5063114 +5014574 conversionkinds -4254113 +4255501 expr_id -4254113 +4255501 kind @@ -30142,7 +30710,7 @@ 1 2 -4254113 +4255501 @@ -30166,8 +30734,8 @@ 1 -13109 -13110 +13672 +13673 1 @@ -30181,8 +30749,8 @@ 1 -4161592 -4161593 +4162417 +4162418 1 @@ -30193,15 +30761,15 @@ iscall -2365240 +2284876 caller -2365240 +2284876 kind -36 +35 @@ -30215,7 +30783,7 @@ 1 2 -2365240 +2284876 @@ -30231,17 +30799,17 @@ 1319 1320 -12 +11 -5604 -5605 -12 +5643 +5644 +11 -187644 -187645 -12 +188582 +188583 +11 @@ -30251,15 +30819,15 @@ numtemplatearguments -157948 +152181 expr_id -157948 +152181 num -48 +46 @@ -30273,7 +30841,7 @@ 1 2 -157948 +152181 @@ -30289,22 +30857,22 @@ 3 4 -12 +11 41 42 -12 +11 651 652 -12 +11 -12298 -12299 -12 +12329 +12330 +11 @@ -30314,15 +30882,15 @@ specialnamequalifyingelements -12 +11 id -12 +11 name -12 +11 @@ -30336,7 +30904,7 @@ 1 2 -12 +11 @@ -30352,7 +30920,7 @@ 1 2 -12 +11 @@ -30362,23 +30930,23 @@ namequalifiers -1125621 +1116919 id -1125621 +1116919 qualifiableelement -1125621 +1116919 qualifyingelement -37001 +38961 location -509589 +506087 @@ -30392,7 +30960,7 @@ 1 2 -1125621 +1116919 @@ -30408,7 +30976,7 @@ 1 2 -1125621 +1116919 @@ -30424,7 +30992,7 @@ 1 2 -1125621 +1116919 @@ -30440,7 +31008,7 @@ 1 2 -1125621 +1116919 @@ -30456,7 +31024,7 @@ 1 2 -1125621 +1116919 @@ -30472,7 +31040,7 @@ 1 2 -1125621 +1116919 @@ -30488,109 +31056,109 @@ 1 2 -17109 +18965 2 3 -7935 +8142 3 4 -5081 - - -4 -10 -2860 - - -10 -86 -2781 - - -86 -24926 -1232 - - - - - - -qualifyingelement -qualifiableelement - - -12 - - -1 -2 -17109 - - -2 -3 -7935 - - -3 -4 -5081 - - -4 -10 -2860 - - -10 -86 -2781 - - -86 -24926 -1232 - - - - - - -qualifyingelement -location - - -12 - - -1 -2 -22745 - - -2 -3 -4817 - - -3 -4 -3802 +5043 4 11 -3018 +3027 + + +11 +129 +2935 + + +132 +24926 +848 + + + + + + +qualifyingelement +qualifiableelement + + +12 + + +1 +2 +18965 + + +2 +3 +8142 + + +3 +4 +5043 + + +4 +11 +3027 + + +11 +129 +2935 + + +132 +24926 +848 + + + + + + +qualifyingelement +location + + +12 + + +1 +2 +24850 + + +2 +3 +4762 + + +3 +4 +3770 + + +4 +11 +2974 11 16728 -2616 +2603 @@ -30606,22 +31174,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30637,22 +31205,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30668,17 +31236,17 @@ 1 2 -452478 +449080 2 3 -44785 +44650 3 190 -12324 +12356 @@ -30688,15 +31256,15 @@ varbind -5497554 +5445518 expr -5497428 +5445394 var -1549133 +1534266 @@ -30710,12 +31278,12 @@ 1 2 -5497303 +5445270 2 3 -125 +123 @@ -30731,32 +31299,32 @@ 1 2 -685882 +679661 2 3 -311295 +308179 3 4 -236831 +234430 4 5 -93953 +93020 5 9 -134777 +133430 9 6150 -86393 +85544 @@ -30766,15 +31334,15 @@ funbind -2442767 +2419854 expr -2142538 +2122577 fun -438611 +434205 @@ -30788,17 +31356,17 @@ 1 2 -1842553 +1825541 2 3 -299807 +296859 3 5 -177 +176 @@ -30814,32 +31382,32 @@ 1 2 -255153 +252065 2 3 -76151 +75516 3 4 -31642 +31302 4 7 -33910 +33957 7 37 -33831 +33520 37 6664 -7922 +7841 @@ -30849,19 +31417,19 @@ expr_allocator -27692 +26617 expr -27692 +26617 func -133 +128 form -12 +11 @@ -30875,7 +31443,7 @@ 1 2 -27692 +26617 @@ -30891,7 +31459,7 @@ 1 2 -27692 +26617 @@ -30907,42 +31475,42 @@ 1 2 -36 +35 3 4 -12 +11 4 5 -12 +11 5 6 -12 +11 7 8 -24 +23 39 40 -12 +11 973 974 -12 +11 1237 1238 -12 +11 @@ -30958,7 +31526,7 @@ 1 2 -133 +128 @@ -30974,7 +31542,7 @@ 2278 2279 -12 +11 @@ -30990,7 +31558,7 @@ 11 12 -12 +11 @@ -31000,19 +31568,19 @@ expr_deallocator -30998 +29796 expr -30998 +29796 func -145 +140 form -24 +23 @@ -31026,7 +31594,7 @@ 1 2 -30998 +29796 @@ -31042,7 +31610,7 @@ 1 2 -30998 +29796 @@ -31058,42 +31626,42 @@ 1 2 -36 +35 2 3 -24 +23 3 4 -12 +11 4 5 -12 +11 7 8 -24 +23 118 119 -12 +11 883 884 -12 +11 1521 1522 -12 +11 @@ -31109,7 +31677,7 @@ 1 2 -145 +140 @@ -31125,12 +31693,12 @@ 891 892 -12 +11 1659 1660 -12 +11 @@ -31146,12 +31714,12 @@ 4 5 -12 +11 8 9 -12 +11 @@ -31161,26 +31729,26 @@ expr_cond_two_operand -610 +611 cond -610 +611 expr_cond_guard -154429 +154519 cond -154429 +154519 guard -154429 +154519 @@ -31194,7 +31762,7 @@ 1 2 -154429 +154519 @@ -31210,7 +31778,7 @@ 1 2 -154429 +154519 @@ -31220,15 +31788,15 @@ expr_cond_true -154429 +154519 cond -154429 +154519 true -154429 +154519 @@ -31242,7 +31810,7 @@ 1 2 -154429 +154519 @@ -31258,7 +31826,7 @@ 1 2 -154429 +154519 @@ -31268,15 +31836,15 @@ expr_cond_false -154429 +154519 cond -154429 +154519 false -154429 +154519 @@ -31290,7 +31858,7 @@ 1 2 -154429 +154519 @@ -31306,7 +31874,7 @@ 1 2 -154429 +154519 @@ -31316,15 +31884,15 @@ values -8776796 +8788031 id -8776796 +8788031 str -651390 +651491 @@ -31338,7 +31906,7 @@ 1 2 -8776796 +8788031 @@ -31354,17 +31922,17 @@ 1 2 -540103 +540120 2 3 -65463 +65472 3 -4044535 -45824 +4046841 +45899 @@ -31374,15 +31942,15 @@ valuetext -4759381 +4766569 id -4759381 +4766569 text -704971 +705085 @@ -31396,7 +31964,7 @@ 1 2 -4759381 +4766569 @@ -31412,22 +31980,22 @@ 1 2 -528095 +528108 2 3 -102815 +102830 3 7 -56849 +56879 7 427516 -17212 +17268 @@ -31437,15 +32005,15 @@ valuebind -9499071 +9509366 val -8769631 +8779926 expr -9499071 +9509366 @@ -31459,7 +32027,7 @@ 1 2 -8040923 +8051218 2 @@ -31485,7 +32053,7 @@ 1 2 -9499071 +9509366 @@ -31495,19 +32063,19 @@ fieldoffsets -259539 +251575 id -259539 +251575 byteoffset -3914 +9022 bitoffset -85 +52 @@ -31521,7 +32089,7 @@ 1 2 -259539 +251575 @@ -31537,7 +32105,7 @@ 1 2 -259539 +251575 @@ -31553,42 +32121,27 @@ 1 2 -1689 +6132 2 3 -534 +782 3 -4 -194 - - -4 6 -340 +750 6 -11 -328 +17 +678 -11 -23 -328 - - -23 -84 -303 - - -90 -12369 -194 +17 +11685 +678 @@ -31604,12 +32157,12 @@ 1 2 -3853 +8579 2 -8 -60 +9 +443 @@ -31623,29 +32176,44 @@ 12 -1 -2 -36 +83 +84 +6 -2 -3 -12 +87 +88 +6 -3 -4 -12 +102 +103 +6 -4 -5 -12 +122 +123 +6 -21338 -21339 -12 +127 +128 +6 + + +153 +154 +6 + + +195 +196 +6 + + +37692 +37693 +6 @@ -31659,24 +32227,44 @@ 12 -1 -2 -36 +40 +41 +6 -2 -3 -24 +44 +45 +6 -3 -4 -12 +45 +46 +6 -322 -323 -12 +52 +53 +6 + + +54 +55 +6 + + +58 +59 +6 + + +66 +67 +6 + + +1383 +1384 +6 @@ -31686,11 +32274,11 @@ bitfield -13357 +13365 id -13357 +13365 bits @@ -31712,7 +32300,7 @@ 1 2 -13357 +13365 @@ -31728,7 +32316,7 @@ 1 2 -13357 +13365 @@ -31892,23 +32480,23 @@ initialisers -1685017 +1668506 init -1685017 +1668506 var -649685 +643667 expr -1685017 +1668506 location -321906 +318643 @@ -31922,7 +32510,7 @@ 1 2 -1685017 +1668506 @@ -31938,7 +32526,7 @@ 1 2 -1685017 +1668506 @@ -31954,7 +32542,7 @@ 1 2 -1685017 +1668506 @@ -31970,22 +32558,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32001,22 +32589,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32032,7 +32620,7 @@ 1 2 -649672 +643654 2 @@ -32053,7 +32641,7 @@ 1 2 -1685017 +1668506 @@ -32069,7 +32657,7 @@ 1 2 -1685017 +1668506 @@ -32085,7 +32673,7 @@ 1 2 -1685017 +1668506 @@ -32101,27 +32689,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32137,22 +32725,22 @@ 1 2 -271334 +268551 2 3 -25342 +25091 3 -24 -24155 +23 +23904 -24 +23 12632 -1074 +1096 @@ -32168,27 +32756,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32198,15 +32786,15 @@ expr_ancestor -67772 +68706 exp -67176 +68133 ancestor -49695 +51330 @@ -32220,12 +32808,12 @@ 1 2 -66605 +67584 2 4 -571 +549 @@ -32241,17 +32829,17 @@ 1 2 -37405 +39517 2 3 -10150 +9756 3 29 -2139 +2056 @@ -32261,19 +32849,19 @@ exprs -18449753 +18460593 id -18449753 +18460593 kind -393 +1168 location -6150603 +3836046 @@ -32287,7 +32875,7 @@ 1 2 -18449753 +18460593 @@ -32303,7 +32891,7 @@ 1 2 -18449753 +18460593 @@ -32317,69 +32905,69 @@ 12 -5 -28 -30 +1 +14 +105 -71 -82 -30 +15 +44 +93 -94 -255 -30 +47 +86 +93 -271 -627 -30 +90 +223 +93 -858 -1879 -30 +296 +463 +93 -2191 -3716 -30 +483 +715 +93 -4305 -6068 -30 +788 +2129 +93 -7004 -11661 -30 +2165 +2950 +93 -12107 -20202 -30 +3030 +4378 +93 -21965 -29561 -30 +4477 +6077 +93 -32830 -41032 -30 +6490 +17249 +93 -44670 -145995 -30 +19347 +188353 +93 -447805 -725766 -24 +191022 +403956 +35 @@ -32394,68 +32982,68 @@ 1 +4 +105 + + +6 +13 +105 + + +13 24 -30 +93 -27 -72 -30 +24 +38 +93 -77 -157 -30 +38 +134 +93 -171 -402 -30 +144 +259 +93 -422 -1083 -30 +269 +480 +93 -1179 -1862 -30 +481 +1074 +93 -2201 -4268 -30 +1095 +1411 +93 -4679 -6584 -30 +1422 +2045 +93 -6624 -11083 -30 +2059 +4557 +93 -11359 -12983 -30 +5888 +59687 +93 -17158 -28621 -30 - - -29980 -88945 -30 - - -128315 -425042 -24 +72153 +117893 +23 @@ -32471,22 +33059,37 @@ 1 2 -4450587 +1838158 2 3 -874643 +753582 3 -6 -496205 +4 +356208 -6 -22445 -329167 +4 +5 +276250 + + +5 +9 +301489 + + +9 +72 +287759 + + +72 +136887 +22598 @@ -32502,22 +33105,17 @@ 1 2 -4599301 +2734142 2 3 -812812 +859259 3 -5 -498909 - - -5 -33 -239579 +30 +242644 @@ -32527,19 +33125,19 @@ expr_types -18617706 +18629051 id -18444987 +18456012 typeid -1372691 +1345343 value_category -36 +35 @@ -32553,12 +33151,12 @@ 1 2 -18272500 +18283254 2 4 -172487 +172758 @@ -32574,7 +33172,7 @@ 1 2 -18444987 +18456012 @@ -32590,42 +33188,42 @@ 1 2 -530591 +526443 2 3 -259102 +254107 3 4 -113553 +110864 4 5 -95427 +92110 5 8 -122925 +118483 8 14 -105736 +102381 14 -46 -103864 +47 +101797 -46 -111456 -41489 +47 +123210 +39155 @@ -32641,17 +33239,17 @@ 1 2 -1207109 +1185928 2 3 -157753 +151877 3 4 -7828 +7536 @@ -32667,17 +33265,17 @@ 4533 4534 -12 +11 -340895 -340896 -12 +342547 +342548 +11 -1171875 -1171876 -12 +1232420 +1232421 +11 @@ -32691,19 +33289,19 @@ 12 -1340 -1341 -12 +1341 +1342 +11 -29733 -29734 -12 +29841 +29842 +11 -96111 -96112 -12 +98243 +98244 +11 @@ -32713,15 +33311,15 @@ new_allocated_type -29527 +28382 expr -29527 +28382 type_id -18234 +17527 @@ -32735,7 +33333,7 @@ 1 2 -29527 +28382 @@ -32751,22 +33349,22 @@ 1 2 -12667 +12175 2 3 -4035 +3879 3 9 -1446 +1390 10 92 -85 +81 @@ -32776,15 +33374,15 @@ new_array_allocated_type -5364 +5310 expr -5364 +5310 type_id -2306 +2283 @@ -32798,7 +33396,7 @@ 1 2 -5364 +5310 @@ -32819,12 +33417,12 @@ 2 3 -2043 +2022 3 7 -177 +176 8 @@ -33376,15 +33974,15 @@ condition_decl_bind -7646 +7349 expr -7646 +7349 decl -7646 +7349 @@ -33398,7 +33996,7 @@ 1 2 -7646 +7349 @@ -33414,7 +34012,7 @@ 1 2 -7646 +7349 @@ -33424,15 +34022,15 @@ typeid_bind -4899 +4708 expr -4899 +4708 type_id -2601 +2500 @@ -33446,7 +34044,7 @@ 1 2 -4899 +4708 @@ -33462,22 +34060,22 @@ 1 2 -1300 +1250 2 3 -996 +958 3 6 -230 +222 6 17 -72 +70 @@ -33487,15 +34085,15 @@ uuidof_bind -856 +848 expr -856 +848 type_id -652 +645 @@ -33509,7 +34107,7 @@ 1 2 -856 +848 @@ -33525,12 +34123,12 @@ 1 2 -481 +476 2 3 -138 +137 3 @@ -33545,15 +34143,15 @@ sizeof_bind -156997 +157089 expr -156997 +157089 type_id -2673 +2674 @@ -33567,7 +34165,7 @@ 1 2 -156997 +157089 @@ -33583,7 +34181,7 @@ 1 2 -1044 +1045 2 @@ -33681,11 +34279,11 @@ lambdas -12641 +12513 expr -12641 +12513 default_capture @@ -33707,7 +34305,7 @@ 1 2 -12641 +12513 @@ -33723,7 +34321,7 @@ 1 2 -12641 +12513 @@ -33812,23 +34410,23 @@ lambda_capture -21730 +21509 id -21730 +21509 lambda -10097 +9994 index -112 +110 field -21730 +21509 captured_by_reference @@ -33840,7 +34438,7 @@ location -14051 +13909 @@ -33854,7 +34452,7 @@ 1 2 -21730 +21509 @@ -33870,7 +34468,7 @@ 1 2 -21730 +21509 @@ -33886,7 +34484,7 @@ 1 2 -21730 +21509 @@ -33902,7 +34500,7 @@ 1 2 -21730 +21509 @@ -33918,7 +34516,7 @@ 1 2 -21730 +21509 @@ -33934,7 +34532,7 @@ 1 2 -21730 +21509 @@ -33950,27 +34548,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -33986,27 +34584,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34022,27 +34620,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34058,12 +34656,12 @@ 1 2 -9629 +9531 2 3 -467 +463 @@ -34079,7 +34677,7 @@ 1 2 -10077 +9975 2 @@ -34100,27 +34698,27 @@ 1 2 -5483 +5428 2 3 -2504 +2479 3 4 -1041 +1030 4 7 -823 +815 7 18 -243 +241 @@ -34429,7 +35027,7 @@ 2 3 -85 +84 @@ -34450,7 +35048,7 @@ 2 3 -46 +45 @@ -34562,7 +35160,7 @@ 1 2 -21730 +21509 @@ -34578,7 +35176,7 @@ 1 2 -21730 +21509 @@ -34594,7 +35192,7 @@ 1 2 -21730 +21509 @@ -34610,7 +35208,7 @@ 1 2 -21730 +21509 @@ -34626,7 +35224,7 @@ 1 2 -21730 +21509 @@ -34642,7 +35240,7 @@ 1 2 -21730 +21509 @@ -34900,17 +35498,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34926,12 +35524,12 @@ 1 2 -13115 +12982 2 68 -935 +926 @@ -34947,12 +35545,12 @@ 1 2 -13511 +13374 2 8 -540 +534 @@ -34968,17 +35566,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34994,7 +35592,7 @@ 1 2 -14032 +13889 2 @@ -35015,7 +35613,7 @@ 1 2 -14051 +13909 @@ -35141,19 +35739,19 @@ stmts -4943740 +4765273 id -4943740 +4765273 kind -230 +222 location -1317574 +1266448 @@ -35167,7 +35765,7 @@ 1 2 -4943740 +4765273 @@ -35183,7 +35781,7 @@ 1 2 -4943740 +4765273 @@ -35199,97 +35797,97 @@ 2 3 -12 +11 28 29 -12 +11 338 339 -12 +11 473 474 -12 +11 690 691 -12 +11 1560 1561 -12 +11 1757 1758 -12 +11 -2076 -2077 -12 +2080 +2081 +11 -2191 -2192 -12 +2193 +2194 +11 2707 2708 -12 +11 2748 2749 -12 +11 -2944 -2945 -12 +2946 +2947 +11 3296 3297 -12 +11 4540 4541 -12 +11 -28688 -28689 -12 +28694 +28695 +11 -53254 -53255 -12 +53369 +53370 +11 -85878 -85879 -12 +86211 +86212 +11 -98483 -98484 -12 +98824 +98825 +11 -115024 -115025 -12 +115365 +115366 +11 @@ -35305,97 +35903,97 @@ 2 3 -12 +11 23 24 -12 +11 106 107 -12 +11 112 113 -12 +11 178 179 -12 +11 252 253 -12 +11 296 297 -12 +11 661 662 -12 +11 663 664 -12 +11 991 992 -12 +11 1030 1031 -12 +11 1408 1409 -12 +11 1918 1919 -12 +11 2676 2677 -12 +11 10172 10173 -12 +11 10231 10232 -12 +11 22268 22269 -12 +11 26534 26535 -12 +11 31957 31958 -12 +11 @@ -35411,32 +36009,32 @@ 1 2 -779628 +747015 2 3 -179173 +173050 3 4 -120275 +116169 4 6 -106891 +103199 6 19 -102794 +99168 19 -4895 -28810 +4923 +27844 @@ -35452,12 +36050,12 @@ 1 2 -1291693 +1241571 2 9 -25881 +24876 @@ -35563,15 +36161,15 @@ if_then -524558 +524866 if_stmt -524558 +524866 then_id -524558 +524866 @@ -35585,7 +36183,7 @@ 1 2 -524558 +524866 @@ -35601,7 +36199,7 @@ 1 2 -524558 +524866 @@ -35611,15 +36209,15 @@ if_else -148234 +148322 if_stmt -148234 +148322 else_id -148234 +148322 @@ -35633,7 +36231,7 @@ 1 2 -148234 +148322 @@ -35649,7 +36247,7 @@ 1 2 -148234 +148322 @@ -35755,15 +36353,15 @@ while_body -32907 +31630 while_stmt -32907 +31630 body_id -32907 +31630 @@ -35777,7 +36375,7 @@ 1 2 -32907 +31630 @@ -35793,7 +36391,7 @@ 1 2 -32907 +31630 @@ -35803,15 +36401,15 @@ do_body -149900 +149988 do_stmt -149900 +149988 body_id -149900 +149988 @@ -35825,7 +36423,7 @@ 1 2 -149900 +149988 @@ -35841,7 +36439,7 @@ 1 2 -149900 +149988 @@ -35851,11 +36449,11 @@ switch_case -281530 +281695 switch_stmt -55225 +55258 index @@ -35863,7 +36461,7 @@ case_id -281530 +281695 @@ -35877,17 +36475,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -35903,17 +36501,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -36031,7 +36629,7 @@ 1 2 -281530 +281695 @@ -36047,7 +36645,7 @@ 1 2 -281530 +281695 @@ -36057,15 +36655,15 @@ switch_body -55225 +55258 switch_stmt -55225 +55258 body_id -55225 +55258 @@ -36079,7 +36677,7 @@ 1 2 -55225 +55258 @@ -36095,7 +36693,7 @@ 1 2 -55225 +55258 @@ -36105,15 +36703,15 @@ for_initialization -29922 +29619 for_stmt -29922 +29619 init_id -29922 +29619 @@ -36127,7 +36725,7 @@ 1 2 -29922 +29619 @@ -36143,7 +36741,7 @@ 1 2 -29922 +29619 @@ -36153,15 +36751,15 @@ for_condition -31781 +31459 for_stmt -31781 +31459 condition_id -31781 +31459 @@ -36175,7 +36773,7 @@ 1 2 -31781 +31459 @@ -36191,7 +36789,7 @@ 1 2 -31781 +31459 @@ -36201,15 +36799,15 @@ for_update -29659 +29358 for_stmt -29659 +29358 update_id -29659 +29358 @@ -36223,7 +36821,7 @@ 1 2 -29659 +29358 @@ -36239,7 +36837,7 @@ 1 2 -29659 +29358 @@ -36249,15 +36847,15 @@ for_body -32387 +32059 for_stmt -32387 +32059 body_id -32387 +32059 @@ -36271,7 +36869,7 @@ 1 2 -32387 +32059 @@ -36287,7 +36885,7 @@ 1 2 -32387 +32059 @@ -36297,19 +36895,19 @@ stmtparents -4168478 +4131960 id -4168478 +4131960 index -12799 +836 parent -1762006 +1583254 @@ -36323,7 +36921,7 @@ 1 2 -4168478 +4131960 @@ -36339,7 +36937,7 @@ 1 2 -4168478 +4131960 @@ -36355,52 +36953,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36416,52 +37019,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36477,32 +37085,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 +9 +119501 -6 -17 -133386 - - -17 -1943 -12819 +9 +465 +100269 @@ -36518,32 +37121,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 +9 +119501 -6 -17 -133386 - - -17 -1943 -12819 +9 +465 +100269 @@ -36553,26 +37151,26 @@ ishandler -21888 +21666 block -21888 +21666 successors -17214104 +17224218 from -16042874 +16052300 to -16040997 +16050421 @@ -36586,12 +37184,12 @@ 1 2 -15044821 +15053661 2 156 -998052 +998638 @@ -36607,12 +37205,12 @@ 1 2 -15328885 +15337891 2 419 -712111 +712530 @@ -36622,15 +37220,15 @@ truecond -966805 +967373 from -966805 +967373 to -937112 +937663 @@ -36644,7 +37242,7 @@ 1 2 -966805 +967373 @@ -36660,12 +37258,12 @@ 1 2 -913540 +914077 2 21 -23572 +23585 @@ -36675,15 +37273,15 @@ falsecond -966805 +967373 from -966805 +967373 to -812105 +812583 @@ -36697,7 +37295,7 @@ 1 2 -966805 +967373 @@ -36713,17 +37311,17 @@ 1 2 -698749 +699160 2 3 -87006 +87057 3 25 -26349 +26365 @@ -36733,11 +37331,11 @@ stmt_decl_bind -538233 +532777 stmt -531279 +525894 num @@ -36745,7 +37343,7 @@ decl -538233 +532777 @@ -36759,12 +37357,12 @@ 1 2 -525776 +520447 2 9 -5503 +5447 @@ -36780,12 +37378,12 @@ 1 2 -525756 +520427 2 9 -5523 +5467 @@ -36903,7 +37501,7 @@ 1 2 -538233 +532777 @@ -36919,7 +37517,7 @@ 1 2 -538233 +532777 @@ -36929,19 +37527,19 @@ stmt_decl_entry_bind -519726 +520031 stmt -474524 +474803 num -491 +492 decl_entry -495657 +495948 @@ -36955,12 +37553,12 @@ 1 2 -441842 +442101 2 274 -32682 +32702 @@ -36976,12 +37574,12 @@ 1 2 -441842 +442101 2 15 -32682 +32702 @@ -37064,12 +37662,12 @@ 1 2 -483634 +483918 2 85 -12022 +12029 @@ -37085,7 +37683,7 @@ 1 2 -495588 +495879 2 @@ -37100,15 +37698,15 @@ blockscope -1398256 +1347984 block -1398256 +1347984 enclosing -1254288 +1209602 @@ -37122,7 +37720,7 @@ 1 2 -1398256 +1347984 @@ -37138,12 +37736,12 @@ 1 2 -1171636 +1130157 2 509 -82651 +79444 @@ -37153,19 +37751,19 @@ jumpinfo -366503 +366719 id -366503 +366719 str -6361 +6365 target -85508 +85558 @@ -37179,7 +37777,7 @@ 1 2 -366503 +366719 @@ -37195,7 +37793,7 @@ 1 2 -366503 +366719 @@ -37216,12 +37814,12 @@ 2 3 -3507 +3509 3 4 -835 +836 4 @@ -37231,12 +37829,12 @@ 5 7 -491 +492 7 15 -500 +501 15 @@ -37257,12 +37855,12 @@ 1 2 -5095 +5098 2 3 -700 +701 3 @@ -37293,32 +37891,32 @@ 2 3 -21251 +21263 3 4 -7559 +7564 4 5 -3816 +3818 5 6 -39695 +39718 6 7 -11019 +11025 7 162 -1880 +1882 @@ -37334,7 +37932,7 @@ 1 2 -85508 +85558 @@ -37344,19 +37942,19 @@ preprocdirects -1456121 +1399618 id -1456121 +1399618 kind -158 +151 location -1449131 +1392900 @@ -37370,7 +37968,7 @@ 1 2 -1456121 +1399618 @@ -37386,7 +37984,7 @@ 1 2 -1456121 +1399618 @@ -37402,67 +38000,67 @@ 4 5 -12 +11 8 9 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26464 26465 -12 +11 27121 27122 -12 +11 28787 28788 -12 +11 @@ -37478,67 +38076,67 @@ 4 5 -12 +11 7 8 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26122 26123 -12 +11 27121 27122 -12 +11 28555 28556 -12 +11 @@ -37554,12 +38152,12 @@ 1 2 -1448766 +1392549 2 234 -364 +350 @@ -37575,7 +38173,7 @@ 1 2 -1449131 +1392900 @@ -37585,15 +38183,15 @@ preprocpair -416102 +399956 begin -329694 +316901 elseelifend -416102 +399956 @@ -37607,17 +38205,17 @@ 1 2 -261399 +251256 2 3 -60247 +57909 3 53 -8047 +7735 @@ -37633,7 +38231,7 @@ 1 2 -416102 +399956 @@ -37643,41 +38241,41 @@ preproctrue -183112 +176006 branch -183112 +176006 preprocfalse -130000 +124956 branch -130000 +124956 preproctext -1062775 +1021536 id -1062775 +1021536 head -510083 +490290 body -192959 +185471 @@ -37691,7 +38289,7 @@ 1 2 -1062775 +1021536 @@ -37707,7 +38305,7 @@ 1 2 -1062775 +1021536 @@ -37723,22 +38321,22 @@ 1 2 -380459 +365696 2 3 -86116 +82774 3 19 -38414 +36923 19 752 -5093 +4895 @@ -37754,12 +38352,12 @@ 1 2 -486208 +467341 2 38 -23875 +22948 @@ -37775,12 +38373,12 @@ 1 2 -181252 +174219 2 64395 -11706 +11252 @@ -37796,12 +38394,12 @@ 1 2 -182893 +175796 2 21671 -10065 +9674 @@ -37811,15 +38409,15 @@ includes -321805 +309317 id -321805 +309317 included -60162 +57827 @@ -37833,7 +38431,7 @@ 1 2 -321805 +309317 @@ -37849,37 +38447,37 @@ 1 2 -29503 +28358 2 3 -9895 +9511 3 4 -5117 +4919 4 6 -5348 +5141 6 11 -4643 +4463 11 41 -4558 +4381 41 763 -1094 +1051 @@ -37889,15 +38487,15 @@ link_targets -644 +619 id -644 +619 binary -644 +619 @@ -37911,7 +38509,7 @@ 1 2 -644 +619 @@ -37927,7 +38525,7 @@ 1 2 -644 +619 @@ -37937,15 +38535,15 @@ link_parent -19143690 +19072521 element -5076549 +5117392 link_target -644 +619 @@ -37959,32 +38557,32 @@ 1 2 -1439430 +1455425 2 3 -1904730 +1924496 3 4 -772395 +779113 4 6 -426167 +434215 6 -27 -383109 +28 +394382 -27 +28 45 -150715 +129758 @@ -38000,67 +38598,67 @@ 2 3 -97 +93 5 557 -48 +46 -2555 -5912 -48 +2662 +6059 +46 -6322 -8240 -48 +6479 +8402 +46 -9873 -12705 -48 +10060 +12929 +46 -12726 -19568 -48 +13044 +20082 +46 -24613 -26319 -48 +24978 +26985 +46 -26410 -31881 -48 +27088 +32537 +46 -32502 -37729 -48 +33104 +38465 +46 -39858 -40615 -48 +41123 +42511 +46 -43096 -52498 -48 +44410 +55889 +46 -53361 -126529 -48 +55937 +132605 +46 -345660 -345661 -12 +362472 +362473 +11 From afe666500f54db4dc7aa7c688bcab1c1a12b7264 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 11:34:37 +0000 Subject: [PATCH 131/232] C++: Simplify getTemplateArgument*() impl. --- cpp/ql/src/semmle/code/cpp/Class.qll | 18 ------------ cpp/ql/src/semmle/code/cpp/Declaration.qll | 33 ++++++++++------------ cpp/ql/src/semmle/code/cpp/Function.qll | 19 ------------- cpp/ql/src/semmle/code/cpp/Variable.qll | 18 ------------ 4 files changed, 15 insertions(+), 73 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5ccf6193c4f..297654a1afa 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -605,24 +605,6 @@ class Class extends UserType { class_instantiation(underlyingElement(this), unresolveElement(c)) } - /** - * Gets the `i`th template argument used to instantiate this class from a - * class template. When called on a class template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int i) { - class_template_argument(underlyingElement(this), i, unresolveElement(result)) - } - - /** - * Gets the `i`th template argument value used to instantiate this class from a - * class template. When called on a class template, this will return the - * `i`th template parameter value. - */ - override Expr getTemplateArgumentValue(int i) { - class_template_argument_value(underlyingElement(this), i, unresolveElement(result)) - } - /** * Holds if this class/struct is polymorphic (has a virtual function, or * inherits one). diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 9c8ce250d8d..89f52f174de 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -255,25 +255,22 @@ abstract class Declaration extends Locatable, @declaration { result = count(int i | exists(getTemplateArgument(i))) } - /** - * INTERNAL: Do not use. - * - * Gets a Type for a template argument. May be the template argument itself - * or the type of a non-type template argument. - * - * Use `getTemplateArgument` or `getTemplateKind` instead. - */ - Type getTemplateArgumentType(int index) { none() } + private Type getTemplateArgumentType(int index) { + class_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument(underlyingElement(this), index, unresolveElement(result)) + } - /** - * INTERNAL: Do not use. - * - * Gets an Expression representing the value of a non-type template - * argument. - * - * Use `getTemplateArgument` or `getTemplateKind` instead. - */ - Expr getTemplateArgumentValue(int index) { none() } + + private Expr getTemplateArgumentValue(int index) { + class_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 5436c3ba218..14edf014b21 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -343,25 +343,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { function_instantiation(underlyingElement(this), unresolveElement(f)) } - /** - * Gets the `i`th template argument used to instantiate this function from a - * function template. When called on a function template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int index) { - function_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - - /** - * Gets the value of the `i`th template argument used to instantiate this - * function from a function template if that argument was a 'non-type' - * argument. When called on a function template, this with return the value - * of the `i`th template parameter. - */ - override Expr getTemplateArgumentValue(int index) { - function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 689f1c3bfa5..194cc5333c7 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -155,24 +155,6 @@ class Variable extends Declaration, @variable { variable_instantiation(underlyingElement(this), unresolveElement(v)) } - /** - * Gets the `i`th template argument used to instantiate this variable from a - * variable template. When called on a variable template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int index) { - variable_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - - /** - * Gets the `i`th template argument value used to instantiate this variable from a - * variable template. When called on a variable template, this will return the - * `i`th template parameter value. - */ - override Expr getTemplateArgumentValue(int index) { - variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this is a compiler-generated variable. For example, a * [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for) From 8eef953cd75ee10c1292a467fff3297202e5cbc1 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 11:35:35 +0000 Subject: [PATCH 132/232] C++: Update 1.23 change notes --- change-notes/1.23/analysis-cpp.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index f22436f55cb..a92f78ca2f7 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -54,3 +54,8 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. lead to regressions (or improvements) in how queries are optimized because optimization in QL relies on static size estimates, and the control-flow edge relations will now have different size estimates than before. +* Support has been added for non-type template arguments. This means that the + return type of `Declaration::getTemplateArgument()` and + `Declaration::getATemplateArgument` have changed to `Locatable`. See the + documentation for `Declaration::getTemplateArgument()` and + `Declaration::getTemplateArgumentKind()` for details. From 5106626bd07d613f8e2f08193921b14f8539581d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:06:43 +0000 Subject: [PATCH 133/232] CPP: QLDoc helper predicates. --- .../CWE/CWE-457/InitializationFunctions.qll | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 720cf11950b..52b251bad00 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -619,35 +619,41 @@ Function getAPossibleDefinition(Function undefinedFunction) { result.isDefined() } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If there is at least one defined target after performing some simple virtual dispatch + * resolution, then the result is all the defined targets. + */ private Function getTarget1(Call c) { - /* - * If there is at least one defined target after performing some simple virtual dispatch - * resolution, then the result is all the defined targets. - */ - result = VirtualDispatch::getAViableTarget(c) and result.isDefined() } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If we can use the heuristic matching of functions to find definitions for some of the viable + * targets, return those. + */ private Function getTarget2(Call c) { - /* - * If we can use the heuristic matching of functions to find definitions for some of the viable - * targets, return those. - */ - not exists(getTarget1(c)) and result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * Otherwise, the result is the undefined `Function` instances. + */ private Function getTarget3(Call c) { not exists(getTarget1(c)) and not exists(getTarget2(c)) and - // Otherwise, the result is the undefined `Function` instances. result = VirtualDispatch::getAViableTarget(c) } /** - * Gets a possible target for the Call, using the name and parameter matching if we did not associate + * Gets a possible target for the `Call`, using the name and parameter matching if we did not associate * this call with a specific definition at link or compile time, and performing simple virtual * dispatch resolution. */ From 7456a92d6dc5e45f449bf485faba572dfc5a1324 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:10:19 +0000 Subject: [PATCH 134/232] CPP: Autoformat. --- cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 52b251bad00..86102008e2b 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -618,7 +618,7 @@ Function getAPossibleDefinition(Function undefinedFunction) { ) and result.isDefined() } - + /** * Helper predicate for `getTarget`, that computes possible targets of a `Call`. * From df2fbfb3d02485b5a568769ff78d49c6841282b5 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 1 Nov 2019 13:16:45 +0100 Subject: [PATCH 135/232] C++: localInstruction{Flow,Taint} helpers These are analogous to the existing `localExpr{Flow,Taint}` predicates. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 8 ++++++++ .../code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index f824e0b6bf2..cd989c94710 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -214,6 +214,14 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction */ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } +/** + * Holds if data can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionFlow(Instruction e1, Instruction e2) { + localFlow(instructionNode(e1), instructionNode(e2)) +} + /** * Holds if data can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index e34709e94ec..8d7c9194f4f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -53,6 +53,14 @@ private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction no */ predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } +/** + * Holds if taint can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionTaint(Instruction i1, Instruction i2) { + localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2)) +} + /** * Holds if taint can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. From 20ae183c16437c57ebdc651078caa39375103277 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 14:18:29 +0000 Subject: [PATCH 136/232] C++: Tidy up formatting --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 89f52f174de..04135880129 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -257,18 +257,17 @@ abstract class Declaration extends Locatable, @declaration { private Type getTemplateArgumentType(int index) { class_template_argument(underlyingElement(this), index, unresolveElement(result)) - or + or function_template_argument(underlyingElement(this), index, unresolveElement(result)) - or + or variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } - private Expr getTemplateArgumentValue(int index) { class_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - or + or function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - or + or variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) } } From 16b63b3d01a68b8065f463002f43254aa9cdb369 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 5 Nov 2019 15:45:17 +0100 Subject: [PATCH 137/232] move deferred model to the query where it is used --- .../src/Statements/UseOfReturnlessFunction.ql | 51 +++++++++++++++++++ .../ql/src/semmle/javascript/Promises.qll | 42 --------------- .../TaintTracking/BasicTaintTracking.expected | 1 - .../library-tests/TaintTracking/promise.js | 11 ---- .../Statements/UseOfReturnlessFunction/tst.js | 6 +++ 5 files changed, 57 insertions(+), 54 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index f8f459cc84d..48af33b8e43 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -149,6 +149,57 @@ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { ) } + +/** + * Provides classes for working with various Deferred implementations. + * It is a heuristic. The heuristic assume that a class is a promise defintion + * if the class is called "Deferred" and the method `resolve` is called on an instance. + * + * Removes some false positives in the js/use-of-returnless-function query. + */ +module Deferred { + /** + * An instance of a `Deferred` class. + * E.g. the result from `new Deferred()` or `new $.Deferred()`. + */ + class DeferredInstance extends DataFlow::NewNode { + // Describes both `new Deferred()`, `new $.Deferred` and other variants. + DeferredInstance() { this.getCalleeName() = "Deferred" } + + private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { + t.start() and + result = this + or + exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + } + + DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + } + + /** + * A promise object created by a Deferred constructor + */ + private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { + DeferredPromiseDefinition() { + // hardening of the "Deferred" heuristic: a method call to `resolve`. + exists(ref().getAMethodCall("resolve")) + } + + override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } + } + + /** + * A resolved promise created by a `new Deferred().resolve()` call. + */ + class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { + ResolvedDeferredPromiseDefinition() { + this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") + } + + override DataFlow::Node getValue() { result = getArgument(0) } + } +} + from DataFlow::CallNode call, Function func, string name, string msg where ( diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index ae8554c1a0a..858064e85a0 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -32,48 +32,6 @@ module Bluebird { } } -/** - * Provides classes for working with various Deferred implementations - */ -module Deferred { - class DeferredInstance extends DataFlow::NewNode { - // Describes both `new Deferred()`, `new $.Deferred` and other variants. - DeferredInstance() { this.getCalleeName() = "Deferred" } - - private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { - t.start() and - result = this - or - exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) - } - - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } - } - - /** - * A promise object created by a Deferred constructor - */ - private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { - DeferredPromiseDefinition() { - // hardening of the "Deferred" heuristic: a method call to `resolve`. - exists(ref().getAMethodCall("resolve")) - } - - override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } - } - - /** - * A resolved promise created by a `new Deferred().resolve()` call. - */ - class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { - ResolvedDeferredPromiseDefinition() { - this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") - } - - override DataFlow::Node getValue() { result = getArgument(0) } - } -} - /** * Provides classes for working with the `q` library (https://github.com/kriskowal/q). */ diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 77592a2e855..2722f67d6fd 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,7 +69,6 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | -| promise.js:22:23:22:30 | source() | promise.js:22:7:22:31 | promise ... urce()) | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index d16e57241e8..9714d258df5 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -11,15 +11,4 @@ function closure() { let resolver = Promise.withResolver(); resolver.resolve(source()); sink(resolver.promise); // NOT OK -} - -class Deferred { - -} - -function deferred() { - var promise = new Deferred(); - sink(promise.resolve(source())); // NOT OK - - new Deferred().reject("foo") // <- a reject has to exist. } \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 8a6a44707ed..90a52153dea 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -82,4 +82,10 @@ var baz = [1,2,3].filter(n => {n === 3}) // OK console.log(baz); + + class Deferred { + + } + + new Deferred().resolve(onlySideEffects()); // OK })(); \ No newline at end of file From 3e92d0ffb5cb1a3faf930570b46505f8ef42c53f Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 15:49:42 +0000 Subject: [PATCH 138/232] JavaScript: Remove redundant `--experimental` extractor options. --- .../library-tests/PropWrite/tests.expected | 396 +++++++++--------- .../ql/test/library-tests/PropWrite/tst.js | 1 - .../library-tests/SpreadRestProperties/tst.js | 2 - .../library-tests/TaintTracking/exceptions.js | 2 - .../Templates/templates-revised.js | 2 - .../TrailingFunctionCommas/tst.js | 2 - .../library-tests/frameworks/SQL/mssql1.js | 2 - .../RedeclaredVariable/restprops.js | 2 - .../Declarations/UnusedParameter/restprops.js | 2 - .../Expressions/SelfAssignment/jsdoc.js | 2 - .../LanguageFeatures/IllegalInvocation/tst.js | 2 - .../query-tests/NodeJS/DubiousImport/m.js | 2 - .../test/query-tests/Performance/ReDoS/tst.js | 2 - .../Security/CWE-089/untyped/tst2.js | 2 - 14 files changed, 198 insertions(+), 223 deletions(-) diff --git a/javascript/ql/test/library-tests/PropWrite/tests.expected b/javascript/ql/test/library-tests/PropWrite/tests.expected index 33eff9b0628..beb4916f397 100644 --- a/javascript/ql/test/library-tests/PropWrite/tests.expected +++ b/javascript/ql/test/library-tests/PropWrite/tests.expected @@ -1,55 +1,55 @@ test_getAPropertyRead -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertyReference | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertySource | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | @@ -57,10 +57,10 @@ test_getAPropertySource | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:41:12:42 | {} | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | test_PropWritePropName | classes.ts:3:21:3:20 | constructor() {} | constructor | | classes.ts:4:3:4:24 | instanc ... foo(); | instanceField | @@ -70,123 +70,123 @@ test_PropWritePropName | classes.ts:12:17:12:37 | public ... erField | parameterField | | classes.ts:16:5:16:46 | constru ... {}) {} | constructor | | classes.ts:16:17:16:37 | public ... erField | parameterField | -| tst.js:3:5:3:8 | x: 4 | x | -| tst.js:4:5:6:5 | func: f ... ;\\n } | func | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | f | -| tst.js:12:9:12:8 | constructor() {} | constructor | -| tst.js:13:3:15:3 | static ... x);\\n } | func | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | f | -| tst.js:21:1:21:6 | C.prop | prop | -| tst.js:24:13:24:27 | onClick={click} | onClick | -| tst.js:27:3:27:26 | get x() ... null; } | x | -| tst.js:28:3:28:13 | set y(v) {} | y | -| tst.js:32:5:32:8 | n: 1 | n | +| tst.js:2:5:2:8 | x: 4 | x | +| tst.js:3:5:5:5 | func: f ... ;\\n } | func | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | f | +| tst.js:11:9:11:8 | constructor() {} | constructor | +| tst.js:12:3:14:3 | static ... x);\\n } | func | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | f | +| tst.js:20:1:20:6 | C.prop | prop | +| tst.js:23:13:23:27 | onClick={click} | onClick | +| tst.js:26:3:26:26 | get x() ... null; } | x | +| tst.js:27:3:27:13 | set y(v) {} | y | +| tst.js:31:5:31:8 | n: 1 | n | test_getAPropertyRead2 -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_getAPropertyReference2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_hasPropertyWrite | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:24:12:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:8:3:8 | 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:8:32:8 | 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:8:2:8 | 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:8:31:8 | 1 | test_PropWriteBase | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:3:21:3:20 | this | | classes.ts:8:15:8:35 | public ... erField | classes.ts:8:3:8:2 | this | | classes.ts:12:17:12:37 | public ... erField | classes.ts:12:5:12:4 | this | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:5:16:4 | this | -| tst.js:3:5:3:8 | x: 4 | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:12:1:19:1 | class C ... ;\\n }\\n} | -| tst.js:21:1:21:6 | C.prop | tst.js:21:1:21:1 | C | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:8:24:57 |
    | -| tst.js:27:3:27:26 | get x() ... null; } | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:28:3:28:13 | set y(v) {} | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:32:5:32:8 | n: 1 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:18:38:20 | "b" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:23:38:25 | "c" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:39:13:39:15 | "a" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:40:15:40:17 | "b" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:40:20:40:22 | "c" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:41:18:41:20 | "b" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:42:13:42:15 | "a" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:27:42:29 | "d" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | +| tst.js:2:5:2:8 | x: 4 | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:11:1:18:1 | class C ... ;\\n }\\n} | +| tst.js:20:1:20:6 | C.prop | tst.js:20:1:20:1 | C | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:8:23:57 |
    | +| tst.js:26:3:26:26 | get x() ... null; } | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:27:3:27:13 | set y(v) {} | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:31:5:31:8 | n: 1 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:37:13:37:15 | "a" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:18:37:20 | "b" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:23:37:25 | "c" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:38:20:38:22 | "c" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:39:15:39:17 | "b" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:40:13:40:15 | "a" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:40:18:40:20 | "b" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:27:41:29 | "d" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | test_getAPropertyWrite | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | test_PropWrite | classes.ts:3:21:3:20 | constructor() {} | | classes.ts:4:3:4:24 | instanc ... foo(); | @@ -196,46 +196,46 @@ test_PropWrite | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | -| tst.js:3:5:3:8 | x: 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | -| tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | -| tst.js:24:13:24:27 | onClick={click} | -| tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:28:3:28:13 | set y(v) {} | -| tst.js:32:5:32:8 | n: 1 | -| tst.js:33:5:33:10 | [v]: 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | +| tst.js:2:5:2:8 | x: 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | +| tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | +| tst.js:23:13:23:27 | onClick={click} | +| tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:27:3:27:13 | set y(v) {} | +| tst.js:31:5:31:8 | n: 1 | +| tst.js:32:5:32:10 | [v]: 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | test_getAPropertyWrite2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | test_PropWriteRhs | classes.ts:3:21:3:20 | constructor() {} | classes.ts:3:21:3:20 | () {} | | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:4:19:4:23 | foo() | @@ -246,27 +246,27 @@ test_PropWriteRhs | classes.ts:16:5:16:46 | constru ... {}) {} | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:41:16:42 | {} | -| tst.js:3:5:3:8 | x: 4 | tst.js:3:8:3:8 | 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | tst.js:12:9:12:8 | () {} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | tst.js:16:4:18:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:22:24:26 | click | -| tst.js:32:5:32:8 | n: 1 | tst.js:32:8:32:8 | 1 | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:33:10:33:10 | 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:34:14:34:14 | 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:35:20:35:20 | 4 | +| tst.js:2:5:2:8 | x: 4 | tst.js:2:8:2:8 | 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | tst.js:11:9:11:8 | () {} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | tst.js:15:4:17:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:22:23:26 | click | +| tst.js:31:5:31:8 | n: 1 | tst.js:31:8:31:8 | 1 | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:32:10:32:10 | 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:33:14:33:14 | 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:34:20:34:20 | 4 | +| tst.js:37:13:37:15 | "a" | tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | tst.js:41:27:41:29 | "d" | diff --git a/javascript/ql/test/library-tests/PropWrite/tst.js b/javascript/ql/test/library-tests/PropWrite/tst.js index 8b2ad5aa3e2..99e9d5ffb1c 100644 --- a/javascript/ql/test/library-tests/PropWrite/tst.js +++ b/javascript/ql/test/library-tests/PropWrite/tst.js @@ -1,4 +1,3 @@ -// semmle-extractor-options: --experimental var obj = { x: 4, func: function() { diff --git a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js index cbff84ef9b4..faa017a8bd3 100644 --- a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js +++ b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js @@ -1,4 +1,2 @@ var q = { ...o, x: 42, ...p }; let { x, ...r } = q, { z } = {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TaintTracking/exceptions.js b/javascript/ql/test/library-tests/TaintTracking/exceptions.js index b8946b5603a..98e3e7ce009 100644 --- a/javascript/ql/test/library-tests/TaintTracking/exceptions.js +++ b/javascript/ql/test/library-tests/TaintTracking/exceptions.js @@ -169,5 +169,3 @@ function throwThoughLibrary(xs) { sink(e); // OK - doesn't catch exception from event listener } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Templates/templates-revised.js b/javascript/ql/test/library-tests/Templates/templates-revised.js index 0ca81631fb4..7df488e53f9 100644 --- a/javascript/ql/test/library-tests/Templates/templates-revised.js +++ b/javascript/ql/test/library-tests/Templates/templates-revised.js @@ -1,3 +1 @@ tag `\unvalid escape sequence`; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js index 434f0d0ae61..2257a74aa2a 100644 --- a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js +++ b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js @@ -31,5 +31,3 @@ new h2(23, 42,); x => x; function f4(x = 42,) {} - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js index accf4713d71..39a340ccf83 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js +++ b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js @@ -10,5 +10,3 @@ async () => { // ... error checks } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js index ffab5c80539..44cf825c3cd 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js @@ -1,4 +1,2 @@ var f = ({...p}) => {}; var g = ({...p}) => {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js index 2a7d8c0b4e5..43b3b2ebfb2 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js @@ -1,5 +1,3 @@ function f({ x, ...ys }) { return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js index 0329cdf038d..03bfc0b5573 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js @@ -11,5 +11,3 @@ class C extends Q { this.arg = this.arg; // NOT OK } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js index 6a489653379..3ed85a70934 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js @@ -60,5 +60,3 @@ function invoke(fn) { } invoke(C); invoke(function() {}); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js index ac41c9e8511..9e1c24dfecc 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js @@ -5,5 +5,3 @@ var props = { module.exports = { ...props }; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 9d4e7a7b8de..4839b585eb4 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -84,5 +84,3 @@ var bad16 = /(.|\n)*!/s; // GOOD var good8 = /([\w.]+)*/; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js index 126745e9444..b28ddabc9ca 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js @@ -8,5 +8,3 @@ app.get('/post/:id', async function(req, res) { // NOT OK new sql.Request().query("select * from mytable where id = '" + req.params.id + "'"); }); - -// semmle-extractor-options: --experimental From 8661de11f2ff9c5651899095b3465f11faaf5216 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 14:50:28 +0000 Subject: [PATCH 139/232] docs: update ql terminology --- docs/language/learn-ql/ql-training.rst | 52 +++++++++---------- .../ql-training/cpp/bad-overflow-guard.rst | 24 ++++----- .../ql-training/cpp/control-flow-cpp.rst | 4 +- .../ql-training/cpp/data-flow-cpp.rst | 4 +- .../ql-training/cpp/global-data-flow-cpp.rst | 4 +- .../language/ql-training/cpp/intro-ql-cpp.rst | 38 +++++++------- .../cpp/program-representation-cpp.rst | 10 ++-- docs/language/ql-training/cpp/snprintf.rst | 2 +- docs/language/ql-training/index.rst | 4 +- .../ql-training/java/apache-struts-java.rst | 2 +- .../java/global-data-flow-java.rst | 2 +- .../ql-training/java/intro-ql-java.rst | 36 ++++++------- .../java/program-representation-java.rst | 2 +- .../ql-training/java/query-injection-java.rst | 20 +++---- .../slide-snippets/abstract-syntax-tree.rst | 10 ++-- .../ql-training/slide-snippets/info.rst | 33 ------------ .../slide-snippets/intro-ql-general.rst | 16 +++--- 17 files changed, 115 insertions(+), 148 deletions(-) delete mode 100644 docs/language/ql-training/slide-snippets/info.rst diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index 66afa06d754..757de7daed6 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -1,19 +1,19 @@ -QL training and variant analysis examples -######################################### +CodeQL training and variant analysis examples +============================================= QL and variant analysis -======================= +----------------------- `Variant analysis `__ is the process of using a known vulnerability as a seed to find similar problems in your code. Security engineers typically perform variant analysis to identify possible vulnerabilities and to ensure that these threats are properly fixed across multiple code bases. -`QL `__ is Semmle's variant analysis engine, and it is also the technology that underpins LGTM, Semmle's community driven security analysis platform. Together, QL and LGTM provide continuous monitoring and scalable variant analysis for your projects, even if you don’t have your own team of dedicated security engineers. You can read more about using QL and LGTM in variant analysis in the `Semmle blog `__. +`CodeQL `__ is the code analysis engine that underpins LGTM, Semmle's community driven security analysis platform. Together, CodeQL and LGTM provide continuous monitoring and scalable variant analysis for your projects, even if you don’t have your own team of dedicated security engineers. You can read more about using CodeQL and LGTM in variant analysis in the `Semmle blog `__. -The QL language is easy to learn, and exploring code using QL is the most efficient way to perform variant analysis. +CodeQL is easy to learn, and exploring code using CodeQL is the most efficient way to perform variant analysis. Learning QL for variant analysis -================================ +-------------------------------- -Start learning how to use QL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on the QL language, QL libraries, or an example variant discovered using QL. +Start learning how to use CodeQL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on CodeQL, its libraries, or an example variant discovered using CodeQL. .. |arrow-l| unicode:: U+2190 @@ -24,7 +24,7 @@ Start learning how to use QL in variant analysis for a specific language by look When you have selected a presentation, use |arrow-r| and |arrow-l| to navigate between slides. Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode. -The presentations contain a number of QL query examples. +The presentations contain a number of query examples. We recommend that you download `QL for Eclipse `__ and import the example snapshot for each presentation so that you can find the bugs mentioned in the slides. @@ -32,35 +32,35 @@ We recommend that you download `QL for Eclipse `__–an introduction to variant analysis and QL for C/C++ programmers. +- `Introduction to variant analysis: CodeQL for C/C++ <../ql-training/cpp/intro-ql-cpp.html>`__–an introduction to variant analysis and CodeQL for C/C++ programmers. - `Example: Bad overflow guard <../ql-training/cpp/bad-overflow-guard.html>`__–an example of iterative query development to find bad overflow guards in a C++ project. -- `Program representation: QL for C/C++ <../ql-training/cpp/program-representation-cpp.html>`__–information on how QL analysis represents C/C++ programs. -- `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using QL, including an example demonstrating how to develop a query to find a real CVE. +- `Program representation: CodeQL for C/C++ <../ql-training/cpp/program-representation-cpp.html>`__–information on how CodeQL analysis represents C/C++ programs. +- `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: snprintf overflow <../ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query. -- `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using QL. -- `Analyzing control flow: QL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. +- `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL. +- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. -QL and variant analysis for Java --------------------------------- +CodeQL and variant analysis for Java +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `Introduction to variant analysis: QL for Java <../ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and QL for Java programmers. +- `Introduction to variant analysis: CodeQL for Java <../ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and CodeQL for Java programmers. - `Example: Query injection <../ql-training/java/query-injection-java.html>`__–an example of iterative query development to find unsanitized SPARQL injections in a Java project. -- `Program representation: QL for Java <../ql-training/java/program-representation-java.html>`__–information on how QL analysis represents Java programs. -- `Introduction to local data flow <../ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using QL, including an example demonstrating how to develop a query to find a real CVE. +- `Program representation: CodeQL for Java <../ql-training/java/program-representation-java.html>`__–information on how CodeQL analysis represents Java programs. +- `Introduction to local data flow <../ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: Apache Struts <../ql-training/java/apache-struts-java.html>`__–an example demonstrating how to develop a data flow query. -- `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using QL. +- `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL. More resources --------------- +~~~~~~~~~~~~~~ -- If you are completely new to QL, look at our introductory topics in :ref:`Getting started `. -- To find more detailed information about how to write QL queries for specific languages, visit the links in :ref:`Writing QL queries `. -- To read more about how QL queries have been used in Semmle's security research, and to read about new QL developments, visit the `Semmle blog `__. +- If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. +- To find more detailed information about how to write CodeQL queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. +- To read more about how CodeQL queries have been used in Semmle's security research, and to read about new CodeQL developments, visit the `Semmle blog `__. - Find more examples of queries written by Semmle's own security researchers in the `Semmle Demos repository `__ on GitHub. diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 12f35440906..5e9fbcfc700 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -2,7 +2,7 @@ Example: Bad overflow guard =========================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -127,13 +127,13 @@ This happens even though the overflow check passed! .. rst-class:: background2 -Developing a QL query -===================== +Developing a CodeQL query +========================= Finding bad overflow guards -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================== Let’s look for overflow guards of the form ``v + b < v``, using the classes ``AddExpr``, ``Variable`` and ``RelationalOperation`` from the ``cpp`` library. @@ -153,10 +153,10 @@ Let’s look for overflow guards of the form ``v + b < v``, using the classes - a ``RelationalOperation``: the overflow comparison check. - a ``Variable``: used as an argument to both the addition and comparison. - - The ``where`` part of the query ties these three QL variables together using `predicates `__ defined in the `standard QL for C/C++ library `__. + - The ``where`` part of the query ties these three variables together using `predicates `__ defined in the `standard CodeQL for C/C++ library `__. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================= We want to ensure the operands being added have size less than 4 bytes. @@ -180,8 +180,8 @@ We can get the size (in bytes) of a type using the ``getSize()`` method. - We therefore write a helper predicate for small expressions. - This predicate effectively represents the set of all expressions in the database where the size of the type of the expression is less than 4 bytes, that is, less than 32-bits. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================== We can ensure the operands being added have size less than 4 bytes, using our new predicate. @@ -216,8 +216,8 @@ Now our query becomes: - The “range” part, ``op = a.getAnOperand()``, restricts ``op`` to being one of the two operands to the addition. - The “condition” part, ``isSmall(op)``, says that the ``forall`` holds only if the condition (that the ``op`` is small) holds for everything in the range–that is, both the arguments to the addition. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================= Sometimes the result of the addition is cast to a small type of size less than 4 bytes, preventing automatic widening. We don’t want our query to flag these instances. diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index ea8e2c1b158..a8171a44b5d 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -2,7 +2,7 @@ Analyzing control flow ====================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -226,7 +226,7 @@ A ``GuardCondition`` is a ``Boolean`` condition that controls one or more basic Further materials ================= -- QL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html +- CodeQL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html - API reference: https://help.semmle.com/qldoc/cpp .. rst-class:: end-slide diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 2b020499eb0..5377d8d52d1 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -86,9 +86,9 @@ Write a query that flags ``printf`` calls where the format argument is not a ``S .. note:: - This first query is about finding places where the format specifier is not a constant string. In QL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. + This first query is about finding places where the format specifier is not a constant string. In CodeQL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. - The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the QL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. + The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the CodeQL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. Meh... ====== diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 6033581ffc3..bc048ac59f4 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -2,7 +2,7 @@ Introduction to global data flow ================================ -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -77,7 +77,7 @@ The library class ``SecurityOptions`` provides a (configurable) model of what co .. note:: - We first define what it means to be a *source* of tainted data for this particular problem. In this case, what we care about is whether the format string can be provided by an external user to our application or service. As there are many such ways external data could be introduced into the system, the standard QL libraries for C/C++ include an extensible API for modeling user input. In this case, we will simply use the predefined set of *user inputs*, which includes arguments provided to command line applications. + We first define what it means to be a *source* of tainted data for this particular problem. In this case, what we care about is whether the format string can be provided by an external user to our application or service. As there are many such ways external data could be introduced into the system, the standard CodeQL libraries for C/C++ include an extensible API for modeling user input. In this case, we will simply use the predefined set of *user inputs*, which includes arguments provided to command line applications. Defining sinks (exercise) diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 82eb62a3ba8..dddc86ca77f 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -2,7 +2,7 @@ Introduction to variant analysis ================================ -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -56,14 +56,14 @@ Oops .. note:: - Here’s a simple (artificial) bug, which we’ll develop a QL query to catch. + Here’s a simple (artificial) bug, which we’ll develop a query to catch. This function writes a value to a given location in an array, first trying to do a bounds check to validate that the location is within bounds. However, the return statement has been commented out, leaving a redundant if statement and no bounds checking. This case can act as our “patient zero” in the variant analysis game. -A simple QL query -================= +A simple CodeQL query +===================== .. literalinclude:: ../query-examples/cpp/empty-if-cpp.ql :language: ql @@ -72,9 +72,9 @@ A simple QL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `QL query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `C/C++ standard QL library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL for C/C++ standard library `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -97,8 +97,8 @@ A simple QL query -Structure of a QL query -======================= +Structure of a query +==================== A **query file** has the extension ``.ql`` and contains a **query clause**, and optionally **predicates**, **classes**, and **modules**. @@ -110,14 +110,14 @@ Each query library also implicitly defines a module. .. note:: - QL queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. + Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary query file in the background. - Parts of queries can be lifted into `QL library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. -Predicates in QL -================ +Predicates +========== A predicate allows you to pull out and name parts of a query. @@ -135,14 +135,14 @@ A predicate allows you to pull out and name parts of a query. .. note:: - A QL predicate takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be recursive, simply by referring to themselves (directly or indirectly). + A `predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes in QL -============= +Classes +======= -A QL class allows you to name a set of values and define (member) predicates on them. +A class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -162,8 +162,8 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in QL continued -======================= +Classes continued +================= .. container:: column-left @@ -198,7 +198,7 @@ Iterative query refinement .. note:: - QL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. + CodeQL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. As an exercise, refine the redundant-if query based on the observation that if the if-statement has an “else” clause, then even if the body of the “then” clause is empty, it’s not actually redundant. diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 1850e3e5671..b21677fccab 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -2,7 +2,7 @@ Program representation ====================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -25,8 +25,8 @@ Agenda .. resume slides -AST QL classes -============== +AST classes +=========== Important AST classes include: @@ -66,9 +66,9 @@ Working with variables Working with functions ====================== -Functions are represented by the Function QL class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. +Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by QL class Call and its subclasses: +Calls to functions are modeled by class Call and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 77e46933fcb..dafebc4a720 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -2,7 +2,7 @@ Exercise: ``snprintf`` overflow =============================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 0cc4ca9b024..309fe92c052 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,5 +1,5 @@ -QL training and variant analysis examples -========================================= +CodeQL training and variant analysis examples +============================================= .. container:: semmle-logo diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 7fcd2e003cd..5c27ec73979 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -67,7 +67,7 @@ RCE in Apache Struts Finding the RCE yourself ======================== -#. Create a QL class to find the interface ``org.apache.struts2.rest.handler.ContentTypeHandler`` +#. Create a class to find the interface ``org.apache.struts2.rest.handler.ContentTypeHandler`` **Hint**: Use predicate ``hasQualifiedName(...)`` diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 665899f8459..f43c31e0f4f 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -2,7 +2,7 @@ Introduction to global data flow ================================ -QL for Java +CodeQL for Java .. container:: semmle-logo diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 392c18309cb..f80f878492d 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -2,7 +2,7 @@ Introduction to variant analysis ================================ -QL for Java +CodeQL for Java .. container:: semmle-logo @@ -56,14 +56,14 @@ Oops .. note:: - Here’s a simple (artificial) bug, which we’ll develop a QL query to catch. + Here’s a simple (artificial) bug, which we’ll develop a query to catch. This function writes a value to a given location in an array, first trying to do a bounds check to validate that the location is within bounds. However, the return statement has been commented out, leaving a redundant if statement and no bounds checking. This case can act as our “patient zero” in the variant analysis game. -A simple QL query -================= +A simple CodeQL query +===================== .. literalinclude:: ../query-examples/java/empty-if-java.ql :language: ql @@ -72,9 +72,9 @@ A simple QL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `QL query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `Java standard QL library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL for Java library `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -96,8 +96,8 @@ A simple QL query Finally, we select a location, at which to report the problem, and a message, to explain what the problem is. -Structure of a QL query -======================= +Structure of a query +===================== A **query file** has the extension ``.ql`` and contains a **query clause**, and optionally **predicates**, **classes**, and **modules**. @@ -109,14 +109,14 @@ Each query library also implicitly defines a module. .. note:: - QL queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. + Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. - Parts of queries can be lifted into `QL library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. -Predicates in QL -================ +Predicates +========== A predicate allows you to pull out and name parts of a query. @@ -134,15 +134,15 @@ A predicate allows you to pull out and name parts of a query. .. note:: - A `QL predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). + A `predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes in QL -============= +Classes +======= -A QL class allows you to name a set of values and define (member) predicates on them. +A class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -162,7 +162,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in QL continued +Classes in continued ======================= .. container:: column-left @@ -197,7 +197,7 @@ Iterative query refinement .. note:: - QL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. + CodeQL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. As an exercise, refine the redundant-if query based on the observation that if the if-statement has an “else” clause, then even if the body of the “then” clause is empty, it’s not actually redundant. diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index d090c30aebe..ef078b53562 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -2,7 +2,7 @@ Program representation ====================== -QL for Java +CodeQL for Java .. container:: semmle-logo diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index 67f7fe21a76..b3ef7d7e182 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -2,7 +2,7 @@ Example: Query injection ======================== -QL for Java +CodeQL for Java .. container:: semmle-logo @@ -65,13 +65,13 @@ SPARQL injection .. rst-class:: background2 -Developing a QL query -====================== +Developing a query +=================== Finding a query concatenation -QL query: find SPARQL methods -============================= +CodeQL query: find SPARQL methods +================================= Let’s start by looking for calls to methods with names of the form ``sparql*Query``, using the classes ``Method`` and ``MethodAccess`` from the Java library. @@ -88,10 +88,10 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu - a ``MethodAccess``: the call to a SPARQL query method - a ``Method``: the SPARQL query method. - - The ``where`` part of the query ties these three QL variables together using `predicates `__ defined in the `standard QL for Java library `__. + - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL for Java library `__. -QL query: find string concatenation -=================================== +CodeQL query: find string concatenation +======================================= - We now need to define what would make these API calls unsafe. - A simple heuristic would be to look for string concatenation used in the query argument. @@ -113,8 +113,8 @@ Looking at autocomplete suggestions, we see that we can get the type of an expre - We therefore write a helper predicate for finding string concatenation. - This predicate effectively represents the set of all ``add`` expressions in the database where the type of the expression is ``TypeString`` - that is, the addition produces a ``String`` value. -QL query: SPARQL injection -========================== +CodeQL query: SPARQL injection +============================== We can now combine our predicate with the existing query. Note that we do not need to specify that the argument of the method access is an ``AddExpr`` - this is implied by the ``isStringConcat`` requirement. diff --git a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst index c640aa7a16a..6a26b5c74a4 100644 --- a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst +++ b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst @@ -35,9 +35,9 @@ The basic representation of an analyzed program is an *abstract syntax tree (AST .. note:: - When writing queries in QL it is important to have in mind the underlying representation of the program which is stored in the database. Typically queries make use of the “AST” representation of the program - a tree structure where program elements are nested within other program elements. + When writing queries it is important to have in mind the underlying representation of the program which is stored in the database. Typically queries make use of the “AST” representation of the program - a tree structure where program elements are nested within other program elements. - The following topics contain overviews of the important AST classes and QL libraries for C/C++, C#, and Java: + The following topics contain overviews of the important AST classes and CodeQL libraries for C/C++, C#, and Java: - `Introducing the C/C++ libraries `__ - `Introducing the C# libraries `__ @@ -47,19 +47,19 @@ The basic representation of an analyzed program is an *abstract syntax tree (AST Database representations of ASTs ================================ -AST nodes and other program elements are encoded in the database as *entity values*. Entities are implemented as integers, but in QL they are opaque - all one can do with them is to check their equality. +AST nodes and other program elements are encoded in the database as *entity values*. Entities are implemented as integers, but in QL they are opaque---all one can do with them is to check their equality. Each entity belongs to an entity type. Entity types have names starting with “@” and are defined in the database schema (not in QL). Properties of AST nodes and their relationships to each other are encoded by database relations, which are predicates defined in the database (not in QL). -Entity types are rarely used directly, the usual pattern is to define a QL class that extends the type and exposes properties of its entities through member predicates. +Entity types are rarely used directly, the usual pattern is to define a class that extends the type and exposes properties of its entities through member predicates. .. note:: ASTs are a typical example of the kind of data representation one finds in object-oriented programming, with data-carrying nodes that reference each other. At first glance, QL, which can only work with atomic values, does not seem to be well suited for working with this kind of data. However, ultimately all that we require of the nodes in an AST is that they have an identity. The relationships among nodes, usually implemented by reference-valued object fields in other languages, can just as well (and arguably more naturally) be represented as relations over nodes. Attaching data (such as strings or numbers) to nodes can also be represented with relations over nodes and primitive values. All we need is a way for relations to reference nodes. This is achieved in QL (as in other database languages) by means of *entity values* (or entities, for short), which are opaque atomic values, implemented as integers under the hood. - It is the job of the extractor to create entity values for all AST nodes and populate database relations that encode the relationship between AST nodes and any values associated with them. These relations are *extensional*, that is, explicitly stored in the database, unlike the relations described by QL predicates, which we also refer to as *intensional* relations. Entity values belong to *entity types*, whose name starts with “@” to set them apart from primitive types and classes. + It is the job of the extractor to create entity values for all AST nodes and populate database relations that encode the relationship between AST nodes and any values associated with them. These relations are *extensional*, that is, explicitly stored in the database, unlike the relations described by predicates, which we also refer to as *intensional* relations. Entity values belong to *entity types*, whose name starts with “@” to set them apart from primitive types and classes. The interface between entity types and extensional relations on the one hand and QL predicates and classes on the other hand is provided by the *database schema*, which defines the available entity types and the schema of each extensional relation, that is, how many columns the relation has, and which entity type or primitive type the values in each column come from. QL programs can refer to entity types and extensional relations just as they would refer to QL classes and predicates, with the restriction that entity types cannot be directly selected in a ``select`` clause, since they do not have a well-defined string representation. diff --git a/docs/language/ql-training/slide-snippets/info.rst b/docs/language/ql-training/slide-snippets/info.rst deleted file mode 100644 index 583a456207b..00000000000 --- a/docs/language/ql-training/slide-snippets/info.rst +++ /dev/null @@ -1,33 +0,0 @@ -Information -=========== - -To try the examples in this presentation we recommend you download `QL for Eclipse `__. - -**QL language resources** - -- If you are new to QL, try the QL language tutorials at `Learning CodeQL `__. -- To learn more about the main features of QL, try looking at the `QL language handbook `__. -- For further information about writing queries in QL, see `Writing QL queries `__. - -**QL queries** - -The QL queries included in the latest Semmle release are open source. View them in the `semmle/ql repository `__. - -**Extra information** - -.. |arrow-l| unicode:: U+2190 - -.. |arrow-r| unicode:: U+2192 - -- Press |arrow-l| and |arrow-r| to navigate between slides -- Pressing **p** toggles between the slide and any extra notes (where they're available) -- Pressing **f** toggles full screen viewing on/off - -.. note:: - - To run the queries featured in this training presentation, we recommend you download the free-to-use `QL for Eclipse plugin `__. - - This plugin allows you to locally access the latest features of QL, including the standard QL libraries and queries. It also provides standard IDE features such as syntax highlighting, jump-to-definition, and tab completion. - - When you have setup QL for Eclipse we recommend increasing the “Memory for running queries” from the default setting of 4096MB to 8192MB, to ensure that all the queries complete quickly. - \ No newline at end of file diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index f0c00c131fc..6fa68c7243e 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -67,9 +67,9 @@ Complete text of the analysis (nothing left out!): .. note:: - Once the mission critical bug was discovered on Curiosity, JPL contacted Semmle for help discovering whether variants of the problem might exist elsewhere in the Curiosity control software. In 20 minutes, research engineers from Semmle produced a QL query and shared it with the JPL team. It finds all functions that are passed an array as an argument whose size is smaller than expected. + Once the mission critical bug was discovered on Curiosity, JPL contacted Semmle for help discovering whether variants of the problem might exist elsewhere in the Curiosity control software. In 20 minutes, research engineers from Semmle produced a CodeQL query and shared it with the JPL team. It finds all functions that are passed an array as an argument whose size is smaller than expected. - (The goal here is not to fully understand the QL, but to illustrate the power of the language and its standard libraries.) + (The goal here is not to fully understand the query, but to illustrate the power of the language and its standard libraries.) Find all instances! @@ -105,16 +105,16 @@ Analysis overview Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. - Once the extraction finishes, all this information is collected into a single `snapshot database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. + Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. - Queries are written in `QL `__ and usually depend on one or more of the `standard QL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a snapshot database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. + Queries are written in `QL `__ and usually depend on one or more of the `standard CodeQL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. Query results can be interpreted and presented in a variety of ways, including displaying them in an `IDE plugin `__ such as QL for Eclipse, or in a web dashboard as on `LGTM `__. Introducing QL ============== -QL is the query language running all Semmle analysis. +QL is the query language running all CodeQL analysis. QL is: @@ -126,12 +126,12 @@ QL is: .. note:: - QL is the high-level, object-oriented logic language that underpins all of Semmle’s libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. + QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. The key features of QL are: - All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables. - The language is declarative–the user focuses on stating what they would like to find, and leaves the details of how to evaluate the query to the engine. - - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard QL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. + - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. - You can start writing QL and running QL queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__ equipped with a QL plugin or extension. + You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__. From 69d7baa9bcfc4ac4ce72459e92bc66436197859c Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 15:35:18 +0000 Subject: [PATCH 140/232] docs: update snapshot terminology --- docs/language/ql-training/cpp/bad-overflow-guard.rst | 8 ++++---- docs/language/ql-training/cpp/control-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/data-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/global-data-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/intro-ql-cpp.rst | 6 +++--- .../ql-training/cpp/program-representation-cpp.rst | 4 ++-- docs/language/ql-training/cpp/snprintf.rst | 6 +++--- docs/language/ql-training/java/apache-struts-java.rst | 6 +++--- docs/language/ql-training/java/data-flow-java.rst | 6 +++--- docs/language/ql-training/java/global-data-flow-java.rst | 6 +++--- docs/language/ql-training/java/intro-ql-java.rst | 6 +++--- docs/language/ql-training/java/query-injection-java.rst | 6 +++--- .../ql-training/slide-snippets/abstract-syntax-tree.rst | 2 +- .../{snapshot-note.rst => database-note.rst} | 2 +- .../ql-training/slide-snippets/global-data-flow.rst | 6 +++--- .../ql-training/slide-snippets/intro-ql-general.rst | 6 +++--- .../ql-training/slide-snippets/local-data-flow.rst | 4 ++-- 17 files changed, 46 insertions(+), 46 deletions(-) rename docs/language/ql-training/slide-snippets/{snapshot-note.rst => database-note.rst} (66%) diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 5e9fbcfc700..6937e9a1a4f 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `ChakraCore snapshot `__ +- `ChakraCore database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides @@ -233,4 +233,4 @@ The final query .. literalinclude:: ../query-examples/cpp/bad-overflow-guard-3.ql :language: ql -This query finds a single result in our historic snapshot, which was `a genuine bug in ChakraCore `__. +This query finds a single result in our historic database, which was `a genuine bug in ChakraCore `__. diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index a8171a44b5d..4e6ebbf4292 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -18,7 +18,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `ChakraCore snapshot `__ +- `ChakraCore database `__ .. note:: @@ -26,9 +26,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 5377d8d52d1..cb7ed7b5133 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `dotnet/coreclr snapshot `__ +- `dotnet/coreclr database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index bc048ac59f4..5a5e93aafda 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `dotnet/coreclr snapshot `__ +- `dotnet/coreclr database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index dddc86ca77f..e7d4b318b25 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `exiv2 snapshot `__ +- `exiv2 database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index b21677fccab..077b36520f6 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -107,7 +107,7 @@ Working with macros #define square(x) x*x y = square(y0), z = square(z0) -is represented in the snapshot database as: +is represented in the CodeQL database database as: - A Macro entity representing the text of the *head* and *body* of the macro - Assignment nodes, representing the two assignments after preprocessing @@ -121,4 +121,4 @@ Useful predicates on ``Element``: ``isInMacroExpansion()``, ``isAffectedByMacro( .. note:: - The snapshot also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file + The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index dafebc4a720..26c54708c0a 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `rsyslog snapshot `__ +- `rsyslog database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 5c27ec73979..73d0122b7ea 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -20,7 +20,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -28,9 +28,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index be9ba98456e..0b9026aadfb 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `VIVO Vitro snapshot `__ +- `VIVO Vitro database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index f43c31e0f4f..062ce30b04c 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f80f878492d..393e35cf5a8 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index b3ef7d7e182..dc345d3b39c 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `VIVO Vitro snapshot `__ +- `VIVO Vitro database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst index 6a26b5c74a4..aaa2cd23d71 100644 --- a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst +++ b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst @@ -63,7 +63,7 @@ Entity types are rarely used directly, the usual pattern is to define a class th The interface between entity types and extensional relations on the one hand and QL predicates and classes on the other hand is provided by the *database schema*, which defines the available entity types and the schema of each extensional relation, that is, how many columns the relation has, and which entity type or primitive type the values in each column come from. QL programs can refer to entity types and extensional relations just as they would refer to QL classes and predicates, with the restriction that entity types cannot be directly selected in a ``select`` clause, since they do not have a well-defined string representation. - For example, the database schemas for C/++, C#, and Java snapshot databases are here: + For example, the database schemas for C/++, C#, and Java CodeQL databases are here: - https://github.com/Semmle/ql/blob/master/cpp/ql/src/semmlecode.cpp.dbscheme - https://github.com/Semmle/ql/blob/master/csharp/ql/src/semmlecode.csharp.dbscheme diff --git a/docs/language/ql-training/slide-snippets/snapshot-note.rst b/docs/language/ql-training/slide-snippets/database-note.rst similarity index 66% rename from docs/language/ql-training/slide-snippets/snapshot-note.rst rename to docs/language/ql-training/slide-snippets/database-note.rst index 4a32243211b..af6dce23728 100644 --- a/docs/language/ql-training/slide-snippets/snapshot-note.rst +++ b/docs/language/ql-training/slide-snippets/database-note.rst @@ -1 +1 @@ -Note that results generated in the query console are likely to differ to those generated in the QL plugin as LGTM.com analyzes the most recent revisions of each project that has been added–the snapshot available to download above is based on an historical version of the codebase. \ No newline at end of file +Note that results generated in the query console are likely to differ to those generated in the QL plugin as LGTM.com analyzes the most recent revisions of each project that has been added–the CodeQL database available to download above is based on an historical version of the codebase. \ No newline at end of file diff --git a/docs/language/ql-training/slide-snippets/global-data-flow.rst b/docs/language/ql-training/slide-snippets/global-data-flow.rst index f18dc22d178..6cb52af0f84 100644 --- a/docs/language/ql-training/slide-snippets/global-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/global-data-flow.rst @@ -17,15 +17,15 @@ Global data flow and taint tracking - Recap: - - Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a snapshot - - Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a snapshot + - Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a CodeQL database + - Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a CodeQL database - For global data flow (and taint tracking), we must therefore provide restrictions to ensure the problem is tractable. - Typically, this involves specifying the *source* and *sink*. .. note:: - As we mentioned in the previous slide deck, while local data flow is feasible to compute for all functions in a snapshot, global data flow is not. This is because the number of paths becomes exponentially larger for global data flow. + As we mentioned in the previous slide deck, while local data flow is feasible to compute for all functions in a CodeQL database, global data flow is not. This is because the number of paths becomes exponentially larger for global data flow. The global data flow (and taint tracking) avoids this problem by requiring that the query author specifies which ``sources`` and ``sinks`` are applicable. This allows the implementation to compute paths between the restricted set of nodes, rather than the full graph. diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index 6fa68c7243e..d559c5bbeb7 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -105,7 +105,7 @@ Analysis overview Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. - Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. + Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. Queries are written in `QL `__ and usually depend on one or more of the `standard CodeQL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. @@ -121,7 +121,7 @@ QL is: - a **logic** language based on first-order logic - a **declarative** language without side effects - an **object-oriented** language -- a **query** language working on a read-only snapshot database +- a **query** language working on a read-only CodeQL database database - equipped with rich standard libraries **for program analysis** .. note:: @@ -134,4 +134,4 @@ QL is: - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. - You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__. + You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download CodeQL databases from LGTM.com to query locally, by `running queries in your IDE `__. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 8a0eeac6374..068dfc9170a 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -61,8 +61,8 @@ Data flow graphs Local vs global data flow ========================= -- Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a snapshot -- Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a snapshot +- Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a CodeQL database +- Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a CodeQL database - Different APIs, so discussed separately - This slide deck focuses on the former From 2d00ca5773b7773184b3beabbd3799876d3fc06b Mon Sep 17 00:00:00 2001 From: james Date: Fri, 4 Oct 2019 09:18:19 +0100 Subject: [PATCH 141/232] docs: semmle logo (cherry picked from commit 4a8e8fa0de4470aaeed94357f70b54b68c0b84a7) --- .../static/theme/css/default.css | 18 +-- .../_static-training/title-slide.svg | 149 +----------------- .../ql-training/cpp/bad-overflow-guard.rst | 4 - .../ql-training/cpp/control-flow-cpp.rst | 4 - .../ql-training/cpp/data-flow-cpp.rst | 4 - .../ql-training/cpp/global-data-flow-cpp.rst | 4 - .../language/ql-training/cpp/intro-ql-cpp.rst | 4 - .../cpp/program-representation-cpp.rst | 4 - docs/language/ql-training/cpp/snprintf.rst | 4 - docs/language/ql-training/index.rst | 4 - .../ql-training/java/apache-struts-java.rst | 4 - .../ql-training/java/data-flow-java.rst | 4 - .../java/global-data-flow-java.rst | 4 - .../ql-training/java/intro-ql-java.rst | 4 - .../java/program-representation-java.rst | 4 - .../ql-training/java/query-injection-java.rst | 4 - docs/language/ql-training/template.rst | 4 - 17 files changed, 4 insertions(+), 223 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 2c05ea5e93b..4f706120747 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -1300,13 +1300,13 @@ aside.gdbar img { .title-slide hgroup h1 { font-size: 2em; line-height: 1.4; - /*letter-spacing: -3px;*/ color: white; margin: auto; display: block; position: absolute; top: 0; bottom: 10%; + left: 1.25em; height: 0; } /* line 898, ../scss/default.scss */ @@ -1430,31 +1430,19 @@ hgroup .pre { color: #5c31ff; } -/* title slide (deck title, subtitle, semmle logo)*/ +/* title slide (deck title, subtitle)*/ .title-slide { background-image: url("../../title-slide.svg"); background-size: cover; } -.semmle-logo sup { - vertical-align: super; - font-size: 0.3em; - font-weight: 100; -} - -.title-slide .semmle-logo { - color: white; - font-size: 1.2em; - position: absolute; - top: 10%; -} - .title-slide p { color: white; font-size: 1em; position: absolute; bottom: 30%; + left: 2.6em; } .title-slide hgroup .pre { diff --git a/docs/language/ql-training/_static-training/title-slide.svg b/docs/language/ql-training/_static-training/title-slide.svg index 6f9a19f4a1b..13eb2d34fef 100644 --- a/docs/language/ql-training/_static-training/title-slide.svg +++ b/docs/language/ql-training/_static-training/title-slide.svg @@ -1,148 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 6937e9a1a4f..dceeec3320f 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -4,10 +4,6 @@ Example: Bad overflow guard CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index 4e6ebbf4292..3fddc3f8072 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -4,10 +4,6 @@ Analyzing control flow CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Include information slides here .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index cb7ed7b5133..e78e8e86220 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -4,10 +4,6 @@ Introduction to data flow Finding string formatting vulnerabilities in C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 5a5e93aafda..aaa567e7a8e 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -3,10 +3,6 @@ Introduction to global data flow ================================ CodeQL for C/C++ - -.. container:: semmle-logo - - Semmle :sup:`TM` .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index e7d4b318b25..cbe29e6c520 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -4,10 +4,6 @@ Introduction to variant analysis CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 077b36520f6..3c062089428 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -4,10 +4,6 @@ Program representation CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 26c54708c0a..c15bf74d286 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -4,10 +4,6 @@ Exercise: ``snprintf`` overflow CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 309fe92c052..021bb58d3c4 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,10 +1,6 @@ CodeQL training and variant analysis examples ============================================= -.. container:: semmle-logo - - Semmle :sup:`TM` - .. toctree:: :glob: :maxdepth: 1 diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 73d0122b7ea..be071d41562 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -8,10 +8,6 @@ Exercise: Apache Struts CVE-2017-9805 -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index 0b9026aadfb..93ccc87b7d1 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -2,10 +2,6 @@ Introduction to data flow ========================= -.. container:: semmle-logo - - Semmle :sup:`TM` - Finding SPARQL injection vulnerabilities in Java .. rst-class:: setup diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 062ce30b04c..9edacde93c3 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -4,10 +4,6 @@ Introduction to global data flow CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 393e35cf5a8..f7afe713c4a 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -4,10 +4,6 @@ Introduction to variant analysis CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index ef078b53562..ba9b1a9d80d 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -4,10 +4,6 @@ Program representation CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index dc345d3b39c..a5b46eabda5 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -4,10 +4,6 @@ Example: Query injection CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/template.rst b/docs/language/ql-training/template.rst index 0cce4a11435..21c5abef144 100644 --- a/docs/language/ql-training/template.rst +++ b/docs/language/ql-training/template.rst @@ -27,10 +27,6 @@ Template slide deck Second subheading -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Set up slide. Include link to QL4E snapshots required for examples .. rst-class:: setup From 0b6592f650421c5b5ff001674042577e038367bb Mon Sep 17 00:00:00 2001 From: james Date: Mon, 30 Sep 2019 11:51:17 +0100 Subject: [PATCH 142/232] docs: version number and small css tweaks (cherry picked from commit ff78feeeeaec99bdf779242c33e25f57c7bcab29) --- .../slides-semmle-2/static/theme/css/default.css | 6 ++++-- docs/language/ql-training/conf.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 4f706120747..3f8a89c6555 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -485,6 +485,7 @@ ul { margin-left: 2.2em; margin-bottom: 1em; position: relative; + width: 90%; } /* line 300, ../scss/default.scss */ ul li { @@ -1452,6 +1453,7 @@ hgroup .pre { .subheading { position: absolute; top: 62.5%; + left: 0; } .subheading p { @@ -1557,7 +1559,7 @@ p.first.admonition-title { text-align: left; font-size: 0.8em; width: 100%; - overflow: scroll; + overflow: auto; border: 1px solid black; } @@ -1596,7 +1598,7 @@ p.first.admonition-title { display: block; position: fixed; top: 0; - right: -1%; + right: 0; font-size: 1.2em; } diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index de712cd06a4..8f8a13569b5 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -86,9 +86,9 @@ htmlhelp_basename = 'QL training' # built documents. # # The short X.Y version. -version = u'1.21' +version = u'1.22' # The full version, including alpha/beta/rc tags. -release = u'1.21' +release = u'1.22' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' From 488ce158887ed174a854730d81dd353c962a5c1d Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Tue, 5 Nov 2019 19:57:24 +0000 Subject: [PATCH 143/232] Apply suggestions from code review Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/ql-training.rst | 12 ++++++------ docs/language/ql-training/cpp/data-flow-cpp.rst | 4 ++-- docs/language/ql-training/cpp/intro-ql-cpp.rst | 2 +- .../ql-training/cpp/program-representation-cpp.rst | 6 +++--- docs/language/ql-training/java/intro-ql-java.rst | 2 +- .../ql-training/slide-snippets/intro-ql-general.rst | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index 757de7daed6..4187ae621b5 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -1,8 +1,8 @@ CodeQL training and variant analysis examples ============================================= -QL and variant analysis ------------------------ +CodeQL and variant analysis +--------------------------- `Variant analysis `__ is the process of using a known vulnerability as a seed to find similar problems in your code. Security engineers typically perform variant analysis to identify possible vulnerabilities and to ensure that these threats are properly fixed across multiple code bases. @@ -10,8 +10,8 @@ QL and variant analysis CodeQL is easy to learn, and exploring code using CodeQL is the most efficient way to perform variant analysis. -Learning QL for variant analysis --------------------------------- +Learning CodeQL for variant analysis +------------------------------------ Start learning how to use CodeQL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on CodeQL, its libraries, or an example variant discovered using CodeQL. @@ -45,7 +45,7 @@ CodeQL and variant analysis for C/C++ - `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: snprintf overflow <../ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query. - `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL. -- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. +- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using CodeQL. CodeQL and variant analysis for Java ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -61,6 +61,6 @@ More resources ~~~~~~~~~~~~~~ - If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. -- To find more detailed information about how to write CodeQL queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. +- To find more detailed information about how to write queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. - To read more about how CodeQL queries have been used in Semmle's security research, and to read about new CodeQL developments, visit the `Semmle blog `__. - Find more examples of queries written by Semmle's own security researchers in the `Semmle Demos repository `__ on GitHub. diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index e78e8e86220..32a3dfa233b 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -82,9 +82,9 @@ Write a query that flags ``printf`` calls where the format argument is not a ``S .. note:: - This first query is about finding places where the format specifier is not a constant string. In CodeQL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. + This first query is about finding places where the format specifier is not a constant string. In the CodeQL libraries for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. - The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the CodeQL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. + The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the standard CodeQL class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. Meh... ====== diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index cbe29e6c520..9cfb1d3b442 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -108,7 +108,7 @@ Each query library also implicitly defines a module. Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary query file in the background. - Parts of queries can be lifted into `library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 3c062089428..156cb0a4a68 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by class Call and its subclasses: +Calls to functions are modeled by class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function @@ -103,7 +103,7 @@ Working with macros #define square(x) x*x y = square(y0), z = square(z0) -is represented in the CodeQL database database as: +is represented in the CodeQL database as: - A Macro entity representing the text of the *head* and *body* of the macro - Assignment nodes, representing the two assignments after preprocessing @@ -117,4 +117,4 @@ Useful predicates on ``Element``: ``isInMacroExpansion()``, ``isAffectedByMacro( .. note:: - The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file + The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f7afe713c4a..46106204ed4 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -158,7 +158,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in continued +Classes continued ======================= .. container:: column-left diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index d559c5bbeb7..ae0c0cdabb5 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -121,7 +121,7 @@ QL is: - a **logic** language based on first-order logic - a **declarative** language without side effects - an **object-oriented** language -- a **query** language working on a read-only CodeQL database database +- a **query** language working on a read-only CodeQL database - equipped with rich standard libraries **for program analysis** .. note:: From 8d02a740dda1b8ed961249b4e40d7e3dfd0c7409 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 20:03:47 +0000 Subject: [PATCH 144/232] docs: address remaining comments --- docs/language/ql-training/conf.py | 8 ++++---- .../ql-training/slide-snippets/local-data-flow.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index 8f8a13569b5..117f515a54f 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# QL training slides build configuration file +# CodeQL training slides build configuration file # # This file is execfile()d with the current directory set to its # containing dir. @@ -59,7 +59,7 @@ highlight_language = 'ql' master_doc = 'index' # General information about the project. -project = u'QL training and variant analysis examples' +project = u'CodeQL training and variant analysis examples' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -77,10 +77,10 @@ slide_theme_path = ["_static-training/"] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = 'QL training and variant analysis examples' +html_title = 'CodeQL training and variant analysis examples' # Output file base name for HTML help builder. -htmlhelp_basename = 'QL training' +htmlhelp_basename = 'CodeQL training' # The Semmle version info for the current release you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 068dfc9170a..85b851a9ce0 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -70,7 +70,7 @@ Local vs global data flow For further information, see: - - `Introduction to data flow analysis in QL `__ + - `Introduction to data flow analysis in CodeQL `__ .. rst-class:: background2 From fca7d9a391ea21206c6ec533e8fd66ac780c0e31 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 07:42:34 +0100 Subject: [PATCH 145/232] C#: Cache IRType like for C++ --- csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll | 1 + csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll | 2 ++ 2 files changed, 3 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 0abfa14023d..5534ed20914 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll index ac400b210a5..36b1285f9e0 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll @@ -144,6 +144,7 @@ private IRType getIRTypeForPRValue(Type type) { string getOpaqueTagIdentityString(Type tag) { result = tag.getQualifiedName() } +cached private newtype TCSharpType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TGLValueAddressType(Type type) { any() } or @@ -163,6 +164,7 @@ class CSharpType extends TCSharpType { * Gets the `IRType` that represents this `CSharpType`. Many different `CSharpType`s can map to a * single `IRType`. */ + cached abstract IRType getIRType(); /** From 21d4e5f18624397b811c9fba594924de5be640f4 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Wed, 6 Nov 2019 10:16:43 +0100 Subject: [PATCH 146/232] Doc: Add missing `t` in `support`. --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 812e1e67748..49f527af424 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -2,7 +2,7 @@ ## General improvements -* Suppor for `globalThis` has been added. +* Support for `globalThis` has been added. * Support for the following frameworks and libraries has been improved: - [firebase](https://www.npmjs.com/package/firebase) From 7a7a8b2b091fad67b88fa138bdad41698a295071 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:11:26 +0100 Subject: [PATCH 147/232] JS: More steps in getImmediatePredecessor --- .../semmle/javascript/dataflow/DataFlow.qll | 73 +++++++++++-------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37..7c77df24e09 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -188,11 +188,7 @@ module DataFlow { lvalueFlowStep(result, this) and not lvalueDefaultFlowStep(_, this) or - // Use of variable -> definition of variable - exists(SsaVariable var | - this = valueNode(var.getAUse()) and - result = TSsaDefNode(var) - ) + immediateFlowStep(result, this) or // Refinement of variable -> original definition of variable exists(SsaRefinementNode refinement | @@ -1299,6 +1295,44 @@ module DataFlow { ) } + /** + * Flow steps shared between `getImmediatePredecessor` and `localFlowStep`. + * + * Inlining is forced because the two relations are indexed differently. + */ + pragma[inline] + private predicate immediateFlowStep(Node pred, Node succ) { + exists(SsaVariable v | + pred = TSsaDefNode(v.getDefinition()) and + succ = valueNode(v.getAUse()) + ) + or + exists(Expr predExpr, Expr succExpr | + pred = valueNode(predExpr) and succ = valueNode(succExpr) + | + predExpr = succExpr.(ParExpr).getExpression() + or + predExpr = succExpr.(SeqExpr).getLastOperand() + or + predExpr = succExpr.(AssignExpr).getRhs() + or + predExpr = succExpr.(TypeAssertion).getExpression() + or + predExpr = succExpr.(NonNullAssertion).getExpression() + or + predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() + ) + or + // flow from 'this' parameter into 'this' expressions + exists(ThisExpr thiz | + pred = TThisNode(thiz.getBindingContainer()) and + succ = valueNode(thiz) + ) + or + // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform + pred = TReflectiveCallNode(succ.asExpr(), _) + } + /** * Holds if data can flow from `pred` to `succ` in one local step. */ @@ -1309,6 +1343,8 @@ module DataFlow { or lvalueDefaultFlowStep(pred, succ) or + immediateFlowStep(pred, succ) + or // Flow through implicit SSA nodes exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) | // from any explicit definition or implicit init of a captured variable into @@ -1326,45 +1362,18 @@ module DataFlow { pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition()) ) or - // flow out of local variables - exists(SsaVariable v | - pred = TSsaDefNode(v.getDefinition()) and - succ = valueNode(v.getAUse()) - ) - or exists(Expr predExpr, Expr succExpr | pred = valueNode(predExpr) and succ = valueNode(succExpr) | - predExpr = succExpr.(ParExpr).getExpression() - or - predExpr = succExpr.(SeqExpr).getLastOperand() - or predExpr = succExpr.(LogicalBinaryExpr).getAnOperand() or - predExpr = succExpr.(AssignExpr).getRhs() - or predExpr = succExpr.(ConditionalExpr).getABranch() or - predExpr = succExpr.(TypeAssertion).getExpression() - or - predExpr = succExpr.(NonNullAssertion).getExpression() - or - predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() - or exists(Function f | predExpr = f.getAReturnedExpr() and localCall(succExpr, f) ) ) - or - // flow from 'this' parameter into 'this' expressions - exists(ThisExpr thiz | - pred = TThisNode(thiz.getBindingContainer()) and - succ = valueNode(thiz) - ) - or - // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform - pred = TReflectiveCallNode(succ.asExpr(), _) } /** From bc35f24f31e8d6772e16eb02adb74a3ad38aaaec Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:11:42 +0100 Subject: [PATCH 148/232] JS: Generalize access paths to arbitrary root nodes --- .../semmle/javascript/GlobalAccessPaths.qll | 266 ++++++++++++------ .../javascript/dataflow/TypeTracking.qll | 20 ++ .../dataflow/internal/CallGraphs.qll | 6 +- .../CallGraphs/AnnotatedTest/access-path.js | 39 +++ 4 files changed, 242 insertions(+), 89 deletions(-) create mode 100644 javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 9e089fc9cf0..99e0d168298 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -5,6 +5,24 @@ import javascript module GlobalAccessPath { + /** + * A source node that can be the root of an access path. + */ + private class Root extends DataFlow::SourceNode { + Root() { + not this.accessesGlobal(_) and + not this instanceof DataFlow::PropRead and + not this instanceof PropertyProjection and + not this instanceof Closure::ClosureNamespaceAccess and + not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter()) + } + + /** Holds if this represents the root of the global access path. */ + predicate isGlobal() { + this = DataFlow::globalAccessPathRootPseudoNode() + } + } + /** * A local variable with exactly one definition, not counting implicit initialization. */ @@ -20,6 +38,78 @@ module GlobalAccessPath { DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() } } + /** + * Gets the access path relative to `root` referred to by `node`. + * + * This holds for direct references as well as for aliases + * established through local data flow. + * + * Examples: + * ``` + * function f(x) { + * let a = x.f.g; // access path relative to 'x' is '.f.g' + * let b = a.h; // access path relative to 'x' is '.f.g.h' + * } + * ``` + */ + cached + string fromReference(DataFlow::Node node, Root root) { + root = node and + not root.isGlobal() and + result = "" + or + result = fromReference(node.getImmediatePredecessor(), root) + or + exists(EffectivelyConstantVariable var | + var.isCaptured() and + node.asExpr() = var.getAnAccess() and + result = fromReference(var.getValue(), root) + ) + or + node.accessesGlobal(result) and + result != "undefined" and + root.isGlobal() + or + not node.accessesGlobal(_) and + exists(DataFlow::PropRead prop | node = prop | + result = fromReference(prop.getBase(), root) + "." + prop.getPropertyName() + ) + or + exists(Closure::ClosureNamespaceAccess acc | node = acc | + result = acc.getClosureNamespace() and + root.isGlobal() + ) + or + exists(PropertyProjection proj | node = proj | + proj.isSingletonProjection() and + result = fromReference(proj.getObject(), root) + "." + proj.getASelector() + ) + or + // Treat 'e || {}' as having the same name as 'e' + exists(LogOrExpr e | node.asExpr() = e | + e.getRightOperand().(ObjectExpr).getNumProperty() = 0 and + result = fromReference(e.getLeftOperand().flow(), root) + ) + or + // Treat 'e && e.f' as having the same name as 'e.f' + exists(LogAndExpr e, Expr lhs, PropAccess rhs | node.asExpr() = e | + lhs = e.getLeftOperand() and + rhs = e.getRightOperand() and + ( + exists(Variable v | + lhs = v.getAnAccess() and + rhs.getBase() = v.getAnAccess() + ) + or + exists(string name | + lhs.(PropAccess).getQualifiedName() = name and + rhs.getBase().(PropAccess).getQualifiedName() = name + ) + ) and + result = fromReference(rhs.flow(), root) + ) + } + /** * Gets the global access path referred to by `node`. * @@ -40,52 +130,7 @@ module GlobalAccessPath { */ cached string fromReference(DataFlow::Node node) { - result = fromReference(node.getImmediatePredecessor()) - or - exists(EffectivelyConstantVariable var | - var.isCaptured() and - node.asExpr() = var.getAnAccess() and - result = fromReference(var.getValue()) - ) - or - node.accessesGlobal(result) and - result != "undefined" - or - not node.accessesGlobal(_) and - exists(DataFlow::PropRead prop | node = prop | - result = fromReference(prop.getBase()) + "." + prop.getPropertyName() - ) - or - exists(Closure::ClosureNamespaceAccess acc | node = acc | result = acc.getClosureNamespace()) - or - exists(PropertyProjection proj | node = proj | - proj.isSingletonProjection() and - result = fromReference(proj.getObject()) + "." + proj.getASelector() - ) - or - // Treat 'e || {}' as having the same name as 'e' - exists(LogOrExpr e | node.asExpr() = e | - e.getRightOperand().(ObjectExpr).getNumProperty() = 0 and - result = fromReference(e.getLeftOperand().flow()) - ) - or - // Treat 'e && e.f' as having the same name as 'e.f' - exists(LogAndExpr e, Expr lhs, PropAccess rhs | node.asExpr() = e | - lhs = e.getLeftOperand() and - rhs = e.getRightOperand() and - ( - exists(Variable v | - lhs = v.getAnAccess() and - rhs.getBase() = v.getAnAccess() - ) - or - exists(string name | - lhs.(PropAccess).getQualifiedName() = name and - rhs.getBase().(PropAccess).getQualifiedName() = name - ) - ) and - result = fromReference(rhs.flow()) - ) + result = fromReference(node, DataFlow::globalAccessPathRootPseudoNode()) } /** @@ -96,7 +141,9 @@ module GlobalAccessPath { * foo = foo || {}; * ``` */ - private predicate isSelfAssignment(DataFlow::Node rhs) { fromRhs(rhs) = fromReference(rhs) } + private predicate isSelfAssignment(DataFlow::Node rhs) { + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = fromReference(rhs, DataFlow::globalAccessPathRootPseudoNode()) + } /** * Holds if there is an assignment to `accessPath` in `file`, not counting @@ -104,7 +151,7 @@ module GlobalAccessPath { */ private predicate isAssignedInFile(string accessPath, File file) { exists(DataFlow::Node rhs | - fromRhs(rhs) = accessPath and + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = accessPath and not isSelfAssignment(rhs) and // Note: Avoid unneeded materialization of DataFlow::Node.getFile() rhs.getAstNode().getFile() = file @@ -112,13 +159,71 @@ module GlobalAccessPath { } /** - * Holds if `accessPath` is only assigned to from one file, not counting + * Holds if the global `accessPath` is only assigned to from one file, not counting * self-assignments. */ predicate isAssignedInUniqueFile(string accessPath) { strictcount(File f | isAssignedInFile(accessPath, f)) = 1 } + /** + * Gets the access path relative to `root`, which `node` is being assigned to, if any. + * + * Only holds for the immediate right-hand side of an assignment or property, not + * for nodes that transitively flow there. + * + * For example, the class nodes below all map to `.foo.bar` relative to `x`: + * ``` + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } + * ``` + */ + cached + string fromRhs(DataFlow::Node node, Root root) { + exists(DataFlow::SourceNode base, string baseName, string name | + node = base.getAPropertyWrite(name).getRhs() and + result = baseName + "." + name + | + baseName = fromReference(base, root) + or + baseName = fromRhs(base, root) + ) + or + exists(GlobalVariable var | + node = var.getAnAssignedExpr().flow() and + result = var.getName() and + root.isGlobal() + ) + or + exists(FunctionDeclStmt fun | + node = DataFlow::valueNode(fun) and + result = fun.getId().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(ClassDeclStmt cls | + node = DataFlow::valueNode(cls) and + result = cls.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(EnumDeclaration decl | + node = DataFlow::valueNode(decl) and + result = decl.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(NamespaceDeclaration decl | + node = DataFlow::valueNode(decl) and + result = decl.getId().(GlobalVarDecl).getName() and + root.isGlobal() + ) + } + /** * Gets the global access path `node` is being assigned to, if any. * @@ -138,48 +243,41 @@ module GlobalAccessPath { */ cached string fromRhs(DataFlow::Node node) { - exists(DataFlow::SourceNode base, string baseName, string name | - node = base.getAPropertyWrite(name).getRhs() and - result = baseName + "." + name - | - baseName = fromReference(base) - or - baseName = fromRhs(base) - ) + result = fromRhs(node, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Gets the access path relative to `root` referenced by or assigned to `node`. + */ + string getAccessPath(DataFlow::Node node, Root root) { + result = fromReference(node, root) or - exists(GlobalVariable var | - node = var.getAnAssignedExpr().flow() and - result = var.getName() - ) - or - exists(FunctionDeclStmt fun | - node = DataFlow::valueNode(fun) and - result = fun.getId().(GlobalVarDecl).getName() - ) - or - exists(ClassDeclStmt cls | - node = DataFlow::valueNode(cls) and - result = cls.getIdentifier().(GlobalVarDecl).getName() - ) - or - exists(EnumDeclaration decl | - node = DataFlow::valueNode(decl) and - result = decl.getIdentifier().(GlobalVarDecl).getName() - ) - or - exists(NamespaceDeclaration decl | - node = DataFlow::valueNode(decl) and - result = decl.getId().(GlobalVarDecl).getName() - ) + not exists(fromReference(node, root)) and + result = fromRhs(node, root) } /** * Gets the global access path referenced by or assigned to `node`. */ string getAccessPath(DataFlow::Node node) { - result = fromReference(node) + result = getAccessPath(node, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Holds if there is a step from `pred` to `succ` through an assignment to an access path. + */ + pragma[inline] + predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(string name, Root root | + name = fromRhs(pred, root) and + name = fromReference(succ, root) and + not root.isGlobal() + ) or - not exists(fromReference(node)) and - result = fromRhs(node) + exists(string name | + name = fromRhs(pred) and + name = fromReference(succ) and + isAssignedInUniqueFile(name) + ) } } diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index ef639d99ad4..62e53962c3f 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -14,6 +14,9 @@ private class PropertyName extends string { this = any(DataFlow::PropRef pr).getPropertyName() or GlobalAccessPath::isAssignedInUniqueFile(this) + or + this = GlobalAccessPath::fromRhs(_, _) and + this != "" } } @@ -95,6 +98,7 @@ module StepSummary { any(AdditionalTypeTrackingStep st).step(pred, succ) and summary = LevelStep() or + // Store to global access path exists(string name | name = GlobalAccessPath::fromRhs(pred) and GlobalAccessPath::isAssignedInUniqueFile(name) and @@ -102,6 +106,7 @@ module StepSummary { summary = StoreStep(name) ) or + // Load from global access path exists(string name | name = GlobalAccessPath::fromReference(succ) and GlobalAccessPath::isAssignedInUniqueFile(name) and @@ -109,6 +114,21 @@ module StepSummary { summary = LoadStep(name) ) or + // Store to non-global access path + exists(string name | + name = GlobalAccessPath::fromRhs(pred, succ) and + succ != DataFlow::globalAccessPathRootPseudoNode() and + summary = StoreStep(name) + ) + or + // Load from non-global access path + exists(string name | + name = GlobalAccessPath::fromReference(succ, pred) and + pred != DataFlow::globalAccessPathRootPseudoNode() and + summary = LoadStep(name) and + name != "" + ) + or // Summarize calls with flow directly from a parameter to a return. exists(DataFlow::ParameterNode param, DataFlow::FunctionNode fun | ( diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index a5e140734a4..1e554b170f1 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -43,11 +43,7 @@ module CallGraph { or imprecision = 0 and t.start() and - exists(string name | - GlobalAccessPath::isAssignedInUniqueFile(name) and - GlobalAccessPath::fromRhs(function) = name and - GlobalAccessPath::fromReference(result) = name - ) + GlobalAccessPath::step(function, result) or imprecision = 0 and exists(DataFlow::ClassNode cls | diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js new file mode 100644 index 00000000000..f320d3ae8f4 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js @@ -0,0 +1,39 @@ +function foo() { + let self = this; + + /** name:direct */ + self.foo.bar.direct = function() {}; + + /** calls:direct */ + self.foo.bar.direct(); + + self.foo.bar = { + /** name:baz */ + baz() {}, + bong() { + /** calls:baz */ + self.foo.bar.baz(); + } + } + + /** calls:baz */ + self.foo.bar.baz(); + + self.foo.bar.Class = class { + /** name:m */ + m() {} + } + + self.foo.bar.instance = new self.foo.bar.Class(); + + /** calls:m */ + self.foo.bar.instance.m(); + + let unknownObject = unknownCall(); + + /** name:direct2 */ + unknownObject.bar.baz.direct = function() {}; + + /** calls:direct2 */ + unknownObject.bar.baz.direct(); +} From e90516d4d8baebff5228d6190f58306f47407175 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Oct 2019 09:51:47 +0100 Subject: [PATCH 149/232] JS: Dont use getALocalSource in fromRhs --- .../ql/src/semmle/javascript/GlobalAccessPaths.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 99e0d168298..3e797e7914c 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -184,13 +184,13 @@ module GlobalAccessPath { */ cached string fromRhs(DataFlow::Node node, Root root) { - exists(DataFlow::SourceNode base, string baseName, string name | - node = base.getAPropertyWrite(name).getRhs() and - result = baseName + "." + name + exists(DataFlow::PropWrite write, string baseName | + node = write.getRhs() and + result = baseName + "." + write.getPropertyName() | - baseName = fromReference(base, root) + baseName = fromReference(write.getBase(), root) or - baseName = fromRhs(base, root) + baseName = fromRhs(write.getBase(), root) ) or exists(GlobalVariable var | From c365833731965757e9123cb87d446c5a92bcdaa0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:47:50 +0100 Subject: [PATCH 150/232] JS: Refactor the public access path API --- .../ql/src/semmle/javascript/Closure.qll | 4 +- .../semmle/javascript/GlobalAccessPaths.qll | 169 +++++++++++++----- javascript/ql/src/semmle/javascript/JSDoc.qll | 2 +- .../src/semmle/javascript/dataflow/Nodes.qll | 10 +- .../javascript/dataflow/TypeTracking.qll | 19 +- .../dataflow/internal/CallGraphs.qll | 2 +- 6 files changed, 136 insertions(+), 70 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/src/semmle/javascript/Closure.qll index 066f68ca5fa..83b8049d48f 100644 --- a/javascript/ql/src/semmle/javascript/Closure.qll +++ b/javascript/ql/src/semmle/javascript/Closure.qll @@ -230,7 +230,7 @@ module Closure { * Gets the closure namespace path addressed by the given data flow node, if any. */ string getClosureNamespaceFromSourceNode(DataFlow::SourceNode node) { - result = GlobalAccessPath::getAccessPath(node) and + node = AccessPath::getAReferenceOrAssignmentTo(result) and hasClosureNamespacePrefix(result) } @@ -238,7 +238,7 @@ module Closure { * Gets the closure namespace path written to by the given property write, if any. */ string getWrittenClosureNamespace(DataFlow::PropWrite node) { - result = GlobalAccessPath::fromRhs(node.getRhs()) and + node.getRhs() = AccessPath::getAnAssignmentTo(result) and hasClosureNamespacePrefix(result) } diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 3e797e7914c..8833e3a9179 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -4,11 +4,41 @@ import javascript +deprecated module GlobalAccessPath { + /** + * DEPRECATED. Instead use `AccessPath::getAReferenceTo` with the result and parameter reversed. + */ + pragma[inline] + string fromReference(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) + } + + /** + * DEPRECATED. Instead use `AccessPath::getAnAssignmentTo` with the result and parameter reversed. + */ + pragma[inline] + string fromRhs(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) + } + + /** + * DEPRECATED. Use `AccessPath::getAReferenceOrAssignmentTo`. + */ + pragma[inline] + string getAccessPath(DataFlow::Node node) { + result = fromReference(node) + or + not exists(fromReference(node)) and + result = fromRhs(node) + } +} + +module AccessPath { /** * A source node that can be the root of an access path. */ - private class Root extends DataFlow::SourceNode { + class Root extends DataFlow::SourceNode { Root() { not this.accessesGlobal(_) and not this instanceof DataFlow::PropRead and @@ -53,7 +83,7 @@ module GlobalAccessPath { * ``` */ cached - string fromReference(DataFlow::Node node, Root root) { + private string fromReference(DataFlow::Node node, Root root) { root = node and not root.isGlobal() and result = "" @@ -110,29 +140,6 @@ module GlobalAccessPath { ) } - /** - * Gets the global access path referred to by `node`. - * - * This holds for direct references as well as for aliases - * established through local data flow. - * - * Examples: - * ``` - * function f() { - * let v = foo.bar; // reference to 'foo.bar' - * v.baz; // reference to 'foo.bar.baz' - * } - * - * (function(ns) { - * ns.x; // reference to 'NS.x' - * })(NS = NS || {}); - * ``` - */ - cached - string fromReference(DataFlow::Node node) { - result = fromReference(node, DataFlow::globalAccessPathRootPseudoNode()) - } - /** * Holds if `rhs` is the right-hand side of a self-assignment. * @@ -183,7 +190,7 @@ module GlobalAccessPath { * ``` */ cached - string fromRhs(DataFlow::Node node, Root root) { + private string fromRhs(DataFlow::Node node, Root root) { exists(DataFlow::PropWrite write, string baseName | node = write.getRhs() and result = baseName + "." + write.getPropertyName() @@ -225,42 +232,109 @@ module GlobalAccessPath { } /** - * Gets the global access path `node` is being assigned to, if any. + * Gets a node that refers to the given access path relative to the given `root` node, + * or `root` itself if the access path is empty. * - * Only holds for the immediate right-hand side of an assignment or property, not - * for nodes that transitively flow there. + * This works for direct references as well as for aliases established through local data flow. * - * For example, the class nodes below all map to `foo.bar`: + * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`. + * + * For example: + * ``` + * function f(x) { + * let a = x.f.g; // reference to (x, ".f.g") + * let b = a.h; // reference to (x, ".f.g.h") + * } + * ``` + */ + DataFlow::Node getAReferenceTo(Root root, string path) { + path = fromReference(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that refers to the given global access path. + * + * This works for direct references as well as for aliases established through local data flow. + * + * Examples: + * ``` + * function f() { + * let v = foo.bar; // reference to 'foo.bar' + * v.baz; // reference to 'foo.bar.baz' + * } + * + * (function(ns) { + * ns.x; // reference to 'NS.x' + * })(NS = NS || {}); + * ``` + */ + DataFlow::Node getAReferenceTo(string path) { + path = fromReference(result, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Gets a node that is assigned to the given access path relative to the given `root` node. + * + * Only gets the immediate right-hand side of an assignment or property, not + * nodes that transitively flow there. + * + * Note that access paths contain an initial `.`, such as in `.foo.bar`. + * + * For example, the class nodes below are all assignments to `(x, ".foo.bar")`. + * ``` + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } + * ``` + */ + DataFlow::Node getAnAssignmentTo(Root root, string path) { + path = fromRhs(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that is assigned to the given global access path. + * + * Only gets the immediate right-hand side of an assignment or property or a global declaration, + * not nodes that transitively flow there. + * + * For example, the class nodes below are all assignmetns to `foo.bar`: * ``` * foo.bar = class {}; - * * foo = { bar: class {} }; - * * (function(f) { * f.bar = class {} * })(foo = foo || {}); * ``` */ - cached - string fromRhs(DataFlow::Node node) { - result = fromRhs(node, DataFlow::globalAccessPathRootPseudoNode()) + DataFlow::Node getAnAssignmentTo(string path) { + path = fromRhs(result, DataFlow::globalAccessPathRootPseudoNode()) } /** - * Gets the access path relative to `root` referenced by or assigned to `node`. + * Gets a node that refers to or is assigned to the given global access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ - string getAccessPath(DataFlow::Node node, Root root) { - result = fromReference(node, root) + DataFlow::Node getAReferenceOrAssignmentTo(string path) { + result = getAReferenceTo(path) or - not exists(fromReference(node, root)) and - result = fromRhs(node, root) + result = getAnAssignmentTo(path) } /** - * Gets the global access path referenced by or assigned to `node`. + * Gets a node that refers to or is assigned to the given access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ - string getAccessPath(DataFlow::Node node) { - result = getAccessPath(node, DataFlow::globalAccessPathRootPseudoNode()) + DataFlow::Node getAReferenceOrAssignmentTo(Root root, string path) { + result = getAReferenceTo(root, path) + or + result = getAnAssignmentTo(root, path) } /** @@ -269,14 +343,13 @@ module GlobalAccessPath { pragma[inline] predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(string name, Root root | - name = fromRhs(pred, root) and - name = fromReference(succ, root) and - not root.isGlobal() + pred = getAnAssignmentTo(root, name) and + succ = getAReferenceTo(root, name) ) or exists(string name | - name = fromRhs(pred) and - name = fromReference(succ) and + pred = getAnAssignmentTo(name) and + succ = getAReferenceTo(name) and isAssignedInUniqueFile(name) ) } diff --git a/javascript/ql/src/semmle/javascript/JSDoc.qll b/javascript/ql/src/semmle/javascript/JSDoc.qll index 806a9477ba6..c080061bc7c 100644 --- a/javascript/ql/src/semmle/javascript/JSDoc.qll +++ b/javascript/ql/src/semmle/javascript/JSDoc.qll @@ -582,7 +582,7 @@ module JSDoc { * within this container. */ string resolveAlias(string alias) { - result = GlobalAccessPath::getAccessPath(getNodeFromAlias(alias)) + getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result) } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index a44f2909ce0..a1e15538ad2 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -771,11 +771,7 @@ class ClassNode extends DataFlow::SourceNode { */ pragma[noinline] predicate hasQualifiedName(string name) { - exists(DataFlow::Node rhs | - getAClassReference().flowsTo(rhs) and - name = GlobalAccessPath::fromRhs(rhs) and - GlobalAccessPath::isAssignedInUniqueFile(name) - ) + getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name)) } } @@ -883,7 +879,7 @@ module ClassNode { } private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { - GlobalAccessPath::getAccessPath(result.getBase()) = name and + result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and result.getPropertyName() = "prototype" and result.getFile() = f } @@ -904,7 +900,7 @@ module ClassNode { ) or exists(string name | - name = GlobalAccessPath::fromRhs(this) and + this = AccessPath::getAnAssignmentTo(name) and exists(getAPrototypeReferenceInFile(name, getFile())) ) ) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index 62e53962c3f..ecbb3187728 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -13,10 +13,9 @@ private class PropertyName extends string { PropertyName() { this = any(DataFlow::PropRef pr).getPropertyName() or - GlobalAccessPath::isAssignedInUniqueFile(this) + AccessPath::isAssignedInUniqueFile(this) or - this = GlobalAccessPath::fromRhs(_, _) and - this != "" + exists(AccessPath::getAnAssignmentTo(_, this)) } } @@ -100,31 +99,29 @@ module StepSummary { or // Store to global access path exists(string name | - name = GlobalAccessPath::fromRhs(pred) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + pred = AccessPath::getAnAssignmentTo(name) and + AccessPath::isAssignedInUniqueFile(name) and succ = DataFlow::globalAccessPathRootPseudoNode() and summary = StoreStep(name) ) or // Load from global access path exists(string name | - name = GlobalAccessPath::fromReference(succ) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + succ = AccessPath::getAReferenceTo(name) and + AccessPath::isAssignedInUniqueFile(name) and pred = DataFlow::globalAccessPathRootPseudoNode() and summary = LoadStep(name) ) or // Store to non-global access path exists(string name | - name = GlobalAccessPath::fromRhs(pred, succ) and - succ != DataFlow::globalAccessPathRootPseudoNode() and + pred = AccessPath::getAnAssignmentTo(succ, name) and summary = StoreStep(name) ) or // Load from non-global access path exists(string name | - name = GlobalAccessPath::fromReference(succ, pred) and - pred != DataFlow::globalAccessPathRootPseudoNode() and + succ = AccessPath::getAReferenceTo(pred, name) and summary = LoadStep(name) and name != "" ) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index 1e554b170f1..d58a83fa0bd 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -43,7 +43,7 @@ module CallGraph { or imprecision = 0 and t.start() and - GlobalAccessPath::step(function, result) + AccessPath::step(function, result) or imprecision = 0 and exists(DataFlow::ClassNode cls | From b373901e11461d598edb6101dadaa9544ce7e0c8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Oct 2019 09:36:27 +0000 Subject: [PATCH 151/232] JS: Avoid leading dot in access paths --- .../semmle/javascript/GlobalAccessPaths.qll | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 8833e3a9179..2b7da2fe7ae 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -68,6 +68,18 @@ module AccessPath { DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() } } + /** + * Appends a single property name onto the access path `base`, where + * the empty string represents the empty access path. + */ + bindingset[base, prop] + private string join(string base, string prop) { + base = "" and result = prop + or + base != "" and + result = base + "." + prop + } + /** * Gets the access path relative to `root` referred to by `node`. * @@ -77,8 +89,8 @@ module AccessPath { * Examples: * ``` * function f(x) { - * let a = x.f.g; // access path relative to 'x' is '.f.g' - * let b = a.h; // access path relative to 'x' is '.f.g.h' + * let a = x.f.g; // access path relative to 'x' is 'f.g' + * let b = a.h; // access path relative to 'x' is 'f.g.h' * } * ``` */ @@ -102,7 +114,7 @@ module AccessPath { or not node.accessesGlobal(_) and exists(DataFlow::PropRead prop | node = prop | - result = fromReference(prop.getBase(), root) + "." + prop.getPropertyName() + result = join(fromReference(prop.getBase(), root), prop.getPropertyName()) ) or exists(Closure::ClosureNamespaceAccess acc | node = acc | @@ -112,7 +124,7 @@ module AccessPath { or exists(PropertyProjection proj | node = proj | proj.isSingletonProjection() and - result = fromReference(proj.getObject(), root) + "." + proj.getASelector() + result = join(fromReference(proj.getObject(), root), proj.getASelector().getStringValue()) ) or // Treat 'e || {}' as having the same name as 'e' @@ -179,7 +191,7 @@ module AccessPath { * Only holds for the immediate right-hand side of an assignment or property, not * for nodes that transitively flow there. * - * For example, the class nodes below all map to `.foo.bar` relative to `x`: + * For example, the class nodes below all map to `foo.bar` relative to `x`: * ``` * function f(x) { * x.foo.bar = class {}; @@ -193,7 +205,7 @@ module AccessPath { private string fromRhs(DataFlow::Node node, Root root) { exists(DataFlow::PropWrite write, string baseName | node = write.getRhs() and - result = baseName + "." + write.getPropertyName() + result = join(baseName, write.getPropertyName()) | baseName = fromReference(write.getBase(), root) or @@ -237,13 +249,11 @@ module AccessPath { * * This works for direct references as well as for aliases established through local data flow. * - * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`. - * * For example: * ``` * function f(x) { - * let a = x.f.g; // reference to (x, ".f.g") - * let b = a.h; // reference to (x, ".f.g.h") + * let a = x.f.g; // reference to (x, "f.g") + * let b = a.h; // reference to (x, "f.g.h") * } * ``` */ @@ -279,9 +289,7 @@ module AccessPath { * Only gets the immediate right-hand side of an assignment or property, not * nodes that transitively flow there. * - * Note that access paths contain an initial `.`, such as in `.foo.bar`. - * - * For example, the class nodes below are all assignments to `(x, ".foo.bar")`. + * For example, the class nodes below are all assignments to `(x, "foo.bar")`. * ``` * function f(x) { * x.foo.bar = class {}; From 7e80823cb62179e2bd21950131f6a864ba2feaa4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 10:40:09 +0000 Subject: [PATCH 152/232] JS: Fix deprecated API usage --- javascript/ql/src/semmle/javascript/dataflow/Nodes.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index a1e15538ad2..d06056a4696 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -965,7 +965,7 @@ module ClassNode { ) or exists(string name | - GlobalAccessPath::fromRhs(this) = name and + this = AccessPath::getAnAssignmentTo(name) and result = getAPrototypeReferenceInFile(name, getFile()) ) or From 3ec95881b497c8738703e85f847267d148c39585 Mon Sep 17 00:00:00 2001 From: Asger F <42069257+asger-semmle@users.noreply.github.com> Date: Wed, 30 Oct 2019 11:16:35 +0000 Subject: [PATCH 153/232] Update javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 2b7da2fe7ae..b19a19482d1 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -165,7 +165,7 @@ module AccessPath { } /** - * Holds if there is an assignment to `accessPath` in `file`, not counting + * Holds if there is an assignment to the global `accessPath` in `file`, not counting * self-assignments. */ private predicate isAssignedInFile(string accessPath, File file) { From 81723ab92a8d3bdda994a3020ed948e95a5c7f63 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 6 Nov 2019 11:57:34 +0000 Subject: [PATCH 154/232] JS: Update GlobalAccessPaths test --- .../GlobalAccessPaths/GlobalAccessPaths.expected | 6 ++++-- .../GlobalAccessPaths/GlobalAccessPaths.ql | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected index a54916e0142..414252881a2 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected @@ -1,4 +1,4 @@ -test_fromReference +test_getAReferenceTo | other_ns.js:2:11:2:12 | ns | NS | | other_ns.js:3:3:3:4 | ns | NS | | other_ns.js:3:3:3:8 | ns.foo | NS.foo | @@ -39,6 +39,7 @@ test_fromReference | test.js:12:19:12:25 | foo.bar | foo.bar | | test.js:13:7:13:15 | something | something | | test.js:14:5:14:23 | notUnique | bar.baz | +| test.js:14:5:14:23 | notUnique = bar.baz | bar.baz | | test.js:14:17:14:19 | bar | bar | | test.js:14:17:14:23 | bar.baz | bar.baz | | test.js:22:11:22:12 | ns | NS | @@ -54,10 +55,11 @@ test_fromReference | test.js:33:9:33:16 | bar = {} | foo.bar | | test.js:33:22:33:24 | foo | foo | | test.js:39:3:39:20 | lazyInit | foo.bar | +| test.js:39:3:39:20 | lazyInit = foo.bar | foo.bar | | test.js:39:14:39:16 | foo | foo | | test.js:39:14:39:20 | foo.bar | foo.bar | | test.js:40:3:40:10 | lazyInit | foo.bar | -test_fromRhs +test_getAnAssignmentTo | other_ns.js:4:9:4:16 | NS \|\| {} | NS | | other_ns.js:6:12:6:13 | {} | Conflict | | test.js:1:1:20:1 | functio ... ss {}\\n} | f | diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql index 4a233f3947b..8412511df8d 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql @@ -1,9 +1,11 @@ import javascript -query string test_fromReference(DataFlow::Node node) { - result = GlobalAccessPath::fromReference(node) +query string test_getAReferenceTo(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) } -query string test_fromRhs(DataFlow::Node node) { result = GlobalAccessPath::fromRhs(node) } +query string test_getAnAssignmentTo(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) +} -query string test_assignedUnique() { GlobalAccessPath::isAssignedInUniqueFile(result) } +query string test_assignedUnique() { AccessPath::isAssignedInUniqueFile(result) } From dc923ef694ca8cec80f8b25c7285ee13c6231753 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 6 Nov 2019 13:28:46 +0100 Subject: [PATCH 155/232] remove change note Co-Authored-By: Esben Sparre Andreasen --- change-notes/1.23/analysis-javascript.md | 1 - 1 file changed, 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 8b89369fcff..bb135758904 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -11,7 +11,6 @@ - [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible) * The call graph has been improved to resolve method calls in more cases. This may produce more security alerts. -* Promises derived from a Deferred object are now recognized. * TypeScript 3.6 and 3.7 features are now supported. From 19554ff6e7a8584e63b76bbde90ff88379e26781 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 6 Nov 2019 13:37:54 +0100 Subject: [PATCH 156/232] change "e.g." to "for example" in qldoc --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 48af33b8e43..123515a7cbd 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -160,7 +160,7 @@ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { module Deferred { /** * An instance of a `Deferred` class. - * E.g. the result from `new Deferred()` or `new $.Deferred()`. + * For example the result from `new Deferred()` or `new $.Deferred()`. */ class DeferredInstance extends DataFlow::NewNode { // Describes both `new Deferred()`, `new $.Deferred` and other variants. From 24615f2bdbb73398e129cc28fa8a95326c5e53c8 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 6 Nov 2019 12:37:20 +0000 Subject: [PATCH 157/232] docs: further review comments --- docs/language/ql-training/cpp/control-flow-cpp.rst | 2 +- docs/language/ql-training/cpp/intro-ql-cpp.rst | 12 ++++++------ .../ql-training/cpp/program-representation-cpp.rst | 10 +++++----- docs/language/ql-training/java/intro-ql-java.rst | 10 +++++----- .../ql-training/java/program-representation-java.rst | 12 ++++++------ .../ql-training/java/query-injection-java.rst | 6 +++--- .../ql-training/slide-snippets/local-data-flow.rst | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index 3fddc3f8072..f72633b714f 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -89,7 +89,7 @@ Control flow graphs Modeling control flow ===================== -The control flow is modeled with a QL class, ``ControlFlowNode``. Examples of control flow nodes include statements and expressions. +The control flow is modeled with a CodeQL class, ``ControlFlowNode``. Examples of control flow nodes include statements and expressions. - ``ControlFlowNode`` provides API for traversing the control flow graph: diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 9cfb1d3b442..4e2cd4ca0b4 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `CodeQL for C/C++ standard library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for C/C++ `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -135,10 +135,10 @@ A predicate allows you to pull out and name parts of a query. You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes -======= +Classes in QL +============= -A class allows you to name a set of values and define (member) predicates on them. +A QL class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -158,8 +158,8 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes continued -================= +Classes in QL continued +======================= .. container:: column-left diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 156cb0a4a68..8f7a4d43de9 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -21,16 +21,16 @@ Agenda .. resume slides -AST classes -=========== +AST CodeQL classes +================== -Important AST classes include: +Important AST CodeQL classes include: - ``Expr``: expressions such as assignments, variable references, function calls, ... - ``Stmt``: statements such as conditionals, loops, try statements, ... - ``DeclarationEntry``: places where functions, variables or types are declared and/or defined -These three (and all other AST classes) are subclasses of ``Element``. +These three (and all other AST CodeQL classes) are subclasses of ``Element``. Symbol table ============ @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by class ``Call`` and its subclasses: +Calls to functions are modeled by CodeQL class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 46106204ed4..1666d9caca8 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `CodeQL for Java library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for Java `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -135,10 +135,10 @@ A predicate allows you to pull out and name parts of a query. You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes -======= +Classes in QL +============= -A class allows you to name a set of values and define (member) predicates on them. +A QL class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -158,7 +158,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes continued +Classes in QL continued ======================= .. container:: column-left diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index ba9b1a9d80d..a66a81d6083 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -12,7 +12,7 @@ Agenda - Abstract syntax trees - Database representation - Program elements -- AST classes +- AST CodeQL classes .. insert abstract-syntax-tree.rst @@ -23,7 +23,7 @@ Agenda Program elements ================ -- The QL class ``Element`` represents program elements with a name. +- The CodeQL class ``Element`` represents program elements with a name. - This includes: packages (``Package``), compilation units (``CompilationUnit``), types (``Type``), methods (``Method``), constructors (``Constructor``), and variables (``Variable``). - It is often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. @@ -31,7 +31,7 @@ Program elements AST === -There are two primary AST classes, used within ``Callables``: +There are two primary AST CodeQL classes, used within ``Callables``: - ``Expr``: expressions such as assignments, variable references, function calls, ... - ``Stmt``: statements such as conditionals, loops, try statements, ... @@ -47,7 +47,7 @@ Types The database also includes information about the types used in a program: -- ``PrimitiveType`` represents a `primitive type `__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``. QL also classifies ``void`` and ```` (the type of the ``null`` literal) as primitive types. +- ``PrimitiveType`` represents a `primitive type `__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``. CodeQL also classifies ``void`` and ```` (the type of the ``null`` literal) as primitive types. - ``RefType`` represents a reference type; it has several subclasses: - ``Class`` represents a Java class. @@ -74,9 +74,9 @@ Working with variables Working with callables ====================== -Callables are represented by the ``Callable`` QL class. +Callables are represented by the ``Callable`` CodeQL class. -Calls to callables are modeled by the QL class ``Call`` and its subclasses: +Calls to callables are modeled by the CodeQL class ``Call`` and its subclasses: - ``Call.getCallee()`` gets the declared target of the call - ``Call.getAReference()`` gets a call to this function diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index a5b46eabda5..799c99e5209 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -77,14 +77,14 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu .. note:: - - When performing `variant analysis `__, it is usually helpful to write a simple query that finds the simple syntactic pattern, before trying to go on to describe the cases where it goes wrong. - - In this case, we start by looking for all the method calls which appear to run, before trying to refine the query to find cases which are vulnerable to query injection. + - When performing `variant analysis `__, it is usually helpful to write a simple query that finds the simple syntactic pattern, before trying to go on to describe the cases where it goes wrong. + - In this case, we start by looking for all the method calls that appear to run, before trying to refine the query to find cases which are vulnerable to query injection. - The ``select`` clause defines what this query is looking for: - a ``MethodAccess``: the call to a SPARQL query method - a ``Method``: the SPARQL query method. - - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL for Java library `__. + - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL library for Java `__. CodeQL query: find string concatenation ======================================= diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 85b851a9ce0..ed681b0398a 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -70,7 +70,7 @@ Local vs global data flow For further information, see: - - `Introduction to data flow analysis in CodeQL `__ + - `Introduction to data flow analysis with CodeQL `__ .. rst-class:: background2 From a4bf361f6440b7acf870ae9e1509448aa0337e0a Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 15:37:54 +0000 Subject: [PATCH 158/232] JavaScript: Remove remaining `--experimental` extractor options. --- .../ql/test/library-tests/CFG/CFG.expected | 8 +- .../ql/test/library-tests/CFG/classes.js | 2 - .../ql/test/library-tests/CFG/fields.js | 2 - .../ql/test/library-tests/CFG/mixedMembers.js | 2 - .../ql/test/library-tests/CFG/staticFields.js | 3 - .../ql/test/library-tests/Classes/fields.js | 2 - .../Comprehensions/comprehensions.js | 2 - .../ql/test/library-tests/DataFlow/tst.js | 2 - .../ql/test/library-tests/Decorators/tst.js | 2 - .../ql/test/library-tests/DefUse/es2015.js | 2 - .../test/library-tests/Expr/legacyletexpr.js | 2 - .../test/library-tests/Expr/mozextensions.js | 2 - .../ql/test/library-tests/Expr/tests.expected | 84 +++++++++---------- .../library-tests/Flow/namespace-reexport.js | 2 - .../library-tests/Flow/reexport-mixins.js | 2 - .../library-tests/Flow/reexport/lib/index.js | 2 - .../library-tests/Functions/exprclosures.js | 2 - .../ql/test/library-tests/LocalObjects/tst.js | 2 - javascript/ql/test/library-tests/Modules/b.js | 2 - .../ql/test/library-tests/Modules/m/c.js | 2 - .../test/library-tests/Modules/tests.expected | 6 +- .../OptionalChaining/short-circuiting.js | 1 - .../library-tests/OptionalChaining/tst.js | 2 - .../ql/test/library-tests/ThisExpr/tst.js | 1 - .../TypeInference/NullishCoalescing/tst.js | 1 - .../TypeInference/OptionalChaining/tst.js | 1 - .../frameworks/ReactJS/statePropertyReads.js | 2 - .../frameworks/ReactJS/statePropertyWrites.js | 2 - .../ql/test/library-tests/stmts/foreach.js | 2 - .../test/library-tests/stmts/guardedCatch.js | 2 - .../ql/test/library-tests/stmts/jscript.js | 2 - .../test/library-tests/stmts/legacyletstmt.js | 2 - .../variables/getDeclaringContainer.expected | 4 +- .../library-tests/variables/legacyletstmt.js | 2 - .../Declarations/DeadStoreOfLocal/fields.js | 2 - .../Declarations/UnusedVariable/funbind.js | 2 - .../Declarations/UnusedVariable/restprops.js | 2 - .../HeterogeneousComparison/tst.js | 2 - .../ImplicitOperandConversion/tst.js | 1 - .../Expressions/ShiftOutOfRange/tst.js | 2 - .../SuspiciousInvocation/fields.js | 2 - .../SuspiciousInvocation/optional-chaining.js | 1 - .../SuspiciousPropAccess/optional-chaining.js | 1 - .../yield_in_non_generator.js | 2 - .../UnboundEventHandlerReceiver/tst.js | 2 - .../ExpressionClosures/foreach.js | 2 - .../ExpressionClosures/jscript.js | 2 - .../ExpressionClosures/letExpr.js | 2 - .../ExpressionClosures/letStmt.js | 2 - .../postfixComprehension.js | 2 - .../ExpressionClosures/tst.js | 2 - .../ForInComprehensionBlocks/tst.js | 2 - .../SemicolonInsertion/jscript.js | 2 - .../YieldInNonGenerator/tst.js | 3 - .../React/DirectStateMutation/valid9.js | 2 - .../issue7506.js | 2 - .../undefined.js | 2 - .../UnusedOrUndefinedStateProperty/unused.js | 2 - .../UselessConditional/UselessConditional.js | 2 - 59 files changed, 51 insertions(+), 156 deletions(-) diff --git a/javascript/ql/test/library-tests/CFG/CFG.expected b/javascript/ql/test/library-tests/CFG/CFG.expected index 7904099cb44..a41f1c4999a 100644 --- a/javascript/ql/test/library-tests/CFG/CFG.expected +++ b/javascript/ql/test/library-tests/CFG/CFG.expected @@ -546,7 +546,7 @@ | classes | 39 | static x = 5; | 39 | t = cla ... () {} } | | classes | 39 | t | 39 | A | | classes | 39 | t = cla ... () {} } | 39 | t | -| classes | 39 | t = cla ... () {} } | 42 | exit node of | +| classes | 39 | t = cla ... () {} } | 40 | exit node of | | classes | 39 | x | 39 | 5 | | classes | 39 | {} | 39 | exit node of () {} | | decorated_parameter | 1 | C | 2 | foo | @@ -625,7 +625,7 @@ | fields | 8 | {} | 8 | exit node of () {} | | fields | 11 | A | 12 | constructor | | fields | 11 | B | 11 | A | -| fields | 11 | class B ... \\n z;\\n} | 21 | exit node of | +| fields | 11 | class B ... \\n z;\\n} | 19 | exit node of | | fields | 12 | constru ... er;\\n } | 11 | class B ... \\n z;\\n} | | fields | 12 | constructor | 12 | function in constru ... er;\\n } | | fields | 12 | entry node of () {\\n ... er;\\n } | 12 | {\\n b ... er;\\n } | @@ -680,7 +680,7 @@ | globals | 19 | h | 20 | {\\n} | | globals | 20 | {\\n} | 21 | exit node of function\\n h()\\n{\\n} | | mixedMembers | 1 | Mixed | 3 | constructor | -| mixedMembers | 1 | class M ... z) {}\\n} | 7 | exit node of | +| mixedMembers | 1 | class M ... z) {}\\n} | 6 | exit node of | | mixedMembers | 1 | entry node of | 1 | Mixed | | mixedMembers | 2 | 3 | 2 | x = 3 | | mixedMembers | 2 | x | 2 | 3 | @@ -746,7 +746,7 @@ | staticFields | 2 | C | 2 | new C() | | staticFields | 2 | instance | 2 | C | | staticFields | 2 | new C() | 2 | static ... ew C(); | -| staticFields | 2 | static ... ew C(); | 7 | exit node of | +| staticFields | 2 | static ... ew C(); | 4 | exit node of | | staticFieldsTS | 1 | C | 1 | constructor | | staticFieldsTS | 1 | class C ... C();\\n} | 2 | instance | | staticFieldsTS | 1 | constructor | 1 | function in constructor() {} | diff --git a/javascript/ql/test/library-tests/CFG/classes.js b/javascript/ql/test/library-tests/CFG/classes.js index cf4bedc2a3b..fa35da77f32 100644 --- a/javascript/ql/test/library-tests/CFG/classes.js +++ b/javascript/ql/test/library-tests/CFG/classes.js @@ -37,5 +37,3 @@ t = class extends A { f() {} } t = class extends A { x = 5; f() {} } t = class extends A { static x = 5; f() {} } t = class extends A { static x = 5; f() {} constructor() {} } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/fields.js b/javascript/ql/test/library-tests/CFG/fields.js index ef4b105c9ff..e93c13eaa18 100644 --- a/javascript/ql/test/library-tests/CFG/fields.js +++ b/javascript/ql/test/library-tests/CFG/fields.js @@ -16,5 +16,3 @@ class B extends A { } z; } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/mixedMembers.js b/javascript/ql/test/library-tests/CFG/mixedMembers.js index 33de7b7ff4a..8ff3721d61c 100644 --- a/javascript/ql/test/library-tests/CFG/mixedMembers.js +++ b/javascript/ql/test/library-tests/CFG/mixedMembers.js @@ -3,5 +3,3 @@ class Mixed { constructor(y) {} method(z) {} } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CFG/staticFields.js b/javascript/ql/test/library-tests/CFG/staticFields.js index 5d8fc7605a2..fa3070ab19f 100644 --- a/javascript/ql/test/library-tests/CFG/staticFields.js +++ b/javascript/ql/test/library-tests/CFG/staticFields.js @@ -1,6 +1,3 @@ class C { static instance = new C(); } - -// semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/library-tests/Classes/fields.js b/javascript/ql/test/library-tests/Classes/fields.js index 63b701e48ac..f71520fc1f8 100644 --- a/javascript/ql/test/library-tests/Classes/fields.js +++ b/javascript/ql/test/library-tests/Classes/fields.js @@ -2,5 +2,3 @@ class C { x; y = 42 } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js index 5194bcc9ddd..32b649bfdae 100644 --- a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js +++ b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js @@ -8,5 +8,3 @@ year; year; (for (i of numbers) for (j of letters) i+j); (for (i of numbers) for (j of letters) if (i | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:10:7 | | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:2:0 | | | nullSensitiveContexts.js:7:1:7:3 | foo | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:1:7:8 | foo[bar] | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:5:7:7 | bar | nullSensitiveContexts.js:1:1:61:0 | | @@ -1922,25 +1922,25 @@ test_getContainer | functions.js:7:4:7:4 | x | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | | mozextensions.js:1:20:1:20 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:23 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:11:1:25 | function(x) x+1 | diff --git a/javascript/ql/test/library-tests/Flow/namespace-reexport.js b/javascript/ql/test/library-tests/Flow/namespace-reexport.js index 0a1e70c5abe..021a140061a 100644 --- a/javascript/ql/test/library-tests/Flow/namespace-reexport.js +++ b/javascript/ql/test/library-tests/Flow/namespace-reexport.js @@ -1,3 +1 @@ export * as h from './h'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport-mixins.js b/javascript/ql/test/library-tests/Flow/reexport-mixins.js index f38cd783b9b..ff303ad3432 100644 --- a/javascript/ql/test/library-tests/Flow/reexport-mixins.js +++ b/javascript/ql/test/library-tests/Flow/reexport-mixins.js @@ -1,3 +1 @@ export default from './mixins'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js index 5ffc9d62bc4..e20cf1a083e 100644 --- a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js @@ -1,3 +1 @@ export data from './src/utils/util' - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Functions/exprclosures.js b/javascript/ql/test/library-tests/Functions/exprclosures.js index 66e0f855744..dd6a10086bd 100644 --- a/javascript/ql/test/library-tests/Functions/exprclosures.js +++ b/javascript/ql/test/library-tests/Functions/exprclosures.js @@ -1,3 +1 @@ a.map(function(x) x+1); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/LocalObjects/tst.js b/javascript/ql/test/library-tests/LocalObjects/tst.js index dee138c0f27..a02a29776c0 100644 --- a/javascript/ql/test/library-tests/LocalObjects/tst.js +++ b/javascript/ql/test/library-tests/LocalObjects/tst.js @@ -89,5 +89,3 @@ let bound = {}; bound::unknown(); }); - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/b.js b/javascript/ql/test/library-tests/Modules/b.js index 4b58c09c31b..835bd1abbf6 100644 --- a/javascript/ql/test/library-tests/Modules/b.js +++ b/javascript/ql/test/library-tests/Modules/b.js @@ -5,5 +5,3 @@ f(); export { f as g }; export f2 from './a'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/c.js b/javascript/ql/test/library-tests/Modules/m/c.js index 6c3645f382d..8192ccc9b45 100644 --- a/javascript/ql/test/library-tests/Modules/m/c.js +++ b/javascript/ql/test/library-tests/Modules/m/c.js @@ -3,5 +3,3 @@ import * as b from '../b'; b.g(); export { g as h } from '../b'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/tests.expected b/javascript/ql/test/library-tests/Modules/tests.expected index 8cdd45f9066..39d24b09700 100644 --- a/javascript/ql/test/library-tests/Modules/tests.expected +++ b/javascript/ql/test/library-tests/Modules/tests.expected @@ -104,15 +104,15 @@ test_Module_exports | a.js:1:1:5:32 | | default | a.js:1:1:3:1 | export ... n 23;\\n} | | a.js:1:1:5:32 | | x | a.js:5:1:5:32 | export ... } = o; | | a.js:1:1:5:32 | | y | a.js:5:1:5:32 | export ... } = o; | -| b.js:1:1:10:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | -| b.js:1:1:10:0 | | g | b.js:5:1:5:18 | export { f as g }; | +| b.js:1:1:8:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | +| b.js:1:1:8:0 | | g | b.js:5:1:5:18 | export { f as g }; | | e.js:1:1:4:0 | | g | e.js:3:1:3:35 | export ... './a'; | | e.js:1:1:4:0 | | x | e.js:2:1:2:16 | export { x, y }; | | e.js:1:1:4:0 | | y | e.js:2:1:2:16 | export { x, y }; | | es2015_require.js:1:1:3:25 | | default | es2015_require.js:3:1:3:25 | export ... ss C {} | | export-in-mjs.mjs:1:1:1:34 | | exported_from_mjs | export-in-mjs.mjs:1:1:1:34 | export ... s = 42; | | f.ts:1:1:6:0 | | foo | f.ts:5:1:5:24 | export ... oo() {} | -| m/c.js:1:1:8:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | +| m/c.js:1:1:6:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | | tst.html:4:23:8:0 | | y | tst.html:7:3:7:22 | export const y = 42; | test_ExportDefaultDeclarations | a.js:1:1:3:1 | export ... n 23;\\n} | diff --git a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js index 97576676994..7367e64dd4c 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js +++ b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js @@ -13,4 +13,3 @@ DUMP(o3); DUMP(o4); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/tst.js b/javascript/ql/test/library-tests/OptionalChaining/tst.js index b0ee7435722..39389024d6d 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/OptionalChaining/tst.js @@ -13,5 +13,3 @@ a?.m().b; a.m?.().b; a.m()?.b; a?.m?.()?.b; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/tst.js b/javascript/ql/test/library-tests/ThisExpr/tst.js index 418021624e7..316e3feb1de 100644 --- a/javascript/ql/test/library-tests/ThisExpr/tst.js +++ b/javascript/ql/test/library-tests/ThisExpr/tst.js @@ -146,4 +146,3 @@ class C_lodash { } } -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js index 6c3458781a1..28d7e45c44e 100644 --- a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js @@ -21,4 +21,3 @@ v7 = x ?? {}; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js index 4890c8335cc..42747617b6b 100644 --- a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js @@ -22,4 +22,3 @@ var v11 = h(); var v12 = h?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js index df115aac5b8..697bc35c150 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js @@ -11,5 +11,3 @@ class Reads extends React.Component { prevState.p4; } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js index 4f15d9a1b31..692400c7381 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js @@ -43,5 +43,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/stmts/foreach.js b/javascript/ql/test/library-tests/stmts/foreach.js index ee6fd60e59b..1df30053437 100644 --- a/javascript/ql/test/library-tests/stmts/foreach.js +++ b/javascript/ql/test/library-tests/stmts/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/guardedCatch.js b/javascript/ql/test/library-tests/stmts/guardedCatch.js index 2c9a24cdb07..0c7b4c2b890 100644 --- a/javascript/ql/test/library-tests/stmts/guardedCatch.js +++ b/javascript/ql/test/library-tests/stmts/guardedCatch.js @@ -7,5 +7,3 @@ function f(g) { console.log("something else!"); } } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/jscript.js b/javascript/ql/test/library-tests/stmts/jscript.js index 6e281fcec08..0f6a81c8fb3 100644 --- a/javascript/ql/test/library-tests/stmts/jscript.js +++ b/javascript/ql/test/library-tests/stmts/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/legacyletstmt.js b/javascript/ql/test/library-tests/stmts/legacyletstmt.js index e88411c12c1..89b5e7505e9 100644 --- a/javascript/ql/test/library-tests/stmts/legacyletstmt.js +++ b/javascript/ql/test/library-tests/stmts/legacyletstmt.js @@ -1,5 +1,3 @@ let (x = 23, y = 19) { console.log(x + y); } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected index 158f001459c..bf97e07b559 100644 --- a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected +++ b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected @@ -24,7 +24,7 @@ | x | defaultargs.js:3:3:3:25 | functio ... = x) {} | | x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | | x | for.js:1:2:5:1 | functio ... x;\\n} | -| x | legacyletstmt.js:1:1:9:42 | | +| x | legacyletstmt.js:1:1:8:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | @@ -36,7 +36,7 @@ | x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | | y | defaultargs.js:3:3:3:25 | functio ... = x) {} | | y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| y | legacyletstmt.js:1:1:9:42 | | +| y | legacyletstmt.js:1:1:8:0 | | | y | let.js:1:1:22:0 | | | y | let.js:14:1:21:1 | functio ... }\\n} | | y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | diff --git a/javascript/ql/test/library-tests/variables/legacyletstmt.js b/javascript/ql/test/library-tests/variables/legacyletstmt.js index 07531d1cc9c..69beaac8a09 100644 --- a/javascript/ql/test/library-tests/variables/legacyletstmt.js +++ b/javascript/ql/test/library-tests/variables/legacyletstmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js index 6b5cc4cc2d8..22e649c68c6 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js @@ -3,5 +3,3 @@ var x = 42; class C { myX = x } - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js index b3210a08775..ce0a9ddfd0f 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js @@ -2,5 +2,3 @@ function test(bar, e) { let foo = bar; e.target::foo::baz(); } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js index d4e6de4b3ba..3f0516d2266 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js @@ -2,5 +2,3 @@ function f(o) { let { x, ...ys } = o; return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js index 46199104674..f500d4cdafc 100644 --- a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js @@ -232,5 +232,3 @@ function l() { function f(...x) { x === 42 }; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js index e1ef6f1cdfd..a454ed9bde3 100644 --- a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js @@ -107,4 +107,3 @@ function l() { g(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js index 356d0cf57ee..a8cedd993b2 100644 --- a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js @@ -1,4 +1,2 @@ var n = 1<<40; // NOT OK var n2 = BigInt(1) << 40n; // OK - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js index 23651d79e6c..01a0c35bc5b 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js @@ -3,5 +3,3 @@ class A { } class B {} - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js index 2df3535216a..9be73a4dde5 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js @@ -7,4 +7,3 @@ b(); b?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js index 9f662507227..fa6003ad795 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js @@ -7,4 +7,3 @@ b.p; b?.p; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js index ae0bcba2a23..c0cd2619e81 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js @@ -4,5 +4,3 @@ function outer() { } inner().next() } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js index 6733344c3ba..6657556b072 100644 --- a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js @@ -172,5 +172,3 @@ class Component4 extends React.Component { this.setState({ }); } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js index 0095642669c..1df30053437 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js index 373939cae64..0f6a81c8fb3 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js index 51e8fd38fda..a5c7a09b6be 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js @@ -3,5 +3,3 @@ var x = 42, y = 19; console.log(let (x = 23, y = 19) x + y); console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js index 07531d1cc9c..69beaac8a09 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js index bb08a86ceec..3cca1b5c615 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js @@ -2,5 +2,3 @@ var numbers = [1, 2, 3, 4, 5]; var squares = [i*i for (i of numbers)]; var specialKeyCodes = [for (keyCodeName of Object.keys(SPECIAL_CODES_MAP)) SPECIAL_CODES_MAP[keyCodeName]]; - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js index dbfeda687e0..202ea2a262a 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js @@ -6,5 +6,3 @@ // OK [1, 2, 3].map((x) => x * x); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js index 30135633974..08542e2be52 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js @@ -1,4 +1,2 @@ var a = [23,,42]; var desc = [for(i in a) i + " = a[" + i + "]"]; - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js index 66a296a0ae8..5e9b07cf675 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js @@ -23,5 +23,3 @@ foo(); foo(); foo(); foo(); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js index 5081e9991d1..a68f3ad35f9 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js @@ -4,6 +4,3 @@ function idMaker(){ // NOT OK yield index++; } - -//semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js index f1adc83643f..0d4d465638d 100644 --- a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js @@ -11,5 +11,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js index 7d5a881389c..f5acdc8d99a 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js @@ -19,5 +19,3 @@ class C2 extends React.Component { const { p1: p2 } = state } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js index dda64bc62e8..6db5702e2fc 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js @@ -166,5 +166,3 @@ class C11 extends React.Component { this.state.writeIn_getDerivedStateFromProps; // OK } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js index e1972ddec1f..d71aa7136da 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js @@ -72,5 +72,3 @@ class C6 extends React.Component { } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js index 8731ac0cfac..a3e429ed0b5 100644 --- a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js @@ -176,5 +176,3 @@ async function awaitFlow(){ if (v) { // OK } }); - -// semmle-extractor-options: --experimental From 2e7bd4db6f163b3d19eda68fab2b460dc8f43196 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 6 Nov 2019 12:59:45 +0000 Subject: [PATCH 159/232] Update docs/language/ql-training/cpp/program-representation-cpp.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-training/cpp/program-representation-cpp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 8f7a4d43de9..7048251aa02 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by CodeQL class ``Call`` and its subclasses: +Calls to functions are modeled by the CodeQL class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function From 79f107946068940e7050b1ed3bc52abf54c48ac8 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 13:01:23 +0000 Subject: [PATCH 160/232] JavaScript: Add `options` files with `--experimental` extractor options. --- javascript/ql/test/library-tests/CFG/options | 1 + javascript/ql/test/library-tests/Classes/options | 1 + javascript/ql/test/library-tests/Comprehensions/options | 1 + javascript/ql/test/library-tests/DataFlow/options | 1 + javascript/ql/test/library-tests/Decorators/options | 1 + javascript/ql/test/library-tests/DefUse/options | 1 + javascript/ql/test/library-tests/Expr/options | 1 + javascript/ql/test/library-tests/Flow/options | 1 + javascript/ql/test/library-tests/Flow/reexport/lib/options | 1 + javascript/ql/test/library-tests/Functions/options | 1 + javascript/ql/test/library-tests/LocalObjects/options | 1 + javascript/ql/test/library-tests/Modules/m/options | 1 + javascript/ql/test/library-tests/Modules/options | 1 + javascript/ql/test/library-tests/OptionalChaining/options | 1 + javascript/ql/test/library-tests/ThisExpr/options | 1 + .../test/library-tests/TypeInference/NullishCoalescing/options | 1 + .../ql/test/library-tests/TypeInference/OptionalChaining/options | 1 + javascript/ql/test/library-tests/frameworks/ReactJS/options | 1 + javascript/ql/test/library-tests/stmts/options | 1 + javascript/ql/test/library-tests/variables/options | 1 + .../ql/test/query-tests/Declarations/DeadStoreOfLocal/options | 1 + .../ql/test/query-tests/Declarations/UnusedVariable/options | 1 + .../test/query-tests/Expressions/HeterogeneousComparison/options | 1 + .../query-tests/Expressions/ImplicitOperandConversion/options | 1 + .../ql/test/query-tests/Expressions/ShiftOutOfRange/options | 1 + .../ql/test/query-tests/Expressions/SuspiciousInvocation/options | 1 + .../ql/test/query-tests/Expressions/SuspiciousPropAccess/options | 1 + .../query-tests/Expressions/UnboundEventHandlerReceiver/options | 1 + .../test/query-tests/LanguageFeatures/ExpressionClosures/options | 1 + .../LanguageFeatures/ForInComprehensionBlocks/options | 1 + .../test/query-tests/LanguageFeatures/SemicolonInsertion/options | 1 + .../query-tests/LanguageFeatures/YieldInNonGenerator/options | 1 + javascript/ql/test/query-tests/React/DirectStateMutation/options | 1 + .../query-tests/React/UnusedOrUndefinedStateProperty/options | 1 + .../ql/test/query-tests/Statements/UselessConditional/options | 1 + 35 files changed, 35 insertions(+) create mode 100644 javascript/ql/test/library-tests/CFG/options create mode 100644 javascript/ql/test/library-tests/Classes/options create mode 100644 javascript/ql/test/library-tests/Comprehensions/options create mode 100644 javascript/ql/test/library-tests/DataFlow/options create mode 100644 javascript/ql/test/library-tests/Decorators/options create mode 100644 javascript/ql/test/library-tests/DefUse/options create mode 100644 javascript/ql/test/library-tests/Expr/options create mode 100644 javascript/ql/test/library-tests/Flow/options create mode 100644 javascript/ql/test/library-tests/Flow/reexport/lib/options create mode 100644 javascript/ql/test/library-tests/Functions/options create mode 100644 javascript/ql/test/library-tests/LocalObjects/options create mode 100644 javascript/ql/test/library-tests/Modules/m/options create mode 100644 javascript/ql/test/library-tests/Modules/options create mode 100644 javascript/ql/test/library-tests/OptionalChaining/options create mode 100644 javascript/ql/test/library-tests/ThisExpr/options create mode 100644 javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options create mode 100644 javascript/ql/test/library-tests/TypeInference/OptionalChaining/options create mode 100644 javascript/ql/test/library-tests/frameworks/ReactJS/options create mode 100644 javascript/ql/test/library-tests/stmts/options create mode 100644 javascript/ql/test/library-tests/variables/options create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options create mode 100644 javascript/ql/test/query-tests/Declarations/UnusedVariable/options create mode 100644 javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options create mode 100644 javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options create mode 100644 javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options create mode 100644 javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options create mode 100644 javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options create mode 100644 javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options create mode 100644 javascript/ql/test/query-tests/React/DirectStateMutation/options create mode 100644 javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options create mode 100644 javascript/ql/test/query-tests/Statements/UselessConditional/options diff --git a/javascript/ql/test/library-tests/CFG/options b/javascript/ql/test/library-tests/CFG/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/CFG/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Classes/options b/javascript/ql/test/library-tests/Classes/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Classes/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Comprehensions/options b/javascript/ql/test/library-tests/Comprehensions/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Comprehensions/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DataFlow/options b/javascript/ql/test/library-tests/DataFlow/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/DataFlow/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Decorators/options b/javascript/ql/test/library-tests/Decorators/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Decorators/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DefUse/options b/javascript/ql/test/library-tests/DefUse/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/DefUse/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Expr/options b/javascript/ql/test/library-tests/Expr/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Expr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/options b/javascript/ql/test/library-tests/Flow/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/options b/javascript/ql/test/library-tests/Flow/reexport/lib/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Functions/options b/javascript/ql/test/library-tests/Functions/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Functions/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/LocalObjects/options b/javascript/ql/test/library-tests/LocalObjects/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/LocalObjects/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/options b/javascript/ql/test/library-tests/Modules/m/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/m/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/options b/javascript/ql/test/library-tests/Modules/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/options b/javascript/ql/test/library-tests/OptionalChaining/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/options b/javascript/ql/test/library-tests/ThisExpr/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/ThisExpr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/options b/javascript/ql/test/library-tests/frameworks/ReactJS/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/stmts/options b/javascript/ql/test/library-tests/stmts/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/stmts/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/variables/options b/javascript/ql/test/library-tests/variables/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/variables/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/options b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/options b/javascript/ql/test/query-tests/React/DirectStateMutation/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/options b/javascript/ql/test/query-tests/Statements/UselessConditional/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental From 1fa8c43a8c4ca2cd8905318634c03e42e7e179f3 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:00:51 +0000 Subject: [PATCH 161/232] JavaScript: Remove a redundant extractor option. --- javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js index abf7cc4034f..8eb1794ae7b 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js @@ -3,5 +3,3 @@ class C { } module.exports = C; - -// semmle-extractor-options: --abort-on-parse-errors \ No newline at end of file From 48483724358022cf3df1494bfb316d5a04ddac7d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:09:17 +0000 Subject: [PATCH 162/232] JavaScript: Replace `--externs` extractor flag with `/** @externs */` comment. --- javascript/ql/test/library-tests/Externs/Point.js | 2 +- .../test/query-tests/Declarations/ArgumentsRedefined/externs.js | 2 +- .../test/query-tests/Declarations/DeadStoreOfGlobal/externs.js | 2 +- .../query-tests/Declarations/DeadStoreOfProperty/externs.js | 2 +- .../test/query-tests/Declarations/RedeclaredVariable/externs.js | 2 +- .../test/query-tests/Declarations/TooManyParameters/externs.js | 2 +- .../ql/test/query-tests/Declarations/UnusedParameter/externs.js | 2 +- .../ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js | 2 +- .../ql/test/query-tests/Expressions/SelfAssignment/externs.js | 2 +- javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js | 2 +- .../query-tests/LanguageFeatures/InconsistentNew/externs.js | 2 +- .../SemicolonInsertion/SemicolonInsertion.expected | 2 +- .../query-tests/LanguageFeatures/SpuriousArguments/externs.js | 2 +- .../query-tests/NodeJS/DubiousImport/DubiousImport.expected | 2 +- javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js | 2 +- .../ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js | 2 +- javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/javascript/ql/test/library-tests/Externs/Point.js b/javascript/ql/test/library-tests/Externs/Point.js index a811a482009..ea4c950e7d2 100644 --- a/javascript/ql/test/library-tests/Externs/Point.js +++ b/javascript/ql/test/library-tests/Externs/Point.js @@ -17,4 +17,4 @@ Point.prototype['final']; /** @type {!Point} */ var aPoint; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js index f91c316b0ed..7824a7ffe02 100644 --- a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js +++ b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js @@ -1,3 +1,3 @@ var arguments; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js index d3594220a05..6e79be49a81 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js @@ -38,4 +38,4 @@ function Worker(opt_arg0) {} */ Worker.prototype.onmessage = function() {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js index a32e349e56d..11caae4e1b1 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js @@ -40,4 +40,4 @@ function Element() {} */ Element.prototype.clientTop; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js index 19dd15789e9..0a9eab06996 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js @@ -2,4 +2,4 @@ var f = function() {}; var f = function(x) {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js index a3c8c8999c0..4327b4885f5 100644 --- a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js +++ b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js @@ -1,4 +1,4 @@ // OK: overly long parameter lists in external APIs aren't the fault of the externs definitions function f(a, b, c, d, e, f, g, h) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js index ec8e5c4f6db..9153844b527 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js @@ -1,3 +1,3 @@ function String(str) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js index d3fff886259..98a1d68e520 100644 --- a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js +++ b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js @@ -53,4 +53,4 @@ function Error() {} */ function SyntaxError() {} -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js index 70685e250c1..58b2c99e892 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js @@ -36,4 +36,4 @@ function Element() {} Element.prototype.innerHTML; -// semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js index f27d6054e27..433db5a26f4 100644 --- a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js +++ b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js @@ -3,4 +3,4 @@ */ function f(x) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js index c81b555e5aa..0ffbf63dd3f 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js @@ -7,4 +7,4 @@ String.prototype.toString = function() {}; function Array() {} Array.prototype.toString = function() {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected index 81808eb76ba..bab6488e83b 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected @@ -1,4 +1,4 @@ | export.js:5:8:5:17 | var x = 42 | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | export.js:1:1:29:0 | | the enclosing script | -| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:27:42 | | the enclosing script | +| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:26:0 | | the enclosing script | | tst.js:5:1:5:3 | var a = ... : 2\\n } | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | | tst.js:7:3:7:10 | return 1 | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js index cf8665ea531..c8a88126efb 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js @@ -39,4 +39,4 @@ function Number() {} Number.parseFloat = function(num) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected index e28c1641af8..88425eed728 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected @@ -1,5 +1,5 @@ | a.js:1:11:1:28 | require('./b').foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:5:1:5:5 | b.foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:15:1:15:9 | fs.renmae | Module $@ does not export symbol renmae. | fs.js:1:1:15:0 | | fs | -| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:7:52 | | l | +| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:6:0 | | l | | multi_import.js:16:3:16:10 | mod2.bar | Module $@ does not export symbol bar. | b.js:1:1:5:21 | | b | diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js index f1cb91159f0..bd8e36c10e3 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js @@ -615,4 +615,4 @@ Array.some = function(arr, callback, opt_context) {}; */ Array.isArray = function(arr) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js index e4c633ecf31..fefe8f6b2e7 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js @@ -2,4 +2,4 @@ var fs = require('fs'); fs.move = fs.rename; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js index 9fc7f5f1343..7b5e87d891a 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js @@ -11,4 +11,4 @@ fs.rename; module.exports = fs; -//semmle-extractor-options: --externs +/** @externs */ From 8fdf6298b980e7426e026fbdd6365a2478e94026 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:14:07 +0000 Subject: [PATCH 163/232] JavaScript: Remove `--platform node` extractor options. --- javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js | 3 +-- .../ql/test/query-tests/NodeJS/UnusedDependency/src/other.js | 2 -- .../ql/test/query-tests/Security/CWE-089/untyped/tst4.js | 2 -- .../test/query-tests/Statements/ReturnOutsideFunction/node.js | 3 +-- .../test/tutorials/Introducing the JavaScript libraries/m.js | 4 ++-- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js index 3d097fb8ede..c475ea2262f 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js @@ -4,5 +4,4 @@ module.exports = me; }(module)); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); // ensure this is treated as Node.js code diff --git a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js index 20c9961d626..3b29030a26f 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js +++ b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js @@ -1,4 +1,2 @@ import hipsterness from 'react'; import curry from 'lodash/function/curry'; - -//semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js index 7df5c6b4f3f..73cddfb3a6a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js @@ -7,5 +7,3 @@ angular.module('myApp', ['ngRoute']) .controller('FindPost', function($routeParams) { db.get('SELECT * FROM Post WHERE id = "' + $routeParams.id + '"'); }); - -// semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js index 3397ebd38a4..572dbe25035 100644 --- a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js +++ b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js @@ -1,5 +1,4 @@ // not a syntax error, but still NOT OK return 42; -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("path") // ensure this is treated as Node.js code diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js index c53a0a15327..a54fda636cc 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js @@ -1,2 +1,2 @@ -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process") +; From 5681565d4addcc24fefabfd19737f4e686c887e0 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:20:23 +0000 Subject: [PATCH 164/232] JavaScript: Move `--html elements` extractor options into `options` file. --- .../ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html | 1 - .../ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html | 1 - .../ql/test/query-tests/DOM/HTML/ConflictingAttributes.html | 1 - .../ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html | 1 - javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html | 1 - .../ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html | 1 - .../ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html | 1 - .../ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html | 1 - javascript/ql/test/query-tests/DOM/HTML/options | 1 + 9 files changed, 1 insertion(+), 8 deletions(-) create mode 100644 javascript/ql/test/query-tests/DOM/HTML/options diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html index 3277461d787..98a490ec408 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html @@ -4,5 +4,4 @@
  • First element
  • Second element -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html index 7800cfcd048..bb5969c1f79 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html @@ -10,5 +10,4 @@
  • duplicate-class
  • duplicate-class
  • -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html index 370337bc7af..92af95c3e3c 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html index 9b6a94b0e2d..dfe1141a21b 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html index eedc176211b..a78e3314283 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html index 9b6a94b0e2d..dfe1141a21b 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html index 666592a7716..9da8fcde502 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html index 9a7815efb64..1dfea0491fe 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/options b/javascript/ql/test/query-tests/DOM/HTML/options new file mode 100644 index 00000000000..49be7a9261e --- /dev/null +++ b/javascript/ql/test/query-tests/DOM/HTML/options @@ -0,0 +1 @@ +semmle-extractor-options: --html elements From 6b817203fdcc89c58022d856d07198d8579d244a Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:24:52 +0000 Subject: [PATCH 165/232] JavaScript: Move `--tolerate-parse-errors` extractor options into `options` file. --- javascript/ql/test/library-tests/Errors/options | 1 + javascript/ql/test/library-tests/Errors/setters.js | 2 -- javascript/ql/test/library-tests/Errors/tst.js | 2 -- javascript/ql/test/library-tests/JSON/JSONError.expected | 1 - javascript/ql/test/library-tests/JSON/invalid.json | 1 - javascript/ql/test/library-tests/JSON/options | 1 + .../ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts | 2 -- .../ql/test/library-tests/TypeScript/SyntaxErrors/options | 1 + javascript/ql/test/library-tests/YAML/YAMLError.expected | 2 +- javascript/ql/test/library-tests/YAML/err.yaml | 1 - javascript/ql/test/library-tests/YAML/options | 1 + javascript/ql/test/library-tests/frameworks/Express/options | 1 + .../ql/test/query-tests/AngularJS/DuplicateDependency/options | 1 + .../test/query-tests/Declarations/UniqueParameterNames/options | 1 + .../test/query-tests/Declarations/UniqueParameterNames/tst.js | 2 -- .../ql/test/query-tests/LanguageFeatures/SyntaxError/options | 1 + .../ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js | 2 -- javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js | 2 -- javascript/ql/test/query-tests/filters/ClassifyFiles/options | 1 + .../test/query-tests/filters/ClassifyFiles/some-template.html | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html | 1 - .../test/tutorials/Introducing the JavaScript libraries/options | 1 + 24 files changed, 11 insertions(+), 20 deletions(-) create mode 100644 javascript/ql/test/library-tests/Errors/options create mode 100644 javascript/ql/test/library-tests/JSON/options create mode 100644 javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options create mode 100644 javascript/ql/test/library-tests/YAML/options create mode 100644 javascript/ql/test/library-tests/frameworks/Express/options create mode 100644 javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options create mode 100644 javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/options create mode 100644 javascript/ql/test/tutorials/Introducing the JavaScript libraries/options diff --git a/javascript/ql/test/library-tests/Errors/options b/javascript/ql/test/library-tests/Errors/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/Errors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/setters.js b/javascript/ql/test/library-tests/Errors/setters.js index 50865e9f0c9..a8d40c45d2f 100644 --- a/javascript/ql/test/library-tests/Errors/setters.js +++ b/javascript/ql/test/library-tests/Errors/setters.js @@ -8,5 +8,3 @@ var o = { set y(...ys) {}, set z(z, ...zs) {} }; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/tst.js b/javascript/ql/test/library-tests/Errors/tst.js index baf2fbf4711..f0931ee0e49 100644 --- a/javascript/ql/test/library-tests/Errors/tst.js +++ b/javascript/ql/test/library-tests/Errors/tst.js @@ -1,4 +1,2 @@ while } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/JSON/JSONError.expected b/javascript/ql/test/library-tests/JSON/JSONError.expected index 37d5aabfd08..e63d3862491 100644 --- a/javascript/ql/test/library-tests/JSON/JSONError.expected +++ b/javascript/ql/test/library-tests/JSON/JSONError.expected @@ -1,2 +1 @@ | invalid.json:3:1:3:1 | Error: Comments are not legal in JSON. | -| invalid.json:4:1:4:1 | Error: Comments are not legal in JSON. | diff --git a/javascript/ql/test/library-tests/JSON/invalid.json b/javascript/ql/test/library-tests/JSON/invalid.json index 54c870bb907..03f76948f63 100644 --- a/javascript/ql/test/library-tests/JSON/invalid.json +++ b/javascript/ql/test/library-tests/JSON/invalid.json @@ -1,4 +1,3 @@ "hi" // JSON doesn't have comments -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/JSON/options b/javascript/ql/test/library-tests/JSON/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/JSON/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts index 6bba445dce4..55716a17a65 100644 --- a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts @@ -23,5 +23,3 @@ var nns: Array; var dns: Array; var anys: Array<*>; var vars: Array<...number>; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/YAMLError.expected b/javascript/ql/test/library-tests/YAML/YAMLError.expected index 2045e49be51..386d8874ef2 100644 --- a/javascript/ql/test/library-tests/YAML/YAMLError.expected +++ b/javascript/ql/test/library-tests/YAML/YAMLError.expected @@ -1 +1 @@ -| err.yaml:4:1:4:1 | found unexpected end of stream | +| err.yaml:3:1:3:1 | found unexpected end of stream | diff --git a/javascript/ql/test/library-tests/YAML/err.yaml b/javascript/ql/test/library-tests/YAML/err.yaml index f6d3951be96..96d2d75ddc0 100644 --- a/javascript/ql/test/library-tests/YAML/err.yaml +++ b/javascript/ql/test/library-tests/YAML/err.yaml @@ -1,3 +1,2 @@ "unterminated string -# semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/options b/javascript/ql/test/library-tests/YAML/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/YAML/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/frameworks/Express/options b/javascript/ql/test/library-tests/frameworks/Express/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Express/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js index 2d543e5bf1b..470b14e8300 100644 --- a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js @@ -12,5 +12,3 @@ this.addPropertyListener(prop.name, function(_, _, _, a) { function f(x, y, x) { 'use strict'; } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js index 2da4e693aeb..e7aaa89f128 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js @@ -1,4 +1,2 @@ function findBox() { return $("box.important - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js index ba9b39b4f72..5d56c9b782e 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js @@ -1,3 +1 @@ 😼😼 - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/options b/javascript/ql/test/query-tests/filters/ClassifyFiles/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html index 734e6cf7da8..671a0c7b51b 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html @@ -1,4 +1,3 @@ -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js index 1a42f3cf925..cda21380525 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js @@ -3,4 +3,3 @@ common.autofocus('#id_password'); {% else %} common.autofocus('#id_username'); {% endif %} -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html index c21d85208f5..e3bdc744425 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html @@ -5,4 +5,3 @@ common.autofocus('#id_password'); common.autofocus('#id_username'); {% endif %} -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html index 8e96a8b41f4..700fe9c08d2 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html @@ -5,4 +5,3 @@ {{/config}} } -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options new file mode 100644 index 00000000000..a1b2b21840f --- /dev/null +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors \ No newline at end of file From 3ad5af7ceff7a942277bb5ef0a42b09cdf21c1a2 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:44:57 +0000 Subject: [PATCH 166/232] JavaScript: Move `--extract-program-text` extractor options into `options` files. --- .../test/library-tests/Lines/Lines.expected | 10 ++-- .../ql/test/library-tests/Lines/options | 1 + .../ql/test/library-tests/Lines/tst1.js | 4 +- .../ql/test/library-tests/Lines/tst2.js | 2 +- .../ql/test/library-tests/Lines/tst3.js | 4 +- .../TypeScript/Modifiers/options | 1 + .../library-tests/TypeScript/Modifiers/tst.ts | 2 - .../test/library-tests/stmts/conditionals.js | 2 +- .../ql/test/library-tests/stmts/es2015.js | 2 +- .../ql/test/library-tests/stmts/functions.js | 2 +- .../ql/test/library-tests/stmts/loops.js | 2 +- .../ql/test/library-tests/stmts/options | 2 +- .../ql/test/library-tests/stmts/others.js | 2 +- .../test/library-tests/stmts/tests.expected | 51 +++++++++---------- javascript/ql/test/library-tests/stmts/try.js | 2 +- 15 files changed, 43 insertions(+), 46 deletions(-) create mode 100644 javascript/ql/test/library-tests/Lines/options create mode 100644 javascript/ql/test/library-tests/TypeScript/Modifiers/options diff --git a/javascript/ql/test/library-tests/Lines/Lines.expected b/javascript/ql/test/library-tests/Lines/Lines.expected index 552c1b8ff0e..e3c7973c9b8 100644 --- a/javascript/ql/test/library-tests/Lines/Lines.expected +++ b/javascript/ql/test/library-tests/Lines/Lines.expected @@ -1,4 +1,4 @@ -| tst1.js:1:1:1:55 | abc // semmle-extractor-options: --extract-program-text | abc // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:1:1:1:3 | abc | abc | \n | | tst1.js:2:1:2:3 | def | def | \r | | tst1.js:3:1:3:3 | ghi | ghi | \r\n | | tst1.js:4:1:4:3 | jkl | jkl | \n | @@ -6,13 +6,13 @@ | tst1.js:6:1:6:3 | mno | mno | \u2028 | | tst1.js:7:1:7:0 | | | \n | | tst1.js:8:1:8:3 | pqr | pqr | \u2029 | -| tst1.js:9:1:9:3 | stu | stu | | -| tst2.js:1:1:1:63 | first_line // semmle-extractor-options: --extract-program-text | first_line // semmle-extractor-options: --extract-program-text | \n | -| tst3.js:1:1:1:56 | 42; // semmle-extractor-options: --extract-program-text | 42; // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:9:1:9:3 | stu | stu | \n | +| tst2.js:1:1:1:10 | first_line | first_line | \n | +| tst3.js:1:1:1:3 | 42; | 42; | \n | | tst3.js:2:1:2:4 | \t42; | \t42; | \n | | tst3.js:3:1:3:5 | \t\t42; | \t\t42; | \n | | tst3.js:4:1:4:6 | \t\t\t42; | \t\t\t42; | \n | | tst3.js:5:1:5:6 | \t\t 42; | \t\t 42; | \n | | tst3.js:6:1:6:6 | \t \t42; | \t \t42; | \n | | tst3.js:7:1:7:7 | 42; | 42; | \n | -| tst3.js:8:1:8:5 | 42; | 42; | | +| tst3.js:8:1:8:5 | 42; | 42; | \n | diff --git a/javascript/ql/test/library-tests/Lines/options b/javascript/ql/test/library-tests/Lines/options new file mode 100644 index 00000000000..d51f2d49be2 --- /dev/null +++ b/javascript/ql/test/library-tests/Lines/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/Lines/tst1.js b/javascript/ql/test/library-tests/Lines/tst1.js index f10f44a7440..d5fa50c5f3a 100644 --- a/javascript/ql/test/library-tests/Lines/tst1.js +++ b/javascript/ql/test/library-tests/Lines/tst1.js @@ -1,5 +1,5 @@ -abc // semmle-extractor-options: --extract-program-text +abc def ghi jkl mno
 -pqr
stu \ No newline at end of file +pqr
stu diff --git a/javascript/ql/test/library-tests/Lines/tst2.js b/javascript/ql/test/library-tests/Lines/tst2.js index d3c77609145..c380edd400c 100644 --- a/javascript/ql/test/library-tests/Lines/tst2.js +++ b/javascript/ql/test/library-tests/Lines/tst2.js @@ -1 +1 @@ -first_line // semmle-extractor-options: --extract-program-text +first_line diff --git a/javascript/ql/test/library-tests/Lines/tst3.js b/javascript/ql/test/library-tests/Lines/tst3.js index ad0059d91ea..8c8468ffab2 100644 --- a/javascript/ql/test/library-tests/Lines/tst3.js +++ b/javascript/ql/test/library-tests/Lines/tst3.js @@ -1,8 +1,8 @@ -42; // semmle-extractor-options: --extract-program-text +42; 42; 42; 42; 42; 42; 42; - 42; \ No newline at end of file + 42; diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/options b/javascript/ql/test/library-tests/TypeScript/Modifiers/options new file mode 100644 index 00000000000..d51f2d49be2 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts index a56c724cf57..615a36ae6e5 100644 --- a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts @@ -113,5 +113,3 @@ interface InterfaceFields { z?: number; readonly w?: number; } - -// semmle-extractor-options: --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/conditionals.js b/javascript/ql/test/library-tests/stmts/conditionals.js index 12562b2881f..e21a4299f87 100644 --- a/javascript/ql/test/library-tests/stmts/conditionals.js +++ b/javascript/ql/test/library-tests/stmts/conditionals.js @@ -1,4 +1,4 @@ -if (true) // semmle-extractor-options: --extract-program-text +if (true) ; if (b) ; diff --git a/javascript/ql/test/library-tests/stmts/es2015.js b/javascript/ql/test/library-tests/stmts/es2015.js index 6264c54a04f..09a501be36b 100644 --- a/javascript/ql/test/library-tests/stmts/es2015.js +++ b/javascript/ql/test/library-tests/stmts/es2015.js @@ -1,2 +1,2 @@ -for (var x of [1, 2, 3]) // semmle-extractor-options: --extract-program-text +for (var x of [1, 2, 3]) console.log(x); diff --git a/javascript/ql/test/library-tests/stmts/functions.js b/javascript/ql/test/library-tests/stmts/functions.js index f1ac615a040..20ecacefad5 100644 --- a/javascript/ql/test/library-tests/stmts/functions.js +++ b/javascript/ql/test/library-tests/stmts/functions.js @@ -1,4 +1,4 @@ -function g(x, y) { // semmle-extractor-options: --extract-program-text +function g(x, y) { return x+y; } diff --git a/javascript/ql/test/library-tests/stmts/loops.js b/javascript/ql/test/library-tests/stmts/loops.js index e2a63b3e3f9..6d424254d74 100644 --- a/javascript/ql/test/library-tests/stmts/loops.js +++ b/javascript/ql/test/library-tests/stmts/loops.js @@ -1,4 +1,4 @@ -while(true) // semmle-extractor-options: --extract-program-text +while(true) ; outer: for(a; b; c) { for(;;) diff --git a/javascript/ql/test/library-tests/stmts/options b/javascript/ql/test/library-tests/stmts/options index ae107b46f9e..7b186f72cc5 100644 --- a/javascript/ql/test/library-tests/stmts/options +++ b/javascript/ql/test/library-tests/stmts/options @@ -1 +1 @@ -semmle-extractor-options: --experimental +semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/others.js b/javascript/ql/test/library-tests/stmts/others.js index 58d6c5c1709..3b2a62a47bf 100644 --- a/javascript/ql/test/library-tests/stmts/others.js +++ b/javascript/ql/test/library-tests/stmts/others.js @@ -1,4 +1,4 @@ -with(a) { // semmle-extractor-options: --extract-program-text +with(a) { } debugger; var x = 23, y; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/tests.expected b/javascript/ql/test/library-tests/stmts/tests.expected index c4632fbc065..75d6f0a24b4 100644 --- a/javascript/ql/test/library-tests/stmts/tests.expected +++ b/javascript/ql/test/library-tests/stmts/tests.expected @@ -4,14 +4,11 @@ test_LetStmt test_LineTerminators | conditionals.js:12:1:12:1 | } | | functions.js:9:1:9:1 | } | -| guardedCatch.js:11:1:11:65 | //semmle-extractor-options: --experimental --extract-program-text | -| jscript.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | -| legacyletstmt.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | | loops.js:22:1:22:18 | for (x = 0 in xs); | | others.js:4:1:4:14 | var x = 23, y; | | try.js:5:1:5:29 | try {} catch(x) {} finally {} | test_EnclosingStmt -| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (tru ... t\\n ; | +| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (true)\\n ; | | conditionals.js:3:5:3:5 | b | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | | conditionals.js:7:9:7:9 | b | conditionals.js:7:1:12:1 | switch ... ault:\\n} | | conditionals.js:8:6:8:7 | 23 | conditionals.js:8:1:8:8 | case 23: | @@ -96,7 +93,7 @@ test_EnclosingStmt | legacyletstmt.js:2:15:2:15 | x | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:15:2:19 | x + y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:19:2:19 | y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | -| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(t ... t\\n ; | +| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(true)\\n ; | | loops.js:3:1:3:5 | outer | loops.js:3:1:11:1 | outer: ... inue;\\n} | | loops.js:3:12:3:12 | a | loops.js:3:8:11:1 | for(a; ... inue;\\n} | | loops.js:3:15:3:15 | b | loops.js:3:8:11:1 | for(a; ... inue;\\n} | @@ -129,7 +126,7 @@ test_EnclosingStmt | loops.js:22:6:22:6 | x | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:10:22:10 | 0 | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:15:22:16 | xs | loops.js:22:1:22:18 | for (x = 0 in xs); | -| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) ... -text\\n} | +| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) {\\n} | | others.js:4:5:4:5 | x | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:5:4:10 | x = 23 | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:9:4:10 | 23 | others.js:4:1:4:14 | var x = 23, y; | @@ -140,7 +137,7 @@ test_EnclosingStmt | try.js:5:14:5:14 | x | try.js:5:8:5:18 | catch(x) {} | test_NumCatchClauses | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | 2 | -| try.js:1:1:3:16 | try { / ... ) { ; } | 1 | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | 1 | | try.js:4:1:4:20 | try {} finally { ; } | 0 | | try.js:5:1:5:29 | try {} ... ally {} | 1 | test_DoubleColonMethods @@ -151,7 +148,7 @@ test_SemicolonInsertion test_getGuard | guardedCatch.js:4:4:6:2 | catch ( ... !");\\n\\t} | guardedCatch.js:4:16:4:33 | e instanceof Error | test_Containers -| conditionals.js:1:1:2:5 | if (tru ... t\\n ; | conditionals.js:1:1:12:1 | | +| conditionals.js:1:1:2:5 | if (true)\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:2:5:2:5 | ; | conditionals.js:1:1:12:1 | | | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:4:5:4:5 | ; | conditionals.js:1:1:12:1 | | @@ -164,22 +161,22 @@ test_Containers | es2015.js:1:1:2:16 | for (va ... log(x); | es2015.js:1:1:3:0 | | | es2015.js:1:6:1:10 | var x | es2015.js:1:1:3:0 | | | es2015.js:2:2:2:16 | console.log(x); | es2015.js:1:1:3:0 | | -| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:11:0 | | -| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:11:0 | | -| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:4:11:4:18 | var item | foreach.js:1:1:11:0 | | -| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:11:0 | | -| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:11:0 | | +| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:9:0 | | +| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:9:0 | | +| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:4:11:4:18 | var item | foreach.js:1:1:9:0 | | +| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:9:0 | | +| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:9:0 | | | functions.js:1:1:3:1 | functio ... x+y;\\n} | functions.js:1:1:9:1 | | -| functions.js:1:18:3:1 | { // se ... x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | +| functions.js:1:18:3:1 | {\\n return x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:2:5:2:15 | return x+y; | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:5:1:5:15 | function h() {} | functions.js:1:1:9:1 | | | functions.js:5:14:5:15 | {} | functions.js:5:1:5:15 | function h() {} | | functions.js:7:1:9:1 | k = fun ... turn;\\n} | functions.js:1:1:9:1 | | | functions.js:7:16:9:1 | {\\n return;\\n} | functions.js:7:5:9:1 | functio ... turn;\\n} | | functions.js:8:5:8:11 | return; | functions.js:7:5:9:1 | functio ... turn;\\n} | -| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:11:65 | | +| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:10:0 | | | guardedCatch.js:1:15:9:1 | {\\n\\ttry ... );\\n\\t}\\n} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:6:4:2 | {\\n\\t\\tg();\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | @@ -190,14 +187,14 @@ test_Containers | guardedCatch.js:6:4:8:2 | catch ( ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:6:14:8:2 | {\\n\\t\\tcon ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:7:3:7:33 | console ... lse!"); | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | -| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:1:27:1:28 | {} | jscript.js:1:1:1:28 | functio ... ad() {} | -| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:3:35:3:36 | {} | jscript.js:3:17:3:36 | function onload() {} | -| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:5:65 | | -| loops.js:1:1:2:5 | while(t ... t\\n ; | loops.js:1:1:22:18 | | +| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:4:0 | | +| loops.js:1:1:2:5 | while(true)\\n ; | loops.js:1:1:22:18 | | | loops.js:2:5:2:5 | ; | loops.js:1:1:22:18 | | | loops.js:3:1:11:1 | outer: ... inue;\\n} | loops.js:1:1:22:18 | | | loops.js:3:8:11:1 | for(a; ... inue;\\n} | loops.js:1:1:22:18 | | @@ -223,12 +220,12 @@ test_Containers | loops.js:21:16:21:16 | ; | loops.js:1:1:22:18 | | | loops.js:22:1:22:18 | for (x = 0 in xs); | loops.js:1:1:22:18 | | | loops.js:22:18:22:18 | ; | loops.js:1:1:22:18 | | -| others.js:1:1:2:1 | with(a) ... -text\\n} | others.js:1:1:4:14 | | -| others.js:1:9:2:1 | { // se ... -text\\n} | others.js:1:1:4:14 | | +| others.js:1:1:2:1 | with(a) {\\n} | others.js:1:1:4:14 | | +| others.js:1:9:2:1 | {\\n} | others.js:1:1:4:14 | | | others.js:3:1:3:9 | debugger; | others.js:1:1:4:14 | | | others.js:4:1:4:14 | var x = 23, y; | others.js:1:1:4:14 | | -| try.js:1:1:3:16 | try { / ... ) { ; } | try.js:1:1:5:29 | | -| try.js:1:5:3:1 | { // se ... "!";\\n} | try.js:1:1:5:29 | | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | try.js:1:1:5:29 | | +| try.js:1:5:3:1 | {\\n throw "!";\\n} | try.js:1:1:5:29 | | | try.js:2:5:2:14 | throw "!"; | try.js:1:1:5:29 | | | try.js:3:3:3:16 | catch(x) { ; } | try.js:1:1:5:29 | | | try.js:3:12:3:16 | { ; } | try.js:1:1:5:29 | | diff --git a/javascript/ql/test/library-tests/stmts/try.js b/javascript/ql/test/library-tests/stmts/try.js index 2d82952fbd3..0151114bf84 100644 --- a/javascript/ql/test/library-tests/stmts/try.js +++ b/javascript/ql/test/library-tests/stmts/try.js @@ -1,4 +1,4 @@ -try { // semmle-extractor-options: --extract-program-text +try { throw "!"; } catch(x) { ; } try {} finally { ; } From 725059deea8abccc6a38531fed27e7db47d7a2a7 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 12:08:33 +0000 Subject: [PATCH 167/232] JavaScript: Remove `--source-type module` extractor options. --- .../library-tests/DataFlow/flowStep.expected | 8 ++++---- javascript/ql/test/library-tests/DataFlow/tst.ts | 4 +--- .../library-tests/Flow/AbstractValues.expected | 16 ++++++++-------- javascript/ql/test/library-tests/Flow/tst.ts | 4 +--- .../InterProceduralFlow/callback.js | 2 +- .../InterProceduralFlow/properties2.js | 2 +- .../library-tests/NPM/ImportedModule.expected | 10 +++++----- .../ql/test/library-tests/NPM/Modules.expected | 6 +++--- .../NPM/NPMPackage_getMainModule.expected | 4 ++-- .../ql/test/library-tests/NPM/src/index.js | 3 +-- .../ql/test/library-tests/NPM/src/lib/tst.js | 3 +-- .../src/node_modules/third-party-module/fancy.js | 3 +-- .../NodeJS/Module_getAnImport.expected | 1 + .../NodeJS/Module_getAnImportedModule.expected | 2 +- .../test/library-tests/NodeJS/Modules.expected | 2 +- .../test/library-tests/NodeJS/Require.expected | 1 + .../library-tests/NodeJS/RequireImport.expected | 2 +- javascript/ql/test/library-tests/NodeJS/e.js | 3 +-- 18 files changed, 35 insertions(+), 41 deletions(-) diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index a6446732fbe..ad843094a5e 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -142,11 +142,11 @@ | tst.js:111:29:111:31 | o2c | tst.js:111:6:111:38 | v2c | | tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | -| tst.ts:1:1:1:1 | A | tst.ts:1:11:1:11 | A | +| tst.ts:1:1:1:1 | A | tst.ts:1:18:1:18 | A | | tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:1:5:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:1:5:1 | A | tst.ts:11:11:11:11 | A | -| tst.ts:1:1:5:1 | namespa ... lysed\\n} | tst.ts:1:1:5:1 | A | +| tst.ts:1:8:5:1 | A | tst.ts:7:1:7:0 | A | +| tst.ts:1:8:5:1 | A | tst.ts:11:11:11:11 | A | +| tst.ts:1:8:5:1 | namespa ... lysed\\n} | tst.ts:1:8:5:1 | A | | tst.ts:2:14:2:19 | x | tst.ts:4:3:4:3 | x | | tst.ts:2:18:2:19 | 42 | tst.ts:2:14:2:19 | x | | tst.ts:7:1:7:0 | A | tst.ts:8:3:8:3 | A | diff --git a/javascript/ql/test/library-tests/DataFlow/tst.ts b/javascript/ql/test/library-tests/DataFlow/tst.ts index dca2ee632b7..29c85cba933 100644 --- a/javascript/ql/test/library-tests/DataFlow/tst.ts +++ b/javascript/ql/test/library-tests/DataFlow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); x; // global namespace exports are incompletely analysed @@ -11,5 +11,3 @@ function setX() { var nd2 = A.x as number; // flow through type assertions class StringList extends List {} // flow through expressions with type arguments - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index 42117cac98a..531faf562bd 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -194,8 +194,8 @@ | n.js:2:1:2:15 | function g | | n.js:2:1:2:15 | instance of function g | | n.js:3:16:3:23 | object literal | -| namespace-reexport.js:1:1:4:0 | exports object of module namespace-reexport | -| namespace-reexport.js:1:1:4:0 | module object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | exports object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | module object of module namespace-reexport | | nestedImport.js:1:1:13:0 | exports object of module nestedImport | | nestedImport.js:1:1:13:0 | module object of module nestedImport | | nestedImport.js:9:1:12:1 | function tst | @@ -235,14 +235,14 @@ | objlit.js:43:12:45:3 | object literal | | reexport-d.js:1:1:2:0 | exports object of module reexport-d | | reexport-d.js:1:1:2:0 | module object of module reexport-d | -| reexport-mixins.js:1:1:4:0 | exports object of module reexport-mixins | -| reexport-mixins.js:1:1:4:0 | module object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | exports object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | module object of module reexport-mixins | | reexport-unknown.js:1:1:2:0 | exports object of module reexport-unknown | | reexport-unknown.js:1:1:2:0 | module object of module reexport-unknown | | reexport/client/src/index.js:1:1:3:0 | exports object of module index | | reexport/client/src/index.js:1:1:3:0 | module object of module index | -| reexport/lib/index.js:1:1:4:0 | exports object of module index | -| reexport/lib/index.js:1:1:4:0 | module object of module index | +| reexport/lib/index.js:1:1:2:0 | exports object of module index | +| reexport/lib/index.js:1:1:2:0 | module object of module index | | reexport/lib/src/utils/util.js:1:1:3:0 | exports object of module util | | reexport/lib/src/utils/util.js:1:1:3:0 | module object of module util | | refinements.js:1:1:8:1 | function f1 | @@ -341,8 +341,8 @@ | tst.js:174:1:183:1 | function awaitFlow | | tst.mjs:1:1:4:0 | exports object of module tst | | tst.mjs:1:1:4:0 | module object of module tst | -| tst.ts:1:1:15:0 | exports object of module tst | -| tst.ts:1:1:15:0 | module object of module tst | +| tst.ts:1:1:13:0 | exports object of module tst | +| tst.ts:1:1:13:0 | module object of module tst | | tst.ts:8:1:10:1 | function setX | | tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | function f | diff --git a/javascript/ql/test/library-tests/Flow/tst.ts b/javascript/ql/test/library-tests/Flow/tst.ts index 615efbb7103..63e329f75c0 100644 --- a/javascript/ql/test/library-tests/Flow/tst.ts +++ b/javascript/ql/test/library-tests/Flow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); let x2 = x; @@ -10,5 +10,3 @@ function setX() { } let a = A; - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js index 8ba9bd12fee..1e4d7aed2e8 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js @@ -28,4 +28,4 @@ let source3 = "source3"; call2(source3, store); call2(source3, confounder); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js index 849516d57bb..9f1b0c9ba07 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js @@ -42,4 +42,4 @@ var o5 = {}; setP(o5, "not a source"); var sink10 = getP(o5); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/NPM/ImportedModule.expected b/javascript/ql/test/library-tests/NPM/ImportedModule.expected index 2a89dfeb394..ce2a65d591f 100644 --- a/javascript/ql/test/library-tests/NPM/ImportedModule.expected +++ b/javascript/ql/test/library-tests/NPM/ImportedModule.expected @@ -1,6 +1,6 @@ -| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:5:0 | | -| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:4:0 | | +| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | -| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | -| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:5:0 | | -| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | +| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:4:0 | | +| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/Modules.expected b/javascript/ql/test/library-tests/NPM/Modules.expected index 4d0dde9c33e..e7fa54d6f9a 100644 --- a/javascript/ql/test/library-tests/NPM/Modules.expected +++ b/javascript/ql/test/library-tests/NPM/Modules.expected @@ -1,9 +1,9 @@ | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | | test-package | src/lib/tst2.js:1:1:1:14 | | -| test-package | src/lib/tst.js:1:1:5:0 | | +| test-package | src/lib/tst.js:1:1:4:0 | | | test-package | src/tst2.js:1:1:1:13 | | | test-package | src/tst.js:1:1:2:38 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected index 67fd1880bf0..a8b7753abae 100644 --- a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected +++ b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected @@ -1,4 +1,4 @@ | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/src/index.js b/javascript/ql/test/library-tests/NPM/src/index.js index b875bfd3a10..e99778b633f 100644 --- a/javascript/ql/test/library-tests/NPM/src/index.js +++ b/javascript/ql/test/library-tests/NPM/src/index.js @@ -1,4 +1,3 @@ alert("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/lib/tst.js b/javascript/ql/test/library-tests/NPM/src/lib/tst.js index 840fb76057b..d8fc422959c 100644 --- a/javascript/ql/test/library-tests/NPM/src/lib/tst.js +++ b/javascript/ql/test/library-tests/NPM/src/lib/tst.js @@ -1,4 +1,3 @@ alert("world"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js index f53610fe05c..7dfe5aea1d2 100644 --- a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js @@ -1,4 +1,3 @@ ('alert' in this ? alert : console.log)("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected index 9f2e4dba88e..d1cc2576141 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected @@ -9,6 +9,7 @@ | b.js:1:1:8:0 | | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:7:15 | | d.js:1:1:1:38 | require ... s/ini') | | d.js:1:1:7:15 | | d.js:7:1:7:14 | require('foo') | +| e.js:1:1:6:0 | | e.js:5:1:5:18 | require("process") | | index.js:1:1:3:0 | | index.js:1:12:1:26 | require('path') | | index.js:1:1:3:0 | | index.js:2:1:2:41 | require ... b.js")) | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected index c038d8f9031..0fa0e65f359 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected @@ -1,6 +1,6 @@ | a.js:1:1:14:0 | | b.js:1:1:8:0 | | | a.js:1:1:14:0 | | d.js:1:1:7:15 | | -| a.js:1:1:14:0 | | e.js:1:1:7:0 | | +| a.js:1:1:14:0 | | e.js:1:1:6:0 | | | a.js:1:1:14:0 | | index.js:1:1:3:0 | | | a.js:1:1:14:0 | | sub/c.js:1:1:4:0 | | | b.js:1:1:8:0 | | sub/c.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NodeJS/Modules.expected b/javascript/ql/test/library-tests/NodeJS/Modules.expected index 05306ec82c5..1ef82d0328e 100644 --- a/javascript/ql/test/library-tests/NodeJS/Modules.expected +++ b/javascript/ql/test/library-tests/NodeJS/Modules.expected @@ -1,7 +1,7 @@ | a.js:1:1:14:0 | | a.js:0:0:0:0 | a.js | a.js | a | | b.js:1:1:8:0 | | b.js:0:0:0:0 | b.js | b.js | b | | d.js:1:1:7:15 | | d.js:0:0:0:0 | d.js | d.js | d | -| e.js:1:1:7:0 | | e.js:0:0:0:0 | e.js | e.js | e | +| e.js:1:1:6:0 | | e.js:0:0:0:0 | e.js | e.js | e | | index.js:1:1:3:0 | | index.js:0:0:0:0 | index.js | index.js | index | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:0:0:0:0 | mjs-files/require-from-js.js | mjs-files/require-from-js.js | require-from-js | | sub/c.js:1:1:4:0 | | sub/c.js:0:0:0:0 | sub/c.js | sub/c.js | c | diff --git a/javascript/ql/test/library-tests/NodeJS/Require.expected b/javascript/ql/test/library-tests/NodeJS/Require.expected index 491c80a9a87..7e9a50685ab 100644 --- a/javascript/ql/test/library-tests/NodeJS/Require.expected +++ b/javascript/ql/test/library-tests/NodeJS/Require.expected @@ -9,6 +9,7 @@ | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:1:38 | require ... s/ini') | | d.js:7:1:7:14 | require('foo') | +| e.js:5:1:5:18 | require("process") | | f.js:2:1:2:7 | r("fs") | | index.js:1:12:1:26 | require('path') | | index.js:2:1:2:41 | require ... b.js")) | diff --git a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected index a7ec65d67a2..e01527d2784 100644 --- a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected @@ -3,7 +3,7 @@ | a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | | | a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | | -| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:7:0 | | +| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | | | a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | | | b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | | diff --git a/javascript/ql/test/library-tests/NodeJS/e.js b/javascript/ql/test/library-tests/NodeJS/e.js index 0a3f338f7d0..22254c56326 100644 --- a/javascript/ql/test/library-tests/NodeJS/e.js +++ b/javascript/ql/test/library-tests/NodeJS/e.js @@ -2,5 +2,4 @@ require('./a.js'); })(); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); From 49008c9ff5923efbe3f29ccf66901eec67c40aa7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 5 Nov 2019 14:20:10 +0100 Subject: [PATCH 168/232] C++: IR data flow local virtual dispatch This is just good enough to cause no performance regressions and pass the virtual-dispatch tests we have for `security.TaintTracking`. In particular, it fixes the tests for `UncontrolledProcessOperation.ql` when enabling `DefaultTaintTracking.qll`. --- .../ir/dataflow/internal/DataFlowDispatch.qll | 53 +++++++++++++++++++ .../dataflow/dataflow-tests/dispatch.cpp | 46 ++++++++++++++++ .../dataflow/dataflow-tests/test.expected | 6 +++ .../dataflow-tests/test_diff.expected | 2 + .../dataflow/dataflow-tests/test_ir.expected | 8 +++ 5 files changed, 115 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index d0325a28d3e..9572639de59 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -1,5 +1,6 @@ private import cpp private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.DataFlow Function viableImpl(CallInstruction call) { result = viableCallable(call) } @@ -20,6 +21,58 @@ Function viableCallable(CallInstruction call) { functionSignatureWithBody(qualifiedName, nparams, result) and strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 ) + or + // Rudimentary virtual dispatch support. It's essentially local data flow + // where the source is a derived-to-base conversion and the target is the + // qualifier of a call. + exists(Class derived, DataFlow::Node thisArgument | + nodeMayHaveClass(derived, thisArgument) and + overrideMayAffectCall(derived, thisArgument, _, result, call) + ) +} + +/** + * Holds if `call` is a virtual function call with qualifier `thisArgument` in + * `enclosingFunction`, whose static target is overridden by + * `overridingFunction` in `overridingClass`. + */ +pragma[noinline] +private predicate overrideMayAffectCall( + Class overridingClass, DataFlow::Node thisArgument, Function enclosingFunction, + MemberFunction overridingFunction, CallInstruction call +) { + call.getEnclosingFunction() = enclosingFunction and + overridingFunction.getAnOverriddenFunction+() = call.getStaticCallTarget() and + overridingFunction.getDeclaringType() = overridingClass and + thisArgument = DataFlow::instructionNode(call.getThisArgument()) +} + +/** + * Holds if `node` may have dynamic class `derived`, where `derived` is a class + * that may affect virtual dispatch within the enclosing function. + * + * For the sake of performance, this recursion is written out manually to make + * it a relation on `Class x Node` rather than `Node x Node` or `MemberFunction + * x Node`, both of which would be larger. It's a forward search since there + * should usually be fewer classes than calls. + * + * If a value is cast several classes up in the hierarchy, that will be modeled + * as a chain of `ConvertToBaseInstruction`s and will cause the search to start + * from each of them and pass through subsequent ones. There might be + * performance to gain by stopping before a second upcast and reconstructing + * the full chain in a "big-step" recursion after this one. + */ +private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) { + exists(ConvertToBaseInstruction toBase | + derived = toBase.getDerivedClass() and + overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and + node.asInstruction() = toBase + ) + or + exists(DataFlow::Node prev | + nodeMayHaveClass(derived, prev) and + DataFlow::localFlowStep(prev, node) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp new file mode 100644 index 00000000000..f37eb4e9cbe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -0,0 +1,46 @@ +int source(); +void sink(int); + +// This class has the opposite behavior of what the member function names suggest. +struct Top { + virtual int isSource1() { return 0; } + virtual int isSource2() { return 0; } + virtual void isSink(int x) { } + virtual int notSource1() { return source(); } + virtual int notSource2() { return source(); } + virtual void notSink(int x) { sink(x); } +}; + +// This class has the correct behavior for just the functions ending in 2. +struct Middle : Top { + int isSource2() override { return source(); } + int notSource2() override { return 0; } +}; + +// This class has all the behavior suggested by the function names. +struct Bottom : Middle { + int isSource1() override { return source(); } + void isSink(int x) override { sink(x); } + int notSource1() override { return 0; } + void notSink(int x) override { } +}; + +void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { + Top *topPtr = bottomPtr, &topRef = bottomRef; + + sink(topPtr->isSource1()); // flow [NOT DETECTED] + sink(topPtr->isSource2()); // flow [NOT DETECTED by AST] + topPtr->isSink(source()); // flow [NOT DETECTED] + + sink(topPtr->notSource1()); // no flow [FALSE POSITIVE] + sink(topPtr->notSource2()); // no flow [FALSE POSITIVE] + topPtr->notSink(source()); // no flow [FALSE POSITIVE] + + sink(topRef.isSource1()); // flow [NOT DETECTED] + sink(topRef.isSource2()); // flow [NOT DETECTED by AST] + topRef.isSink(source()); // flow [NOT DETECTED] + + sink(topRef.notSource1()); // no flow [FALSE POSITIVE] + sink(topRef.notSource2()); // no flow [FALSE POSITIVE] + topRef.notSink(source()); // no flow [FALSE POSITIVE] +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected index 6527db4b77e..24fa6fdb5bd 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected @@ -15,6 +15,12 @@ | clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source | | clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | | clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | +| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source | +| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source | +| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source | +| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source | +| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source | +| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source | | lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 7d0d4e7d72e..8e914d53337 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -5,6 +5,8 @@ | clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 9b67a013a58..8d21837510e 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -12,6 +12,14 @@ | clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source | | clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source | | clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | +| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source | +| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source | +| dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | +| dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | +| dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | +| dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | +| dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | +| dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | | test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source | From ec9ef334864e59dc9e95fda9ab8267b99e7f29dd Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 13:59:52 +0100 Subject: [PATCH 169/232] C++: IR data flow through inheritance conversions This makes IR data flow behave more like AST data flow, and it makes IR virtual dispatch work without further changes. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 3 ++- .../library-tests/dataflow/dataflow-tests/dispatch.cpp | 8 ++++---- .../dataflow/dataflow-tests/test_diff.expected | 4 ++++ .../dataflow/dataflow-tests/test_ir.expected | 4 ++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index cd989c94710..4e84424fcb7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -205,7 +205,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo.(CopyInstruction).getSourceValue() = iFrom or iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or // Treat all conversions as flow, even conversions between different numeric types. - iTo.(ConvertInstruction).getUnary() = iFrom + iTo.(ConvertInstruction).getUnary() = iFrom or + iTo.(InheritanceConversionInstruction).getUnary() = iFrom } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp index f37eb4e9cbe..5e4f2f97f46 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -28,17 +28,17 @@ struct Bottom : Middle { void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { Top *topPtr = bottomPtr, &topRef = bottomRef; - sink(topPtr->isSource1()); // flow [NOT DETECTED] + sink(topPtr->isSource1()); // flow [NOT DETECTED by AST] sink(topPtr->isSource2()); // flow [NOT DETECTED by AST] - topPtr->isSink(source()); // flow [NOT DETECTED] + topPtr->isSink(source()); // flow [NOT DETECTED by AST] sink(topPtr->notSource1()); // no flow [FALSE POSITIVE] sink(topPtr->notSource2()); // no flow [FALSE POSITIVE] topPtr->notSink(source()); // no flow [FALSE POSITIVE] - sink(topRef.isSource1()); // flow [NOT DETECTED] + sink(topRef.isSource1()); // flow [NOT DETECTED by AST] sink(topRef.isSource2()); // flow [NOT DETECTED by AST] - topRef.isSink(source()); // flow [NOT DETECTED] + topRef.isSink(source()); // flow [NOT DETECTED by AST] sink(topRef.notSource1()); // no flow [FALSE POSITIVE] sink(topRef.notSource2()); // no flow [FALSE POSITIVE] diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 8e914d53337..9b8be3abd1e 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -7,6 +7,10 @@ | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:31:16:31:24 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:39:15:39:23 | IR only | +| dispatch.cpp:33:18:33:23 | dispatch.cpp:23:38:23:38 | IR only | +| dispatch.cpp:41:17:41:22 | dispatch.cpp:23:38:23:38 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 8d21837510e..651e580a105 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -14,9 +14,13 @@ | clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | | dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source | | dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source | +| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:33:18:33:23 | Call: call to source | +| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:41:17:41:22 | Call: call to source | +| dispatch.cpp:31:16:31:24 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source | | dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | | dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | | dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | +| dispatch.cpp:39:15:39:23 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source | | dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | | dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | | dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | From aa841c306dd0a2ca2e732a29df4883ace4bba4ad Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 5 Nov 2019 14:48:31 +0100 Subject: [PATCH 170/232] C++: Use virtual dispatch in DefaultTaintTracking This bit is only used by the compatibility code that sends flow into parameters of functions without body. --- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 0753dfd266e..e0135e0ad2f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.security.Security private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch /** * A predictable instruction is one where an external user can predict @@ -145,7 +146,8 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { } Function resolveCall(Call call) { - // TODO: improve virtual dispatch. This will help in the test for - // `UncontrolledProcessOperation.ql`. - result = call.getTarget() + exists(CallInstruction callInstruction | + callInstruction.getAST() = call and + result = Dispatch::viableCallable(callInstruction) + ) } From f9feb05a727bf9640636ca89ae68d0fcbacd25cf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 17:05:38 +0000 Subject: [PATCH 171/232] CPP: Add a test of NtohlArrayNoBoundOpenSource.ql. --- .../NtohlArrayNoBound.expected | 8 ++ .../NtohlArrayNoBound/NtohlArrayNoBound.qlref | 1 + .../NtohlArrayNoBound/test.cpp | 100 ++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected new file mode 100644 index 00000000000..6c2fa97858c --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected @@ -0,0 +1,8 @@ +| test.cpp:12:25:12:29 | call to ntohl | Unchecked use of data from network function $@ | test.cpp:12:25:12:29 | call to ntohl | call to ntohl | +| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@ | test.cpp:85:10:85:14 | call to ntohl | call to ntohl | +| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@ | test.cpp:99:8:99:12 | call to ntohl | call to ntohl | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref new file mode 100644 index 00000000000..2647a5479f2 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref @@ -0,0 +1 @@ +Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp new file mode 100644 index 00000000000..e3f01f9ae77 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp @@ -0,0 +1,100 @@ + +typedef unsigned int size_t; +void *memcpy(void *s1, const void *s2, size_t n); +size_t strlen(const char *s); +int ntohl(int x); + +void test1(const char *source, size_t len) +{ + char buffer[256]; + size_t len2 = ntohl(len); + + memcpy(buffer, source, ntohl(len)); // BAD + + if (len2 < 256) + { + memcpy(buffer, source, len2); // GOOD + } + + if (source != 0) + { + memcpy(buffer, source, len2); // BAD + } + + if ((len2 < 256) && (source != 0)) + { + memcpy(buffer, source, len2); // GOOD + } + + if ((len2 < 256) || (source != 0)) + { + memcpy(buffer, source, len2); // BAD + } + + if (len2 < 256) + { + if (source != 0) + { + memcpy(buffer, source, len2); // GOOD + } + } + + if (len2 >= 256) + { + // fail + } else { + memcpy(buffer, source, len2); // GOOD + } + + if (len2 + 1 < 256) + { + memcpy(buffer, source, len2 + 1); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, strlen(source)); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, len2); // BAD + } + + buffer[len2] = 0; // BAD + + if (len2 < 256) + { + buffer[len2] = 0; // GOOD + } + + { + unsigned short lens = len2; + buffer[lens] = 0; // BAD + } + + if (len2 < 256) + { + unsigned short lens = len2; + buffer[lens] = 0; // GOOD + } + + size_t len3 = 0; + if (len3 < 256) + { + len3 = ntohl(len); + buffer[len3] = 0; // BAD + } +} + +void test2(size_t len) +{ + char buffer[256]; + + buffer[len] = 0; // BAD +} + +void test3(size_t len) +{ + test2(ntohl(len)); +} From b6f16dee81a97f6f50d047beb9a90c0e9f9ee1c5 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 15:14:48 +0100 Subject: [PATCH 172/232] Python: Fix bad join order in `py/unused-import` --- python/ql/src/Imports/UnusedImport.ql | 59 +++++++++++++++++---------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 3ac04e2e4d2..4049f3d5e41 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -41,41 +41,58 @@ predicate all_not_understood(Module m) { } predicate imported_module_used_in_doctest(Import imp) { - exists(string modname | + exists(string modname, string docstring | imp.getAName().getAsname().(Name).getId() = modname and // Look for doctests containing the patterns: // >>> …name… // ... …name… - exists(StrConst doc | - doc.getEnclosingModule() = imp.getScope() and - doc.isDocString() and - doc.getText().regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") - ) + docstring = doctest_in_scope(imp.getScope()) and + docstring.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") + ) +} + +pragma[noinline] +private string doctest_in_scope(Scope scope) { + exists(StrConst doc | + doc.getEnclosingModule() = scope and + doc.isDocString() and + result = doc.getText() and + result.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.)[\\s\\S]*") + ) +} + +pragma[noinline] +private string typehint_annotation_in_file(File file) { + exists(StrConst annotation | + annotation = any(Arguments a).getAnAnnotation() + or + annotation = any(AnnAssign a).getAnnotation() + | + annotation.pointsTo(Value::forString(result)) and + file = annotation.getLocation().getFile() + ) +} + +pragma[noinline] +private string typehint_comment_in_file(File file) { + exists(Comment typehint | + file = typehint.getLocation().getFile() and + result = typehint.getText() and + result.matches("# type:%") ) } predicate imported_module_used_in_typehint(Import imp) { - exists(string modname, Location loc | + exists(string modname, File file | imp.getAName().getAsname().(Name).getId() = modname and - loc.getFile() = imp.getScope().(Module).getFile() + file = imp.getScope().(Module).getFile() | // Look for type hints containing the patterns: // # type: …name… - exists(Comment typehint | - loc = typehint.getLocation() and - typehint.getText().regexpMatch("# type:.*" + modname + ".*") - ) + typehint_comment_in_file(file).regexpMatch("# type:.*" + modname + ".*") or // Type hint is inside a string annotation, as needed for forward references - exists(string typehint, Expr annotation | - annotation = any(Arguments a).getAnAnnotation() - or - annotation = any(AnnAssign a).getAnnotation() - | - annotation.pointsTo(Value::forString(typehint)) and - loc = annotation.getLocation() and - typehint.regexpMatch(".*\\b" + modname + "\\b.*") - ) + typehint_annotation_in_file(file).regexpMatch(".*\\b" + modname + "\\b.*") ) } From 217ecd3551753708e146d46957d4765842adc3b7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 15:50:08 +0100 Subject: [PATCH 173/232] C++: Add

    tags to split text into paragraphs Without this, the rendered output is one big paragraph. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 4d5dfabef14..621ae3273fd 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -21,7 +21,9 @@ Solutions to this problem can be thought of as falling into one of two categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. +

    +

    Below we list examples of expressions where signed overflow may occur, along with proposed solutions. The list should not be considered exhaustive. @@ -31,21 +33,29 @@ considered exhaustive. Given unsigned short i, delta and i + delta < i, it is possible to rewrite it as (unsigned short)(i + delta) < i. Note that i + deltadoes not actually overflow, due to int promotion +

    +

    Given unsigned short i, delta and i + delta < i, it is also possible to rewrite it as USHORT_MAX - delta. It must be true that delta > 0 and the limits.h or climits header has been included. +

    +

    Given int i, delta and i + delta < i, it is possible to rewrite it as INT_MAX - delta. It must be true that delta > 0 and the limits.h or climits header has been included. +

    +

    Given int i, delta and i + delta < i, it is also possible to rewrite it as (unsigned)i + delta < i. Note that program semantics are affected by this change. +

    +

    Given int i, delta and i + delta < i, it is also possible to rewrite it as unsigned int i, delta and i + delta < i. Note that program semantics are From 43148083ebf7ca19832a5017b88f0853f5559ab9 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 16:36:28 +0100 Subject: [PATCH 174/232] Python: Fix bad join order for `global_name_used`. As it turns out, there was a further bad join-order in the `global_name_used` predicate. In this case, there was a common subexpression in the RA that was being factored out and evaluated separately, producing a large number of tuples. --- python/ql/src/Imports/UnusedImport.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 3ac04e2e4d2..3d9163f9320 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -13,17 +13,17 @@ import python import Variables.Definition -predicate global_name_used(Module m, Variable name) { +predicate global_name_used(Module m, string name) { exists(Name u, GlobalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m ) or // A use of an undefined class local variable, will use the global variable exists(Name u, LocalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m and not v.getScope().getEnclosingScope*() instanceof Function ) @@ -84,7 +84,7 @@ predicate unused_import(Import imp, Variable name) { not imp.getAnImportedModuleName() = "__future__" and not imp.getEnclosingModule().declaredInAll(name.getId()) and imp.getScope() = imp.getEnclosingModule() and - not global_name_used(imp.getScope(), name) and + not global_name_used(imp.getScope(), name.getId()) and // Imports in `__init__.py` are used to force module loading not imp.getEnclosingModule().isPackageInit() and // Name may be imported for use in epytext documentation From 399ac1f11297d24231ee8daab34daafd7618db0f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 15:57:44 +0000 Subject: [PATCH 175/232] CPP: Rename 'getAssertedFalseCondition' to something less misleading. --- .../Security/CWE/CWE-457/InitializationFunctions.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 240bd7aa25e..1c299b9ad51 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -89,9 +89,9 @@ class ParameterNullCheck extends ParameterCheck { ( va = this.(NotExpr).getOperand() or va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or - va = getAssertedFalseCondition(this) or + va = getCheckedFalseCondition(this) or va = any(NEExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) or @@ -101,7 +101,7 @@ class ParameterNullCheck extends ParameterCheck { va = this or va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or va = any(EQExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) ) @@ -669,7 +669,7 @@ FieldAccess getAFieldAccess(Variable v) { } /** - * Gets a condition which is asserted to be false by the given `ne` expression, according to this pattern: + * Gets a condition which is checked to be false by the given `ne` expression, according to this pattern: * ``` * int a = !!result; * if (!a) { // <- ne @@ -677,7 +677,7 @@ FieldAccess getAFieldAccess(Variable v) { * } * ``` */ -Expr getAssertedFalseCondition(NotExpr ne) { +private Expr getCheckedFalseCondition(NotExpr ne) { exists(LocalVariable v | result = v.getInitializer().getExpr().(NotExpr).getOperand().(NotExpr).getOperand() and ne.getOperand() = v.getAnAccess() and From 0c3f4e530f62ce1340c022948f5a2a84108e6353 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:07:28 +0000 Subject: [PATCH 176/232] CPP: Make some library predicates private. --- .../src/Security/CWE/CWE-457/InitializationFunctions.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 1c299b9ad51..276b6043901 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -567,7 +567,7 @@ Expr getAnInitializedArgument(Call call) { result = call.getArgument(initialized * the call, under the given context and evidence. */ pragma[nomagic] -int conditionallyInitializedArgument( +private int conditionallyInitializedArgument( Call call, ConditionalInitializationFunction target, Context c, Evidence e ) { target = getTarget(call) and @@ -588,7 +588,7 @@ Expr getAConditionallyInitializedArgument( /** * Gets the type signature for the functions parameters. */ -string typeSig(Function f) { +private string typeSig(Function f) { result = concat(int i, Type pt | pt = f.getParameter(i).getType() | @@ -599,7 +599,7 @@ string typeSig(Function f) { /** * Holds where qualifiedName and typeSig make up the signature for the function. */ -predicate functionSignature(Function f, string qualifiedName, string typeSig) { +private predicate functionSignature(Function f, string qualifiedName, string typeSig) { qualifiedName = f.getQualifiedName() and typeSig = typeSig(f) } @@ -611,7 +611,7 @@ predicate functionSignature(Function f, string qualifiedName, string typeSig) { * This is useful for identifying call to target dependencies across libraries, where the libraries * are never statically linked together. */ -Function getAPossibleDefinition(Function undefinedFunction) { +private Function getAPossibleDefinition(Function undefinedFunction) { not undefinedFunction.isDefined() and exists(string qn, string typeSig | functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig) From 81c58d5a64cdda985da83f0395cca56230b9477c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:17:33 +0000 Subject: [PATCH 177/232] CPP: Improve QLDoc comments. --- cpp/ql/src/semmle/code/cpp/NestedFields.qll | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/NestedFields.qll b/cpp/ql/src/semmle/code/cpp/NestedFields.qll index 12109be8ece..c4be8b8b9ff 100644 --- a/cpp/ql/src/semmle/code/cpp/NestedFields.qll +++ b/cpp/ql/src/semmle/code/cpp/NestedFields.qll @@ -1,9 +1,8 @@ import cpp /** - * Gets a `Field` that is nested within the given `Struct`. - * - * This identifies `Field`s which are located in the same memory + * Gets a `Field` that is within the given `Struct`, either directly or nested + * inside one or more levels of member structs. */ private Field getANestedField(Struct s) { result = s.getAField() @@ -15,7 +14,7 @@ private Field getANestedField(Struct s) { } /** - * Unwraps a series of field accesses to determine the inner-most qualifier. + * Unwraps a series of field accesses to determine the outer-most qualifier. */ private Expr getUltimateQualifier(FieldAccess fa) { exists(Expr qualifier | qualifier = fa.getQualifier() | From 2b24eb2e7083c7c776dd68b59289b8b6ea0ae479 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 17:14:05 +0100 Subject: [PATCH 178/232] Python: Fix bad join order for `py/multiple-calls-to-init`. The `multiple_invocation_paths` predicate had a bad join order where we (essentially) joined `i1` with `i2` and only then joined `i1` and `i2` separately to reduce the number of tuples. The join coming from `i1 != i2` had little impact, but `i1.getFunction() = multi` made a big difference (and similarly for `i2`). I factored out the code so that these joins would be done more eagerly. Thus, we went from ``` [2019-11-06 16:53:05] (38s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2ce75a [2019-11-06 16:53:35] (68s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff: 134547 ~9% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<0>, I.<2> 235284431 ~3% {4} r2 = JOIN r1 WITH CallGraph::TInvocation#fff AS R ON FIRST 1 OUTPUT r1.<0>, r1.<1>, R.<1>, R.<2> 235149884 ~3% {4} r3 = SELECT r2 ON r2.<3> != r2.<1> 235149884 ~4% {3} r4 = SCAN r3 OUTPUT r3.<1>, r3.<0>, r3.<3> 166753634 ~5% {4} r5 = JOIN r4 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r4.<2>, r4.<1>, r4.<0> 129778 ~0% {4} r6 = JOIN r5 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 2 OUTPUT r5.<0>, r5.<3>, r5.<1>, r5.<2> return r6 [2019-11-06 16:53:35] (68s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv [2019-11-06 16:53:35] (68s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns. ``` to ``` [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff/4@586aec [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff: 134547 ~0% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0> 88111 ~4% {3} r2 = JOIN r1 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0> 761305 ~0% {4} r3 = JOIN r2 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<0>, R.<1> 673194 ~0% {4} r4 = SELECT r3 ON r3.<3> != r3.<1> 673194 ~0% {4} r5 = SCAN r4 OUTPUT r4.<2>, r4.<1>, r4.<3>, r4.<0> return r5 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff + [] with content 20edaaecf25nldgp24d9c4et8m3kv [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff with 673194 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs/4@9e5441 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs: 673194 ~0% {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths_helper#ffff AS I OUTPUT I.<2>, I.<3>, I.<0>, I.<1> return r1 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs + [] with content 2069301e655fi9mcovngg9hetfqas [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs with 673194 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2f7c34 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff: 134547 ~0% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0> 129778 ~0% {4} r2 = JOIN r1 WITH MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs AS R ON FIRST 2 OUTPUT R.<2>, R.<3>, r1.<0>, r1.<1> return r2 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs/4@9f9146 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs: 129778 ~0% {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths#ffff AS I OUTPUT I.<0>, I.<3>, I.<1>, I.<2> return r1 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs + [] with content 17c3fe1fcbf6ghhdr7hiukqp41rst [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs with 129778 rows and 4 columns. ``` Execution time on `salt` went from 29.5s to somewhere below 299ms (the predicate was not listed in the timing report). --- python/ql/src/Classes/MethodCallOrder.qll | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/ql/src/Classes/MethodCallOrder.qll b/python/ql/src/Classes/MethodCallOrder.qll index fe6ef07266a..5073cefc134 100644 --- a/python/ql/src/Classes/MethodCallOrder.qll +++ b/python/ql/src/Classes/MethodCallOrder.qll @@ -3,11 +3,16 @@ import python // Helper predicates for multiple call to __init__/__del__ queries. pragma [noinline] -private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +private predicate multiple_invocation_paths_helper(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { i1 != i2 and i1 = top.getACallee+() and i2 = top.getACallee+() and - i1.getFunction() = multi and + i1.getFunction() = multi +} + +pragma [noinline] +private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { + multiple_invocation_paths_helper(top, i1, i2, multi) and i2.getFunction() = multi } From e886cf729773f9e1f86ff35805e596e5f4274d9f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:27:06 +0000 Subject: [PATCH 179/232] CPP: 'i.e.' -> 'that is'. --- cpp/ql/src/Microsoft/SAL.qll | 2 +- cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll | 2 +- .../src/semmle/code/cpp/security/boostorg/asio/protocols.qll | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index fe6b455fa9b..963a726ae54 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -126,7 +126,7 @@ class SALParameter extends Parameter { } /** - * A SAL element, i.e. a SAL annotation or a declaration entry + * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. */ library class SALElement extends Element { diff --git a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll index 2fa9322843e..a181c9bb543 100644 --- a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll @@ -63,7 +63,7 @@ module VirtualDispatch { /** * Holds if `c` cannot inherit the member function `f`, - * i.e. `c` or one of its supertypes overrides `f`. + * that is, `c` or one of its supertypes overrides `f`. */ private predicate cannotInherit(Class c, MemberFunction f) { exists(Class overridingType, MemberFunction override | diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll index ae3733473ad..af1a8eaf8e7 100644 --- a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -56,7 +56,8 @@ module BoostorgAsio { } /** - * returns the value for a approved protocols, but that are hard-coded (i.e. no protocol negotiation) + * returns the value for an approved protocol, but that are hard-coded + * (that is, no protocol negotiation) */ EnumConstant getAnApprovedButHardcodedProtocolConstant() { result = this.getATls12ProtocolConstant() From 54e40a8977f50173dbfd0befae900fa5080208af Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 12:19:09 +0000 Subject: [PATCH 180/232] JavaScript: Move `--html all` extractor options into `options` file. --- javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html | 2 +- javascript/ql/test/library-tests/HTML/HtmlText/options | 1 + .../frameworks/AngularJS/expressions/scopes/options | 1 + .../frameworks/AngularJS/expressions/scopes/tst.html | 1 - .../frameworks/AngularJS/expressions/sources/HtmlText.html | 1 - .../frameworks/AngularJS/expressions/sources/options | 1 + 6 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/library-tests/HTML/HtmlText/options create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html index 6cf4bfc564f..0b571650c40 100644 --- a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html +++ b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html @@ -1,4 +1,4 @@ -// semmle-extractor-options: --html all + (1) as child #0 diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/options b/javascript/ql/test/library-tests/HTML/HtmlText/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/HTML/HtmlText/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html index 23449e03c0e..29608f2da53 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html @@ -17,4 +17,3 @@

    -// semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html index 9678f75e0cc..87bb928ac4c 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html @@ -7,4 +7,3 @@
    {{myExpr3}}
    -semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all From 6c38f55e28aa4b9ebff51ccddd6a414fa03f45de Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:31:21 +0000 Subject: [PATCH 181/232] CPP: QLDoc protocols.qll. --- .../cpp/security/boostorg/asio/protocols.qll | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll index af1a8eaf8e7..73ccd49e2f8 100644 --- a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -3,7 +3,7 @@ import semmle.code.cpp.dataflow.DataFlow module BoostorgAsio { /** - * Represents boost::asio::ssl::context enum + * Represents the `boost::asio::ssl::context` enum. */ class SslContextMethod extends Enum { SslContextMethod() { @@ -12,7 +12,7 @@ module BoostorgAsio { } /** - * returns the value for a banned protocol + * Gets an enumeration constant for a banned protocol. */ EnumConstant getABannedProtocolConstant() { result = this.getAnEnumConstant() and @@ -56,15 +56,15 @@ module BoostorgAsio { } /** - * returns the value for an approved protocol, but that are hard-coded - * (that is, no protocol negotiation) + * Gets an enumeration constant for an approved protocol, that is hard-coded + * (no protocol negotiation). */ EnumConstant getAnApprovedButHardcodedProtocolConstant() { result = this.getATls12ProtocolConstant() } /** - * returns the value for a TLS v1.2 protocol + * Gets an enumeration constant for a TLS v1.2 protocol. */ EnumConstant getATls12ProtocolConstant() { result = this.getAnEnumConstant() and @@ -81,7 +81,7 @@ module BoostorgAsio { } /** - * returns the value for a TLS v1.3 protocol + * Gets an enumeration constant for a TLS v1.3 protocol. */ EnumConstant getATls13ProtocolConstant() { result = this.getAnEnumConstant() and @@ -98,7 +98,7 @@ module BoostorgAsio { } /** - * returns the value of a generic TLS or SSL/TLS protocol + * Gets an enumeration constant for a generic TLS or SSL/TLS protocol. */ EnumConstant getAGenericTlsProtocolConstant() { result = this.getAnEnumConstant() and @@ -117,7 +117,7 @@ module BoostorgAsio { } /** - * returns the value of a generic SSL/TLS protocol + * Gets an enumeration constant for a generic SSL/TLS protocol. */ EnumConstant getASslv23ProtocolConstant() { result = this.getAnEnumConstant() and @@ -136,7 +136,9 @@ module BoostorgAsio { } /** - * NOTE: ignore - Modern versions of OpenSSL do not support SSL v2 anymore, so this option is for backwards compatibility only + * Gets the value for the no_sslv2 constant, right shifted by 16 bits. + * + * Note that modern versions of OpelSSL do not support SSL v2, so this option is for backwards compatibility only. */ int getShiftedSslOptionsNoSsl2() { // SSL_OP_NO_SSLv2 was removed from modern OpenSSL versions @@ -144,7 +146,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_sslv3 constant + * Gets the value for the no_sslv3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoSsl3() { // SSL_OP_NO_SSLv3 == 0x02000000U @@ -152,7 +154,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1 constant + * Gets the value for the no_tlsv1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1() { // SSL_OP_NO_TLSv1 == 0x04000000U @@ -160,7 +162,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_1 constant + * Gets the value for the no_tlsv1_1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_1() { // SSL_OP_NO_TLSv1_1 == 0x10000000U @@ -168,7 +170,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_2 constant + * Gets the value for the no_tlsv1_2 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_2() { // SSL_OP_NO_TLSv1_2 == 0x08000000U @@ -176,7 +178,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_3 constant + * Gets the value for the no_tlsv1_3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_3() { // SSL_OP_NO_TLSv1_2 == 0x20000000U @@ -184,7 +186,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context class + * Represents the `boost::asio::ssl::context` class. */ class SslContextClass extends Class { SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" } @@ -197,7 +199,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context::set_options member function + * Represents `boost::asio::ssl::context::set_options` member function. */ class SslSetOptionsFunction extends Function { SslSetOptionsFunction() { @@ -206,7 +208,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a banned protocol + * Holds if the expression represents a banned protocol. */ predicate isExprBannedBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -245,7 +247,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a TLS v1.2 protocol + * Holds if the expression represents a TLS v1.2 protocol. */ predicate isExprTls12BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -270,7 +272,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a protocol that requires Crypto Board approval + * Holds if the expression represents a protocol that requires Crypto Board approval. */ predicate isExprTls13BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -295,7 +297,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic TLS or SSL/TLS protocol + * Holds if the expression represents a generic TLS or SSL/TLS protocol. */ predicate isExprTlsBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -326,7 +328,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic SSl/TLS protocol + * Holds if the expression represents a generic SSl/TLS protocol. */ predicate isExprSslV23BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -352,7 +354,8 @@ module BoostorgAsio { //////////////////////// Dataflow ///////////////////// /** - * Abstract - Protocol value Flows to the first argument of the context constructor + * Abstract class for flows of protocol values to the first argument of a context + * constructor. */ abstract class SslContextCallAbstractConfig extends DataFlow::Configuration { bindingset[this] @@ -367,7 +370,7 @@ module BoostorgAsio { } /** - * any Protocol value Flows to the first argument of the context constructor + * Any protocol value that flows to the first argument of a context constructor. */ class SslContextCallConfig extends SslContextCallAbstractConfig { SslContextCallConfig() { this = "SslContextCallConfig" } @@ -381,7 +384,7 @@ module BoostorgAsio { } /** - * a banned protocol value Flows to the first argument of the context constructor + * A banned protocol value that flows to the first argument of a context constructor. */ class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" } @@ -396,7 +399,7 @@ module BoostorgAsio { } /** - * a TLS 1.2 protocol value Flows to the first argument of the context constructor + * A TLS 1.2 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -411,7 +414,7 @@ module BoostorgAsio { } /** - * a TLS 1.3 protocol value Flows to the first argument of the context constructor + * A TLS 1.3 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -426,7 +429,7 @@ module BoostorgAsio { } /** - * a generic TLS protocol value Flows to the first argument of the context constructor + * A generic TLS protocol value that flows to the first argument of a context constructor. */ class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" } @@ -441,7 +444,7 @@ module BoostorgAsio { } /** - * a context constructor call flows to a call calling SetOptions() + * A context constructor call that flows to a call to `SetOptions()`. */ class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" } @@ -465,7 +468,7 @@ module BoostorgAsio { } /** - * an option value flows to the 1st parameter of SetOptions() + * An option value that flows to the first parameter of a call to `SetOptions()`. */ class SslOptionConfig extends DataFlow::Configuration { SslOptionConfig() { this = "SslOptionConfig" } From a9e3bfbd11476210ff72c95f15866b7f745bae8e Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Wed, 6 Nov 2019 13:08:28 -0700 Subject: [PATCH 182/232] C++/C#: Treat string literals like read-only global variables for alias purposes. Previously, we didn't track string literals as known memory locations at all, so they all just got marked as `UnknownMemoryLocation`, just like an aribtrary read from a random pointer. This led to some confusing def-use chains, where it would look like the contents of a string literal were being written to by the side effect of an earlier function call, which of course is impossible. To fix this, I've made two changes. First, each string literal is now given a corresponding `IRVariable` (specifically `IRStringLiteral`), since a string literal behaves more or less as a read-only global variable. Second, the `IRVariable` for each string literal is now marked `isReadOnly()`, which the alias analysis uses to determine that an arbitrary write to aliased memory will not overwrite the contents of a string literal. I originally planned to treat all string literals with the same value as being the same memory location, since this is the usual behavior of modern compilers. However, this made implementing `IRVariable.getAST()` tricky for string literals, so I left them unpooled. --- .../implementation/aliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../aliased_ssa/Instruction.qll | 10 ++-- .../aliased_ssa/internal/AliasAnalysis.qll | 4 ++ .../aliased_ssa/internal/AliasedSSA.qll | 12 ++-- .../aliased_ssa/internal/SSAConstruction.qll | 5 -- .../implementation/internal/TIRVariable.qll | 6 ++ .../cpp/ir/implementation/raw/IRVariable.qll | 57 ++++++++++++++----- .../cpp/ir/implementation/raw/Instruction.qll | 10 ++-- .../raw/internal/IRConstruction.qll | 23 +++++--- .../unaliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../unaliased_ssa/Instruction.qll | 10 ++-- .../unaliased_ssa/internal/AliasAnalysis.qll | 4 ++ .../internal/SSAConstruction.qll | 5 -- .../ir/ssa/aliased_ssa_ir.expected | 26 +++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 8 +++ .../ir/ssa/unaliased_ssa_ir.expected | 25 ++++++++ .../implementation/internal/TIRVariable.qll | 6 ++ .../ir/implementation/raw/IRVariable.qll | 57 ++++++++++++++----- .../ir/implementation/raw/Instruction.qll | 10 ++-- .../raw/internal/IRConstruction.qll | 25 +++++--- .../unaliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../unaliased_ssa/Instruction.qll | 10 ++-- .../internal/SSAConstruction.qll | 5 -- 23 files changed, 359 insertions(+), 130 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 049983c9126..9f7cf68b065 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..0923ec8f994 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index 955d422cf9a..0835ffb7da6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -210,17 +210,21 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) { def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap or - // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable. + // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable, + // unless the location is read-only. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownMemoryLocation and - result instanceof MayPartiallyOverlap + result instanceof MayPartiallyOverlap and + not use.(VariableMemoryLocation).getVariable().isReadOnly() or // An UnknownNonLocalMemoryLocation may partially overlap any location within the same virtual - // variable, except a local variable. + // variable, except a local variable or read-only variable. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownNonLocalMemoryLocation and result instanceof MayPartiallyOverlap and - not use.(VariableMemoryLocation).getVariable() instanceof IRAutomaticVariable + not exists(IRVariable var | var = use.(VariableMemoryLocation).getVariable() | + var instanceof IRAutomaticVariable or var.isReadOnly() + ) or exists(VariableMemoryLocation defVariableLocation | defVariableLocation = def and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd..01c135abf13 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 049983c9126..9f7cf68b065 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index fbf6b7e3d08..fe161e5196a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -44,6 +44,13 @@ private module Cached { ) } + cached + predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) { + literal = ast and + literal.getEnclosingFunction() = func and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -231,8 +238,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -263,12 +276,6 @@ private module Cached { ) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126..9f7cf68b065 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..0923ec8f994 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 98786207c45..07faf581d3e 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -869,3 +869,29 @@ ssa.cpp: # 207| v0_25(void) = UnmodeledUse : mu* # 207| v0_26(void) = AliasedUse : ~m0_1 # 207| v0_27(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| m0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| m0_5(unknown) = ^CallSideEffect : ~m0_1 +# 216| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 +# 218| r0_7(glval) = VariableAddress[s] : +# 218| r0_8(glval) = StringConstant["Literal"] : +# 218| r0_9(char *) = Convert : r0_8 +# 218| m0_10(char *) = Store : &:r0_7, r0_9 +# 219| r0_11(glval) = VariableAddress[#return] : +# 219| r0_12(glval) = VariableAddress[s] : +# 219| r0_13(char *) = Load : &:r0_12, m0_10 +# 219| r0_14(int) = Constant[2] : +# 219| r0_15(glval) = PointerAdd[1] : r0_13, r0_14 +# 219| r0_16(char) = Load : &:r0_15, ~m0_1 +# 219| m0_17(char) = Store : &:r0_11, r0_16 +# 215| r0_18(glval) = VariableAddress[#return] : +# 215| v0_19(void) = ReturnValue : &:r0_18, m0_17 +# 215| v0_20(void) = UnmodeledUse : mu* +# 215| v0_21(void) = AliasedUse : ~m0_6 +# 215| v0_22(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cd..8ce2b8900d8 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,11 @@ int ModeledCallTarget(int x) { return y; } +extern void ExternalFunc(); + +char StringLiteralAliasing() { + ExternalFunc(); + + const char* s = "Literal"; + return s[2]; // Should be defined by `AliasedDefinition`, not `Chi` or `CallSideEffect`. +} diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 5ac06cadb55..03cf52c2ad6 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -833,3 +833,28 @@ ssa.cpp: # 207| v0_22(void) = UnmodeledUse : mu* # 207| v0_23(void) = AliasedUse : ~mu0_2 # 207| v0_24(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| mu0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| mu0_5(unknown) = ^CallSideEffect : ~mu0_2 +# 218| r0_6(glval) = VariableAddress[s] : +# 218| r0_7(glval) = StringConstant["Literal"] : +# 218| r0_8(char *) = Convert : r0_7 +# 218| m0_9(char *) = Store : &:r0_6, r0_8 +# 219| r0_10(glval) = VariableAddress[#return] : +# 219| r0_11(glval) = VariableAddress[s] : +# 219| r0_12(char *) = Load : &:r0_11, m0_9 +# 219| r0_13(int) = Constant[2] : +# 219| r0_14(glval) = PointerAdd[1] : r0_12, r0_13 +# 219| r0_15(char) = Load : &:r0_14, ~mu0_2 +# 219| m0_16(char) = Store : &:r0_10, r0_15 +# 215| r0_17(glval) = VariableAddress[#return] : +# 215| v0_18(void) = ReturnValue : &:r0_17, m0_16 +# 215| v0_19(void) = UnmodeledUse : mu* +# 215| v0_20(void) = AliasedUse : ~mu0_2 +# 215| v0_21(void) = ExitFunction : diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd..01c135abf13 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 049983c9126..9f7cf68b065 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll index 0d2627e183f..72881a7c720 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll @@ -52,6 +52,15 @@ private module Cached { ) } + cached + predicate hasStringLiteral( + Callable callable, Language::AST ast, CSharpType type, StringLiteral literal + ) { + literal = ast and + literal.getEnclosingCallable() = callable and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -232,8 +241,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -265,12 +280,6 @@ private module Cached { .getInstructionConstantValue(getInstructionTag(instruction)) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached CSharpType getInstructionExceptionType(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126..9f7cf68b065 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) From 51c4ef4f7f20f22d45dd90f48f24957c2d885008 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 6 Nov 2019 13:32:35 -0800 Subject: [PATCH 183/232] C++: add SSA IR test for array initializers --- .../ir/ssa/aliased_ssa_ir.expected | 71 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 10 +++ .../ir/ssa/unaliased_ssa_ir.expected | 65 +++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 98786207c45..7345c6a5204 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -869,3 +869,74 @@ ssa.cpp: # 207| v0_25(void) = UnmodeledUse : mu* # 207| v0_26(void) = AliasedUse : ~m0_1 # 207| v0_27(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| m0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| r0_4(glval) = StringConstant[""] : +# 214| r0_5(char[1]) = Load : &:r0_4, ~m0_1 +# 214| m0_6(char[1]) = Store : &:r0_3, r0_5 +# 214| r0_7(unknown[31]) = Constant[0] : +# 214| r0_8(int) = Constant[1] : +# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 +# 214| m0_10(unknown[31]) = Store : &:r0_9, r0_7 +# 215| r0_11(glval) = VariableAddress[a_nopad] : +# 215| r0_12(glval) = StringConstant["foo"] : +# 215| r0_13(char[4]) = Load : &:r0_12, ~m0_1 +# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 +# 216| r0_15(glval) = VariableAddress[a_infer] : +# 216| r0_16(glval) = StringConstant["blah"] : +# 216| r0_17(char[5]) = Load : &:r0_16, ~m0_1 +# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 +# 217| r0_19(glval) = VariableAddress[b] : +# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 +# 218| r0_21(glval) = VariableAddress[c] : +# 218| m0_22(char[2]) = Uninitialized[c] : &:r0_21 +# 218| r0_23(int) = Constant[0] : +# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 +# 218| r0_25(unknown[2]) = Constant[0] : +# 218| m0_26(unknown[2]) = Store : &:r0_24, r0_25 +# 219| r0_27(glval) = VariableAddress[d] : +# 219| m0_28(char[2]) = Uninitialized[d] : &:r0_27 +# 219| r0_29(int) = Constant[0] : +# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 +# 219| r0_31(char) = Constant[0] : +# 219| m0_32(char) = Store : &:r0_30, r0_31 +# 219| m0_33(char[2]) = Chi : total:m0_28, partial:m0_32 +# 219| r0_34(int) = Constant[1] : +# 219| r0_35(glval) = PointerAdd[1] : r0_27, r0_34 +# 219| r0_36(char) = Constant[0] : +# 219| m0_37(char) = Store : &:r0_35, r0_36 +# 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 +# 220| r0_39(glval) = VariableAddress[e] : +# 220| m0_40(char[2]) = Uninitialized[e] : &:r0_39 +# 220| r0_41(int) = Constant[0] : +# 220| r0_42(glval) = PointerAdd[1] : r0_39, r0_41 +# 220| r0_43(char) = Constant[0] : +# 220| m0_44(char) = Store : &:r0_42, r0_43 +# 220| m0_45(char[2]) = Chi : total:m0_40, partial:m0_44 +# 220| r0_46(int) = Constant[1] : +# 220| r0_47(glval) = PointerAdd[1] : r0_39, r0_46 +# 220| r0_48(char) = Constant[1] : +# 220| m0_49(char) = Store : &:r0_47, r0_48 +# 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 +# 221| r0_51(glval) = VariableAddress[f] : +# 221| m0_52(char[3]) = Uninitialized[f] : &:r0_51 +# 221| r0_53(int) = Constant[0] : +# 221| r0_54(glval) = PointerAdd[1] : r0_51, r0_53 +# 221| r0_55(char) = Constant[0] : +# 221| m0_56(char) = Store : &:r0_54, r0_55 +# 221| m0_57(char[3]) = Chi : total:m0_52, partial:m0_56 +# 221| r0_58(int) = Constant[1] : +# 221| r0_59(glval) = PointerAdd[1] : r0_51, r0_58 +# 221| r0_60(unknown[2]) = Constant[0] : +# 221| m0_61(unknown[2]) = Store : &:r0_59, r0_60 +# 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 +# 222| v0_63(void) = NoOp : +# 213| v0_64(void) = ReturnVoid : +# 213| v0_65(void) = UnmodeledUse : mu* +# 213| v0_66(void) = AliasedUse : ~m0_1 +# 213| v0_67(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cd..a38c66dcaf8 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,13 @@ int ModeledCallTarget(int x) { return y; } +void InitArray() { + char a_pad[32] = ""; + char a_nopad[4] = "foo"; + char a_infer[] = "blah"; + char b[2]; + char c[2] = {}; + char d[2] = { 0 }; + char e[2] = { 0, 1 }; + char f[3] = { 0 }; +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 5ac06cadb55..056b0cd5ac7 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -833,3 +833,68 @@ ssa.cpp: # 207| v0_22(void) = UnmodeledUse : mu* # 207| v0_23(void) = AliasedUse : ~mu0_2 # 207| v0_24(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| mu0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| r0_4(glval) = StringConstant[""] : +# 214| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 +# 214| mu0_6(char[1]) = Store : &:r0_3, r0_5 +# 214| r0_7(unknown[31]) = Constant[0] : +# 214| r0_8(int) = Constant[1] : +# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 +# 214| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 +# 215| r0_11(glval) = VariableAddress[a_nopad] : +# 215| r0_12(glval) = StringConstant["foo"] : +# 215| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 +# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 +# 216| r0_15(glval) = VariableAddress[a_infer] : +# 216| r0_16(glval) = StringConstant["blah"] : +# 216| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 +# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 +# 217| r0_19(glval) = VariableAddress[b] : +# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 +# 218| r0_21(glval) = VariableAddress[c] : +# 218| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 +# 218| r0_23(int) = Constant[0] : +# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 +# 218| r0_25(unknown[2]) = Constant[0] : +# 218| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 +# 219| r0_27(glval) = VariableAddress[d] : +# 219| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 +# 219| r0_29(int) = Constant[0] : +# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 +# 219| r0_31(char) = Constant[0] : +# 219| mu0_32(char) = Store : &:r0_30, r0_31 +# 219| r0_33(int) = Constant[1] : +# 219| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 +# 219| r0_35(char) = Constant[0] : +# 219| mu0_36(char) = Store : &:r0_34, r0_35 +# 220| r0_37(glval) = VariableAddress[e] : +# 220| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 +# 220| r0_39(int) = Constant[0] : +# 220| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 +# 220| r0_41(char) = Constant[0] : +# 220| mu0_42(char) = Store : &:r0_40, r0_41 +# 220| r0_43(int) = Constant[1] : +# 220| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 +# 220| r0_45(char) = Constant[1] : +# 220| mu0_46(char) = Store : &:r0_44, r0_45 +# 221| r0_47(glval) = VariableAddress[f] : +# 221| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 +# 221| r0_49(int) = Constant[0] : +# 221| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 +# 221| r0_51(char) = Constant[0] : +# 221| mu0_52(char) = Store : &:r0_50, r0_51 +# 221| r0_53(int) = Constant[1] : +# 221| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 +# 221| r0_55(unknown[2]) = Constant[0] : +# 221| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 +# 222| v0_57(void) = NoOp : +# 213| v0_58(void) = ReturnVoid : +# 213| v0_59(void) = UnmodeledUse : mu* +# 213| v0_60(void) = AliasedUse : ~mu0_2 +# 213| v0_61(void) = ExitFunction : From 81ad11090ed4291a1671f40b7be8cb32d258bb24 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 6 Nov 2019 10:54:43 -0800 Subject: [PATCH 184/232] C++: uninit instr for string literal initializers --- .../internal/TranslatedDeclarationEntry.qll | 3 +- .../test/library-tests/ir/ir/raw_ir.expected | 119 ++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 121 +++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 119 ++++++++--------- 4 files changed, 187 insertions(+), 175 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 294a539ec31..c3572bd0e79 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -120,7 +120,8 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or - getInitialization() instanceof TranslatedListInitialization + getInitialization() instanceof TranslatedListInitialization or + getInitialization() instanceof TranslatedStringLiteralInitialization } } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 90c3061114e..b4480e1c580 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2666,64 +2666,67 @@ ir.cpp: # 571| mu0_1(unknown) = AliasedDefinition : # 571| mu0_2(unknown) = UnmodeledDefinition : # 572| r0_3(glval) = VariableAddress[a_pad] : -# 572| r0_4(glval) = StringConstant[""] : -# 572| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 -# 572| mu0_6(char[1]) = Store : &:r0_3, r0_5 -# 572| r0_7(unknown[31]) = Constant[0] : -# 572| r0_8(int) = Constant[1] : -# 572| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 572| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 573| r0_11(glval) = VariableAddress[a_nopad] : -# 573| r0_12(glval) = StringConstant["foo"] : -# 573| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 -# 573| mu0_14(char[4]) = Store : &:r0_11, r0_13 -# 574| r0_15(glval) = VariableAddress[a_infer] : -# 574| r0_16(glval) = StringConstant["blah"] : -# 574| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 -# 574| mu0_18(char[5]) = Store : &:r0_15, r0_17 -# 575| r0_19(glval) = VariableAddress[b] : -# 575| mu0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 576| r0_21(glval) = VariableAddress[c] : -# 576| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 576| r0_23(int) = Constant[0] : -# 576| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 576| r0_25(unknown[2]) = Constant[0] : -# 576| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 577| r0_27(glval) = VariableAddress[d] : -# 577| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 577| r0_29(int) = Constant[0] : -# 577| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 577| r0_31(char) = Constant[0] : -# 577| mu0_32(char) = Store : &:r0_30, r0_31 -# 577| r0_33(int) = Constant[1] : -# 577| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 -# 577| r0_35(char) = Constant[0] : -# 577| mu0_36(char) = Store : &:r0_34, r0_35 -# 578| r0_37(glval) = VariableAddress[e] : -# 578| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 -# 578| r0_39(int) = Constant[0] : -# 578| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 -# 578| r0_41(char) = Constant[0] : -# 578| mu0_42(char) = Store : &:r0_40, r0_41 -# 578| r0_43(int) = Constant[1] : -# 578| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 -# 578| r0_45(char) = Constant[1] : -# 578| mu0_46(char) = Store : &:r0_44, r0_45 -# 579| r0_47(glval) = VariableAddress[f] : -# 579| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 -# 579| r0_49(int) = Constant[0] : -# 579| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 -# 579| r0_51(char) = Constant[0] : -# 579| mu0_52(char) = Store : &:r0_50, r0_51 -# 579| r0_53(int) = Constant[1] : -# 579| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 -# 579| r0_55(unknown[2]) = Constant[0] : -# 579| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 -# 580| v0_57(void) = NoOp : -# 571| v0_58(void) = ReturnVoid : -# 571| v0_59(void) = UnmodeledUse : mu* -# 571| v0_60(void) = AliasedUse : ~mu0_2 -# 571| v0_61(void) = ExitFunction : +# 572| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 572| r0_5(glval) = StringConstant[""] : +# 572| r0_6(char[1]) = Load : &:r0_5, ~mu0_2 +# 572| mu0_7(char[1]) = Store : &:r0_3, r0_6 +# 572| r0_8(unknown[31]) = Constant[0] : +# 572| r0_9(int) = Constant[1] : +# 572| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 +# 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 573| r0_12(glval) = VariableAddress[a_nopad] : +# 573| mu0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 +# 573| r0_14(glval) = StringConstant["foo"] : +# 573| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 +# 573| mu0_16(char[4]) = Store : &:r0_12, r0_15 +# 574| r0_17(glval) = VariableAddress[a_infer] : +# 574| mu0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 +# 574| r0_19(glval) = StringConstant["blah"] : +# 574| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 +# 574| mu0_21(char[5]) = Store : &:r0_17, r0_20 +# 575| r0_22(glval) = VariableAddress[b] : +# 575| mu0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 576| r0_24(glval) = VariableAddress[c] : +# 576| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 576| r0_26(int) = Constant[0] : +# 576| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 576| r0_28(unknown[2]) = Constant[0] : +# 576| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 577| r0_30(glval) = VariableAddress[d] : +# 577| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 577| r0_32(int) = Constant[0] : +# 577| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 577| r0_34(char) = Constant[0] : +# 577| mu0_35(char) = Store : &:r0_33, r0_34 +# 577| r0_36(int) = Constant[1] : +# 577| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 +# 577| r0_38(char) = Constant[0] : +# 577| mu0_39(char) = Store : &:r0_37, r0_38 +# 578| r0_40(glval) = VariableAddress[e] : +# 578| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 +# 578| r0_42(int) = Constant[0] : +# 578| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 +# 578| r0_44(char) = Constant[0] : +# 578| mu0_45(char) = Store : &:r0_43, r0_44 +# 578| r0_46(int) = Constant[1] : +# 578| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 +# 578| r0_48(char) = Constant[1] : +# 578| mu0_49(char) = Store : &:r0_47, r0_48 +# 579| r0_50(glval) = VariableAddress[f] : +# 579| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 +# 579| r0_52(int) = Constant[0] : +# 579| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 +# 579| r0_54(char) = Constant[0] : +# 579| mu0_55(char) = Store : &:r0_53, r0_54 +# 579| r0_56(int) = Constant[1] : +# 579| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 +# 579| r0_58(unknown[2]) = Constant[0] : +# 579| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 +# 580| v0_60(void) = NoOp : +# 571| v0_61(void) = ReturnVoid : +# 571| v0_62(void) = UnmodeledUse : mu* +# 571| v0_63(void) = AliasedUse : ~mu0_2 +# 571| v0_64(void) = ExitFunction : # 584| void VarArgs() # 584| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 7345c6a5204..bc2bea75e11 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -876,67 +876,72 @@ ssa.cpp: # 213| m0_1(unknown) = AliasedDefinition : # 213| mu0_2(unknown) = UnmodeledDefinition : # 214| r0_3(glval) = VariableAddress[a_pad] : -# 214| r0_4(glval) = StringConstant[""] : -# 214| r0_5(char[1]) = Load : &:r0_4, ~m0_1 -# 214| m0_6(char[1]) = Store : &:r0_3, r0_5 -# 214| r0_7(unknown[31]) = Constant[0] : -# 214| r0_8(int) = Constant[1] : -# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 214| m0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 215| r0_11(glval) = VariableAddress[a_nopad] : -# 215| r0_12(glval) = StringConstant["foo"] : -# 215| r0_13(char[4]) = Load : &:r0_12, ~m0_1 -# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 -# 216| r0_15(glval) = VariableAddress[a_infer] : -# 216| r0_16(glval) = StringConstant["blah"] : -# 216| r0_17(char[5]) = Load : &:r0_16, ~m0_1 -# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 -# 217| r0_19(glval) = VariableAddress[b] : -# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 218| r0_21(glval) = VariableAddress[c] : -# 218| m0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 218| r0_23(int) = Constant[0] : -# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 218| r0_25(unknown[2]) = Constant[0] : -# 218| m0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 219| r0_27(glval) = VariableAddress[d] : -# 219| m0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 219| r0_29(int) = Constant[0] : -# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 219| r0_31(char) = Constant[0] : -# 219| m0_32(char) = Store : &:r0_30, r0_31 -# 219| m0_33(char[2]) = Chi : total:m0_28, partial:m0_32 -# 219| r0_34(int) = Constant[1] : -# 219| r0_35(glval) = PointerAdd[1] : r0_27, r0_34 +# 214| m0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = StringConstant[""] : +# 214| r0_6(char[1]) = Load : &:r0_5, ~m0_1 +# 214| m0_7(char[1]) = Store : &:r0_3, r0_6 +# 214| m0_8(char[32]) = Chi : total:m0_4, partial:m0_7 +# 214| r0_9(unknown[31]) = Constant[0] : +# 214| r0_10(int) = Constant[1] : +# 214| r0_11(glval) = PointerAdd[1] : r0_3, r0_10 +# 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9 +# 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12 +# 215| r0_14(glval) = VariableAddress[a_nopad] : +# 215| m0_15(char[4]) = Uninitialized[a_nopad] : &:r0_14 +# 215| r0_16(glval) = StringConstant["foo"] : +# 215| r0_17(char[4]) = Load : &:r0_16, ~m0_1 +# 215| m0_18(char[4]) = Store : &:r0_14, r0_17 +# 216| r0_19(glval) = VariableAddress[a_infer] : +# 216| m0_20(char[5]) = Uninitialized[a_infer] : &:r0_19 +# 216| r0_21(glval) = StringConstant["blah"] : +# 216| r0_22(char[5]) = Load : &:r0_21, ~m0_1 +# 216| m0_23(char[5]) = Store : &:r0_19, r0_22 +# 217| r0_24(glval) = VariableAddress[b] : +# 217| m0_25(char[2]) = Uninitialized[b] : &:r0_24 +# 218| r0_26(glval) = VariableAddress[c] : +# 218| m0_27(char[2]) = Uninitialized[c] : &:r0_26 +# 218| r0_28(int) = Constant[0] : +# 218| r0_29(glval) = PointerAdd[1] : r0_26, r0_28 +# 218| r0_30(unknown[2]) = Constant[0] : +# 218| m0_31(unknown[2]) = Store : &:r0_29, r0_30 +# 219| r0_32(glval) = VariableAddress[d] : +# 219| m0_33(char[2]) = Uninitialized[d] : &:r0_32 +# 219| r0_34(int) = Constant[0] : +# 219| r0_35(glval) = PointerAdd[1] : r0_32, r0_34 # 219| r0_36(char) = Constant[0] : # 219| m0_37(char) = Store : &:r0_35, r0_36 # 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 -# 220| r0_39(glval) = VariableAddress[e] : -# 220| m0_40(char[2]) = Uninitialized[e] : &:r0_39 -# 220| r0_41(int) = Constant[0] : -# 220| r0_42(glval) = PointerAdd[1] : r0_39, r0_41 -# 220| r0_43(char) = Constant[0] : -# 220| m0_44(char) = Store : &:r0_42, r0_43 -# 220| m0_45(char[2]) = Chi : total:m0_40, partial:m0_44 -# 220| r0_46(int) = Constant[1] : -# 220| r0_47(glval) = PointerAdd[1] : r0_39, r0_46 -# 220| r0_48(char) = Constant[1] : +# 219| r0_39(int) = Constant[1] : +# 219| r0_40(glval) = PointerAdd[1] : r0_32, r0_39 +# 219| r0_41(char) = Constant[0] : +# 219| m0_42(char) = Store : &:r0_40, r0_41 +# 219| m0_43(char[2]) = Chi : total:m0_38, partial:m0_42 +# 220| r0_44(glval) = VariableAddress[e] : +# 220| m0_45(char[2]) = Uninitialized[e] : &:r0_44 +# 220| r0_46(int) = Constant[0] : +# 220| r0_47(glval) = PointerAdd[1] : r0_44, r0_46 +# 220| r0_48(char) = Constant[0] : # 220| m0_49(char) = Store : &:r0_47, r0_48 # 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 -# 221| r0_51(glval) = VariableAddress[f] : -# 221| m0_52(char[3]) = Uninitialized[f] : &:r0_51 -# 221| r0_53(int) = Constant[0] : -# 221| r0_54(glval) = PointerAdd[1] : r0_51, r0_53 -# 221| r0_55(char) = Constant[0] : -# 221| m0_56(char) = Store : &:r0_54, r0_55 -# 221| m0_57(char[3]) = Chi : total:m0_52, partial:m0_56 -# 221| r0_58(int) = Constant[1] : -# 221| r0_59(glval) = PointerAdd[1] : r0_51, r0_58 -# 221| r0_60(unknown[2]) = Constant[0] : -# 221| m0_61(unknown[2]) = Store : &:r0_59, r0_60 +# 220| r0_51(int) = Constant[1] : +# 220| r0_52(glval) = PointerAdd[1] : r0_44, r0_51 +# 220| r0_53(char) = Constant[1] : +# 220| m0_54(char) = Store : &:r0_52, r0_53 +# 220| m0_55(char[2]) = Chi : total:m0_50, partial:m0_54 +# 221| r0_56(glval) = VariableAddress[f] : +# 221| m0_57(char[3]) = Uninitialized[f] : &:r0_56 +# 221| r0_58(int) = Constant[0] : +# 221| r0_59(glval) = PointerAdd[1] : r0_56, r0_58 +# 221| r0_60(char) = Constant[0] : +# 221| m0_61(char) = Store : &:r0_59, r0_60 # 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 -# 222| v0_63(void) = NoOp : -# 213| v0_64(void) = ReturnVoid : -# 213| v0_65(void) = UnmodeledUse : mu* -# 213| v0_66(void) = AliasedUse : ~m0_1 -# 213| v0_67(void) = ExitFunction : +# 221| r0_63(int) = Constant[1] : +# 221| r0_64(glval) = PointerAdd[1] : r0_56, r0_63 +# 221| r0_65(unknown[2]) = Constant[0] : +# 221| m0_66(unknown[2]) = Store : &:r0_64, r0_65 +# 221| m0_67(char[3]) = Chi : total:m0_62, partial:m0_66 +# 222| v0_68(void) = NoOp : +# 213| v0_69(void) = ReturnVoid : +# 213| v0_70(void) = UnmodeledUse : mu* +# 213| v0_71(void) = AliasedUse : ~m0_1 +# 213| v0_72(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 056b0cd5ac7..93f27b13f02 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -840,61 +840,64 @@ ssa.cpp: # 213| mu0_1(unknown) = AliasedDefinition : # 213| mu0_2(unknown) = UnmodeledDefinition : # 214| r0_3(glval) = VariableAddress[a_pad] : -# 214| r0_4(glval) = StringConstant[""] : -# 214| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 -# 214| mu0_6(char[1]) = Store : &:r0_3, r0_5 -# 214| r0_7(unknown[31]) = Constant[0] : -# 214| r0_8(int) = Constant[1] : -# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 214| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 215| r0_11(glval) = VariableAddress[a_nopad] : -# 215| r0_12(glval) = StringConstant["foo"] : -# 215| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 -# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 -# 216| r0_15(glval) = VariableAddress[a_infer] : -# 216| r0_16(glval) = StringConstant["blah"] : -# 216| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 -# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 -# 217| r0_19(glval) = VariableAddress[b] : -# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 218| r0_21(glval) = VariableAddress[c] : -# 218| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 218| r0_23(int) = Constant[0] : -# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 218| r0_25(unknown[2]) = Constant[0] : -# 218| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 219| r0_27(glval) = VariableAddress[d] : -# 219| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 219| r0_29(int) = Constant[0] : -# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 219| r0_31(char) = Constant[0] : -# 219| mu0_32(char) = Store : &:r0_30, r0_31 -# 219| r0_33(int) = Constant[1] : -# 219| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 -# 219| r0_35(char) = Constant[0] : -# 219| mu0_36(char) = Store : &:r0_34, r0_35 -# 220| r0_37(glval) = VariableAddress[e] : -# 220| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 -# 220| r0_39(int) = Constant[0] : -# 220| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 -# 220| r0_41(char) = Constant[0] : -# 220| mu0_42(char) = Store : &:r0_40, r0_41 -# 220| r0_43(int) = Constant[1] : -# 220| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 -# 220| r0_45(char) = Constant[1] : -# 220| mu0_46(char) = Store : &:r0_44, r0_45 -# 221| r0_47(glval) = VariableAddress[f] : -# 221| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 -# 221| r0_49(int) = Constant[0] : -# 221| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 -# 221| r0_51(char) = Constant[0] : -# 221| mu0_52(char) = Store : &:r0_50, r0_51 -# 221| r0_53(int) = Constant[1] : -# 221| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 -# 221| r0_55(unknown[2]) = Constant[0] : -# 221| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 -# 222| v0_57(void) = NoOp : -# 213| v0_58(void) = ReturnVoid : -# 213| v0_59(void) = UnmodeledUse : mu* -# 213| v0_60(void) = AliasedUse : ~mu0_2 -# 213| v0_61(void) = ExitFunction : +# 214| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = StringConstant[""] : +# 214| r0_6(char[1]) = Load : &:r0_5, ~mu0_2 +# 214| mu0_7(char[1]) = Store : &:r0_3, r0_6 +# 214| r0_8(unknown[31]) = Constant[0] : +# 214| r0_9(int) = Constant[1] : +# 214| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 +# 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 215| r0_12(glval) = VariableAddress[a_nopad] : +# 215| m0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 +# 215| r0_14(glval) = StringConstant["foo"] : +# 215| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 +# 215| m0_16(char[4]) = Store : &:r0_12, r0_15 +# 216| r0_17(glval) = VariableAddress[a_infer] : +# 216| m0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 +# 216| r0_19(glval) = StringConstant["blah"] : +# 216| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 +# 216| m0_21(char[5]) = Store : &:r0_17, r0_20 +# 217| r0_22(glval) = VariableAddress[b] : +# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 218| r0_24(glval) = VariableAddress[c] : +# 218| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 218| r0_26(int) = Constant[0] : +# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 218| r0_28(unknown[2]) = Constant[0] : +# 218| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 219| r0_30(glval) = VariableAddress[d] : +# 219| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 219| r0_32(int) = Constant[0] : +# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 219| r0_34(char) = Constant[0] : +# 219| mu0_35(char) = Store : &:r0_33, r0_34 +# 219| r0_36(int) = Constant[1] : +# 219| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 +# 219| r0_38(char) = Constant[0] : +# 219| mu0_39(char) = Store : &:r0_37, r0_38 +# 220| r0_40(glval) = VariableAddress[e] : +# 220| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 +# 220| r0_42(int) = Constant[0] : +# 220| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 +# 220| r0_44(char) = Constant[0] : +# 220| mu0_45(char) = Store : &:r0_43, r0_44 +# 220| r0_46(int) = Constant[1] : +# 220| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 +# 220| r0_48(char) = Constant[1] : +# 220| mu0_49(char) = Store : &:r0_47, r0_48 +# 221| r0_50(glval) = VariableAddress[f] : +# 221| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 +# 221| r0_52(int) = Constant[0] : +# 221| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 +# 221| r0_54(char) = Constant[0] : +# 221| mu0_55(char) = Store : &:r0_53, r0_54 +# 221| r0_56(int) = Constant[1] : +# 221| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 +# 221| r0_58(unknown[2]) = Constant[0] : +# 221| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 +# 222| v0_60(void) = NoOp : +# 213| v0_61(void) = ReturnVoid : +# 213| v0_62(void) = UnmodeledUse : mu* +# 213| v0_63(void) = AliasedUse : ~mu0_2 +# 213| v0_64(void) = ExitFunction : From 0040c9fb4c1defdc206d9558b4e87925f8ca2ce0 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 6 Nov 2019 05:42:59 -0800 Subject: [PATCH 185/232] Update links to OWASP cheat sheet --- cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp | 2 +- .../src/Security Features/CWE-079/XSS.qhelp | 2 +- .../CWE-090/LDAPInjection.qhelp | 2 +- .../CWE-451/MissingXFrameOptions.qhelp | 2 +- .../CWE-601/UrlRedirect.qhelp | 2 +- .../CWE-611/UseXmlSecureResolver.qhelp | 2 +- java/ql/src/Security/CWE/CWE-079/XSS.qhelp | 2 +- .../src/Security/CWE/CWE-089/SqlTainted.qhelp | 2 +- .../Security/CWE/CWE-089/SqlUnescaped.qhelp | 2 +- .../src/Security/CWE/CWE-319/HttpsUrls.qhelp | 2 +- java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp | 2 +- .../CWE/CWE-319/UseSSLSocketFactories.qhelp | 2 +- .../CWE/CWE-502/UnsafeDeserialization.qhelp | 2 +- java/ql/src/Security/CWE/CWE-611/XXE.qhelp | 2 +- .../semmle/code/java/security/XmlParsers.qll | 24 +++++++++---------- .../CWE-020/IncompleteHostnameRegExp.qhelp | 2 +- .../IncompleteUrlSubstringSanitization.qhelp | 2 +- .../CWE-020/MissingRegExpAnchor.qhelp | 2 +- .../src/Security/CWE-079/ReflectedXss.qhelp | 2 +- .../ql/src/Security/CWE-079/StoredXss.qhelp | 2 +- javascript/ql/src/Security/CWE-079/Xss.qhelp | 4 ++-- .../CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- .../CWE-451/MissingXFrameOptions.qhelp | 2 +- .../CWE-502/UnsafeDeserialization.qhelp | 2 +- .../CWE-601/ClientSideUrlRedirect.qhelp | 2 +- .../CWE-601/ServerSideUrlRedirect.qhelp | 2 +- .../CWE-770/MissingRateLimiting.qhelp | 2 +- .../CWE-916/InsufficientPasswordHash.qhelp | 2 +- .../CWE-020/IncompleteHostnameRegExp.qhelp | 2 +- .../IncompleteUrlSubstringSanitization.qhelp | 2 +- .../CWE-079/Jinja2WithoutEscaping.qhelp | 2 +- .../src/Security/CWE-079/ReflectedXss.qhelp | 2 +- .../src/Security/CWE-089/SqlInjection.qhelp | 2 +- .../CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- .../CWE-502/UnsafeDeserialization.qhelp | 2 +- .../ql/src/Security/CWE-601/UrlRedirect.qhelp | 2 +- 36 files changed, 48 insertions(+), 48 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp index ccd297c3b36..4ad7a40fed6 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp @@ -34,7 +34,7 @@ characters before writing to the HTML page.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp index 9a71290694d..409be1030e7 100644 --- a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp +++ b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp @@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp index 118e91ed4d9..04f01720ce6 100644 --- a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp @@ -33,7 +33,7 @@ the query cannot be changed by a malicious user.

    -
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • +
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • OWASP: Preventing LDAP Injection in Java.
  • AntiXSS doc: LdapFilterEncode.
  • AntiXSS doc: LdapDistinguishedNameEncode.
  • diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp index 7df415aff5b..6d5d298c8e4 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp @@ -51,7 +51,7 @@ This next example shows how to specify the X-Frame-Options header w
  • OWASP: -Clickjacking Defense Cheat Sheet. +Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp index 989796b6738..3cf3cdaba6e 100644 --- a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp +++ b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp @@ -32,7 +32,7 @@ It also shows how to remedy the problem by validating the user input against a k
  • OWASP: -XSS +XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp index 2e8e4fcf272..11b1136db4d 100644 --- a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp +++ b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp @@ -38,7 +38,7 @@ The solution is to set the DtdProcessing property to DtdProce
  • OWASP: -XML External Entity (XXE) Prevention Cheat Sheet. +XML External Entity (XXE) Prevention Cheat Sheet.
  • Microsoft Docs: System.XML: Security considerations. diff --git a/java/ql/src/Security/CWE/CWE-079/XSS.qhelp b/java/ql/src/Security/CWE/CWE-079/XSS.qhelp index 85bdfb130fd..428b44c8db9 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSS.qhelp +++ b/java/ql/src/Security/CWE/CWE-079/XSS.qhelp @@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp index cab60173a62..f1ba450d4a0 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp @@ -67,7 +67,7 @@ in the environment variable or user-supplied value are not given any special tre
  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp index 7415235610c..e469415d683 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp @@ -39,7 +39,7 @@ treatment.

  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp index 8b8b0eff847..2cfdca624fb 100644 --- a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp @@ -37,7 +37,7 @@ connection is a secure SSL connection.

    Class HttpsURLConnection.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp index 5856086330f..cec4937c8f7 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp @@ -38,7 +38,7 @@ Class HttpsURLConnection. Class SSLSocket.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp index 56e9be97345..bf0dbc0bcac 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp @@ -33,7 +33,7 @@ uses explicit SSL factories, which are preferable.

    Class SSLSocketFactory.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp index 4fb0ad88b45..61b50a986e3 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp @@ -58,7 +58,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp index 75c5a2d4d7a..93d420f7495 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp +++ b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp @@ -52,7 +52,7 @@ OWASP vulnerability description:
  • OWASP guidance on parsing xml files: -XXE Prevention Cheat Sheet. +XXE Prevention Cheat Sheet.
  • Paper by Timothy Morgen: diff --git a/java/ql/src/semmle/code/java/security/XmlParsers.qll b/java/ql/src/semmle/code/java/security/XmlParsers.qll index 37a72f8128e..1f582489497 100644 --- a/java/ql/src/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/src/semmle/code/java/security/XmlParsers.qll @@ -49,7 +49,7 @@ abstract class ParserConfig extends MethodAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#DocumentBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j */ /** The class `javax.xml.parsers.DocumentBuilderFactory`. */ @@ -227,7 +227,7 @@ class SafeDocumentBuilder extends DocumentBuilderConstruction { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLInputFactory_.28a_StAX_parser.29 + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser */ /** The class `javax.xml.stream.XMLInputFactory`. */ @@ -353,7 +353,7 @@ class SafeXmlInputFactory extends VarAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxbuilder */ /** @@ -429,7 +429,7 @@ class SafeSAXBuilder extends VarAccess { /* * The case in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller * will be split into two, one covers a SAXParser as a sink, the other the SAXSource as a sink. */ @@ -545,7 +545,7 @@ class SafeSAXParser extends MethodAccess { } } -/* SAXReader: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXReader */ +/* SAXReader: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxreader */ /** * The class `org.dom4j.io.SAXReader`. */ @@ -621,7 +621,7 @@ class SafeSAXReader extends VarAccess { } } -/* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLReader */ +/* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader */ /** The class `org.xml.sax.XMLReader`. */ class XMLReader extends RefType { XMLReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") } @@ -756,7 +756,7 @@ class CreatedSafeXMLReader extends Call { /* * SAXSource in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.transform.sax.SAXSource` */ @@ -811,7 +811,7 @@ class SafeSAXSource extends Expr { } } -/* Transformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#TransformerFactory */ +/* Transformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory */ /** An access to a method use for configuring a transformer or schema. */ abstract class TransformerConfig extends MethodAccess { /** Holds if the configuration is disabled */ @@ -975,7 +975,7 @@ class SafeTransformer extends MethodAccess { } /* - * SAXTransformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXTransformerFactory + * SAXTransformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxtransformerfactory * Has an extra method called newFilter. */ @@ -996,7 +996,7 @@ class SAXTransformerFactoryNewXMLFilter extends XmlParserCall { } } -/* Schema: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SchemaFactory */ +/* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */ /** The class `javax.xml.validation.SchemaFactory`. */ class SchemaFactory extends RefType { SchemaFactory() { this.hasQualifiedName("javax.xml.validation", "SchemaFactory") } @@ -1060,7 +1060,7 @@ class SafeSchemaFactory extends VarAccess { } } -/* Unmarshaller: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller */ +/* Unmarshaller: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.bind.Unmarshaller`. */ class XmlUnmarshaller extends RefType { XmlUnmarshaller() { this.hasQualifiedName("javax.xml.bind", "Unmarshaller") } @@ -1081,7 +1081,7 @@ class XmlUnmarshal extends XmlParserCall { override predicate isSafe() { none() } } -/* XPathExpression: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XPathExpression */ +/* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */ /** The class `javax.xml.xpath.XPathExpression`. */ class XPathExpression extends RefType { XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") } diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index 771c446c66f..a5e0a78b8cc 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -68,6 +68,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index b23557aa557..90e6f2762e2 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -83,6 +83,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp index 807574c5898..015e510f0fb 100644 --- a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp +++ b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp @@ -71,6 +71,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp index 0502889fba0..dcbf0ba6f07 100644 --- a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -37,7 +37,7 @@ Sanitizing the user-controlled data prevents the vulnerability:
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp index 1c3fde01798..0e6ed6456c9 100644 --- a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp @@ -48,7 +48,7 @@
  • OWASP: - XSS + XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/Xss.qhelp b/javascript/ql/src/Security/CWE-079/Xss.qhelp index 34ea1d821b6..c974c87b188 100644 --- a/javascript/ql/src/Security/CWE-079/Xss.qhelp +++ b/javascript/ql/src/Security/CWE-079/Xss.qhelp @@ -33,12 +33,12 @@ leaving the website vulnerable to cross-site scripting.
  • OWASP: -DOM based +DOM based XSS Prevention Cheat Sheet.
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 9b230852919..e0ccf71572f 100644 --- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -45,7 +45,7 @@
  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp index ad659015d67..e73ea063b5d 100644 --- a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp +++ b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp @@ -67,7 +67,7 @@
  • OWASP: - Clickjacking Defense Cheat Sheet. + Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index e7b956b10f4..5f5b77cbd7d 100644 --- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -41,7 +41,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Neal Poole: diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp index d4d36fe09bc..392df3e6cbd 100644 --- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp @@ -31,7 +31,7 @@ website of their choosing, which facilitates phishing attacks: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp index cb54477dde5..2052f16146b 100644 --- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp index 1832a803a77..8d4bc0ab5d0 100644 --- a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp +++ b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp @@ -36,7 +36,7 @@ can be used:
  • OWASP: -Denial of Service Cheat Sheet. +Denial of Service Cheat Sheet.
  • Wikipedia: Denial-of-service attack. diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp index 2b1d2b02a31..1efdbe694b1 100644 --- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp +++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp @@ -50,6 +50,6 @@ -
  • OWASP: Password storage.
  • +
  • OWASP: Password storage.
  • diff --git a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index b542ae252eb..8eb0f43eb01 100644 --- a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -64,6 +64,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index 6c783a4f729..828c71153b5 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -80,6 +80,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp index 4497437aac1..5b4d21bb37e 100644 --- a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp +++ b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp @@ -38,7 +38,7 @@ Jinja2: API. Wikipedia: Cross-site scripting.
  • -OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet. +OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp index 8cdeb4d3e79..04a83fba6b4 100644 --- a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -31,7 +31,7 @@ The second view is safe as first_name is escaped, so it is not vuln
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-089/SqlInjection.qhelp b/python/ql/src/Security/CWE-089/SqlInjection.qhelp index 286b71a6047..63941706e84 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.qhelp +++ b/python/ql/src/Security/CWE-089/SqlInjection.qhelp @@ -51,6 +51,6 @@ vulnerable to SQL injection attacks. In this example, if username w
  • Wikipedia: SQL injection.
  • -
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • +
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 6cc787e52e4..1b4031b1cc5 100644 --- a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -49,7 +49,7 @@
  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index f298e62695f..8c2660b9865 100644 --- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -49,7 +49,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp index c2e053f030b..756a43cc106 100644 --- a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp +++ b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • From e314869e5cb134670d63119749abf286489af670 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 09:06:39 +0000 Subject: [PATCH 186/232] JavaScript: Classify files with names ending in `_min` as minified. We already do the same for `-min` and `.min`. [Here](https://github.com/antoniogarrote/rdfstore-js/blob/master/dist/rdfstore_min.js) is a real-world example. --- change-notes/1.23/analysis-javascript.md | 4 ++-- javascript/ql/src/semmle/javascript/AST.qll | 2 +- .../query-tests/filters/ClassifyFiles/ClassifyFiles.expected | 3 +++ .../ql/test/query-tests/filters/ClassifyFiles/tst-min.js | 0 .../ql/test/query-tests/filters/ClassifyFiles/tst.min.js | 0 .../ql/test/query-tests/filters/ClassifyFiles/tst_min.js | 0 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 49f527af424..a7f41473eea 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -2,6 +2,8 @@ ## General improvements +* Automatic classification of generated and minified files has been improved, in particular files generated by Doxygen are now recognized. + * Support for `globalThis` has been added. * Support for the following frameworks and libraries has been improved: @@ -14,8 +16,6 @@ * TypeScript 3.6 and 3.7 features are now supported. -* Automatic classification of generated files has been improved, in particular files generated by Doxygen are now recognized. - ## New queries | **Query** | **Tags** | **Purpose** | diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index efc9ef53af3..66a5155458c 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -150,7 +150,7 @@ class TopLevel extends @toplevel, StmtContainer { /** Holds if this toplevel is minified. */ predicate isMinified() { // file name contains 'min' (not as part of a longer word) - getFile().getBaseName().regexpMatch(".*[^-.]*[-.]min([-.].*)?\\.\\w+") + getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+") or exists(int numstmt | numstmt = strictcount(Stmt s | s.getTopLevel() = this) | // there are more than two statements per line on average diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected index 7c583b1bf39..da235c205ee 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected @@ -39,8 +39,11 @@ | textmate.html:0:0:0:0 | textmate.html | generated | | tmpl2.html:0:0:0:0 | tmpl2.html | template | | tmpl.html:0:0:0:0 | tmpl.html | template | +| tst-min.js:0:0:0:0 | tst-min.js | generated | | tst.browserify.js:0:0:0:0 | tst.browserify.js | generated | | tst.dart.js:0:0:0:0 | tst.dart.js | generated | +| tst.min.js:0:0:0:0 | tst.min.js | generated | +| tst_min.js:0:0:0:0 | tst_min.js | generated | | twitter-text.js:0:0:0:0 | twitter-text.js | library | | twitter_text.js:0:0:0:0 | twitter_text.js | library | | unannotated-externs-1.js:0:0:0:0 | unannotated-externs-1.js | externs | diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js new file mode 100644 index 00000000000..e69de29bb2d From 6385528d5fe939df63bf03314206ada09ed4cc19 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 7 Nov 2019 11:30:18 +0100 Subject: [PATCH 187/232] C++/C#: Fix getIRTypeForPRValue join order This predicate was taking 39s on a snapshot of Facebook Fizz because it had disjuncts like this: 43685 ~0% {1} r34 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 43685 ~1% {2} r35 = JOIN r34 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r34.<0> 170371500 ~2% {2} r36 = JOIN r35 WITH IRType::IRSizedType#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r35.<1> 43685 ~6% {2} r37 = JOIN r36 WITH IRType::IRFunctionAddressType#class#ff AS R ON FIRST 1 OUTPUT r36.<1>, r36.<0> Instead of fixing the joins in `getIRTypeForPRValue` itself, I've changed the `IRType::getByteSize` predicate such that the optimiser knows how to join with it efficiently. The disjunct shown above now looks like this instead: 43685 ~0% {1} r26 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 43685 ~1% {2} r27 = JOIN r26 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r26.<0> 43685 ~6% {2} r28 = JOIN r27 WITH IRType::IRFunctionAddressType::getByteSize#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r27.<1>, R.<1> --- .../code/cpp/ir/implementation/IRType.qll | 27 +++++++++++++++++-- .../code/csharp/ir/implementation/IRType.qll | 27 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 0abfa14023d..cb652230d2a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -42,6 +42,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +108,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +119,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +146,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +161,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +175,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +192,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +207,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +238,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 0abfa14023d..cb652230d2a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -42,6 +42,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +108,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +119,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +146,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +161,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +175,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +192,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +207,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +238,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { From c0884e9a888ea8fcde2bb01a85a080533efcdaad Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 7 Nov 2019 10:34:59 +0000 Subject: [PATCH 188/232] C++: Update expected results. --- .../copy_from_prototype.expected | 2 +- .../syntax-zoo/drawDifferent.expected | 161 ++++++++++++------ .../syntax-zoo/tellDifferent.expected | 11 ++ .../elements.expected | 4 +- 4 files changed, 122 insertions(+), 56 deletions(-) diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected index 9d77efe772f..f5ef2d77c98 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected @@ -13,7 +13,7 @@ | copy_from_prototype.cpp:13:7:13:7 | c | c::c(const c &) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(c &&) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(const c &) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | Unknown literal | +| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | | copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected index 00cdd21f9ed..6e255ec81b2 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected @@ -1,53 +1,108 @@ -| staticlocals__staticlocals_f2_extractor | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_extractor | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_extractor | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_extractor | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_extractor | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_extractor | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_extractor | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_extractor | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_extractor | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_extractor | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_extractor | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_extractor | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_extractor | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_extractor | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_extractor | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_extractor | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_extractor | true | 22500 | 22499 | | -| staticlocals__staticlocals_f2_ql | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_ql | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_ql | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_ql | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_ql | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_ql | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_ql | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_ql | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_ql | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_ql | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_ql | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_ql | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22484 | | -| staticlocals__staticlocals_f2_ql | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_ql | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_ql | true | 22482 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22484 | 22482 | | -| staticlocals__staticlocals_f2_ql | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_ql | true | 22500 | 22499 | | +| pointer_to_member__pmIsConstT_extractor | false | 21747 | 21747 | pmIsConstT | +| pointer_to_member__pmIsConstT_extractor | false | 21756 | 21756 | declaration | +| pointer_to_member__pmIsConstT_extractor | false | 21759 | 21759 | return ... | +| pointer_to_member__pmIsConstT_extractor | false | 21762 | 21762 | { ... } | +| pointer_to_member__pmIsConstT_extractor | false | 21766 | 21766 | {...} | +| pointer_to_member__pmIsConstT_extractor | false | 21773 | 21773 | x1 | +| pointer_to_member__pmIsConstT_extractor | false | 21777 | 21777 | & ... | +| pointer_to_member__pmIsConstT_extractor | false | 21784 | 21784 | f1 | +| pointer_to_member__pmIsConstT_extractor | false | 21788 | 21788 | & ... | +| pointer_to_member__pmIsConstT_extractor | false | 21791 | 21791 | initializer for pms | +| pointer_to_member__pmIsConstT_extractor | true | 21756 | 21759 | | +| pointer_to_member__pmIsConstT_extractor | true | 21759 | 21747 | | +| pointer_to_member__pmIsConstT_extractor | true | 21762 | 21756 | | +| pointer_to_member__pmIsConstT_ql | false | 21747 | 21747 | pmIsConstT | +| pointer_to_member__pmIsConstT_ql | false | 21756 | 21756 | declaration | +| pointer_to_member__pmIsConstT_ql | false | 21759 | 21759 | return ... | +| pointer_to_member__pmIsConstT_ql | false | 21762 | 21762 | { ... } | +| pointer_to_member__pmIsConstT_ql | false | 21766 | 21766 | {...} | +| pointer_to_member__pmIsConstT_ql | false | 21773 | 21773 | x1 | +| pointer_to_member__pmIsConstT_ql | false | 21777 | 21777 | & ... | +| pointer_to_member__pmIsConstT_ql | false | 21784 | 21784 | f1 | +| pointer_to_member__pmIsConstT_ql | false | 21788 | 21788 | & ... | +| pointer_to_member__pmIsConstT_ql | false | 21791 | 21791 | initializer for pms | +| pointer_to_member__pmIsConstT_ql | true | 21756 | 21791 | | +| pointer_to_member__pmIsConstT_ql | true | 21759 | 21747 | | +| pointer_to_member__pmIsConstT_ql | true | 21762 | 21756 | | +| pointer_to_member__pmIsConstT_ql | true | 21766 | 21759 | | +| pointer_to_member__pmIsConstT_ql | true | 21773 | 21777 | | +| pointer_to_member__pmIsConstT_ql | true | 21777 | 21784 | | +| pointer_to_member__pmIsConstT_ql | true | 21784 | 21788 | | +| pointer_to_member__pmIsConstT_ql | true | 21788 | 21766 | | +| pointer_to_member__pmIsConstT_ql | true | 21791 | 21773 | | +| staticlocals__staticlocals_f2_extractor | false | 31503 | 31503 | f2 | +| staticlocals__staticlocals_f2_extractor | false | 31509 | 31509 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31512 | 31512 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31515 | 31515 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31518 | 31518 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31521 | 31521 | return ... | +| staticlocals__staticlocals_f2_extractor | false | 31524 | 31524 | { ... } | +| staticlocals__staticlocals_f2_extractor | false | 31527 | 31527 | call to C | +| staticlocals__staticlocals_f2_extractor | false | 31530 | 31530 | initializer for c | +| staticlocals__staticlocals_f2_extractor | false | 31533 | 31533 | call to addOne | +| staticlocals__staticlocals_f2_extractor | false | 31539 | 31539 | 2 | +| staticlocals__staticlocals_f2_extractor | false | 31544 | 31544 | initializer for j | +| staticlocals__staticlocals_f2_extractor | false | 31546 | 31546 | call to addOne | +| staticlocals__staticlocals_f2_extractor | false | 31554 | 31554 | 2 | +| staticlocals__staticlocals_f2_extractor | false | 31556 | 31556 | initializer for two | +| staticlocals__staticlocals_f2_extractor | false | 31560 | 31560 | two | +| staticlocals__staticlocals_f2_extractor | false | 31568 | 31568 | initializer for i | +| staticlocals__staticlocals_f2_extractor | true | 31509 | 31556 | | +| staticlocals__staticlocals_f2_extractor | true | 31512 | 31515 | | +| staticlocals__staticlocals_f2_extractor | true | 31515 | 31518 | | +| staticlocals__staticlocals_f2_extractor | true | 31518 | 31521 | | +| staticlocals__staticlocals_f2_extractor | true | 31521 | 31503 | | +| staticlocals__staticlocals_f2_extractor | true | 31524 | 31509 | | +| staticlocals__staticlocals_f2_extractor | true | 31554 | 31512 | | +| staticlocals__staticlocals_f2_extractor | true | 31556 | 31554 | | +| staticlocals__staticlocals_f2_ql | false | 31503 | 31503 | f2 | +| staticlocals__staticlocals_f2_ql | false | 31509 | 31509 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31512 | 31512 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31515 | 31515 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31518 | 31518 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31521 | 31521 | return ... | +| staticlocals__staticlocals_f2_ql | false | 31524 | 31524 | { ... } | +| staticlocals__staticlocals_f2_ql | false | 31527 | 31527 | call to C | +| staticlocals__staticlocals_f2_ql | false | 31530 | 31530 | initializer for c | +| staticlocals__staticlocals_f2_ql | false | 31533 | 31533 | call to addOne | +| staticlocals__staticlocals_f2_ql | false | 31539 | 31539 | 2 | +| staticlocals__staticlocals_f2_ql | false | 31544 | 31544 | initializer for j | +| staticlocals__staticlocals_f2_ql | false | 31546 | 31546 | call to addOne | +| staticlocals__staticlocals_f2_ql | false | 31554 | 31554 | 2 | +| staticlocals__staticlocals_f2_ql | false | 31556 | 31556 | initializer for two | +| staticlocals__staticlocals_f2_ql | false | 31560 | 31560 | two | +| staticlocals__staticlocals_f2_ql | false | 31568 | 31568 | initializer for i | +| staticlocals__staticlocals_f2_ql | true | 31509 | 31556 | | +| staticlocals__staticlocals_f2_ql | true | 31512 | 31515 | | +| staticlocals__staticlocals_f2_ql | true | 31515 | 31518 | | +| staticlocals__staticlocals_f2_ql | true | 31518 | 31521 | | +| staticlocals__staticlocals_f2_ql | true | 31518 | 31530 | | +| staticlocals__staticlocals_f2_ql | true | 31521 | 31503 | | +| staticlocals__staticlocals_f2_ql | true | 31524 | 31509 | | +| staticlocals__staticlocals_f2_ql | true | 31527 | 31521 | | +| staticlocals__staticlocals_f2_ql | true | 31530 | 31527 | | +| staticlocals__staticlocals_f2_ql | true | 31554 | 31512 | | +| staticlocals__staticlocals_f2_ql | true | 31556 | 31554 | | +| staticlocals__staticlocals_f3_extractor | false | 31473 | 31473 | f3 | +| staticlocals__staticlocals_f3_extractor | false | 31477 | 31477 | declaration | +| staticlocals__staticlocals_f3_extractor | false | 31480 | 31480 | return ... | +| staticlocals__staticlocals_f3_extractor | false | 31483 | 31483 | { ... } | +| staticlocals__staticlocals_f3_extractor | false | 31492 | 31492 | value | +| staticlocals__staticlocals_f3_extractor | false | 31496 | 31496 | (int)... | +| staticlocals__staticlocals_f3_extractor | false | 31498 | 31498 | initializer for i | +| staticlocals__staticlocals_f3_extractor | true | 31477 | 31480 | | +| staticlocals__staticlocals_f3_extractor | true | 31480 | 31473 | | +| staticlocals__staticlocals_f3_extractor | true | 31483 | 31477 | | +| staticlocals__staticlocals_f3_ql | false | 31473 | 31473 | f3 | +| staticlocals__staticlocals_f3_ql | false | 31477 | 31477 | declaration | +| staticlocals__staticlocals_f3_ql | false | 31480 | 31480 | return ... | +| staticlocals__staticlocals_f3_ql | false | 31483 | 31483 | { ... } | +| staticlocals__staticlocals_f3_ql | false | 31492 | 31492 | value | +| staticlocals__staticlocals_f3_ql | false | 31496 | 31496 | (int)... | +| staticlocals__staticlocals_f3_ql | false | 31498 | 31498 | initializer for i | +| staticlocals__staticlocals_f3_ql | true | 31477 | 31480 | | +| staticlocals__staticlocals_f3_ql | true | 31477 | 31498 | | +| staticlocals__staticlocals_f3_ql | true | 31480 | 31473 | | +| staticlocals__staticlocals_f3_ql | true | 31483 | 31477 | | +| staticlocals__staticlocals_f3_ql | true | 31492 | 31480 | | +| staticlocals__staticlocals_f3_ql | true | 31498 | 31492 | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected index 0e06bb202c4..ae6f3429892 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected @@ -1,3 +1,14 @@ +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:44:11:44:28 | initializer for pms | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from extractor | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | initializer for pms | pointer_to_member.cpp:44:14:44:18 | x1 | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | {...} | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:13:44:18 | & ... | pointer_to_member.cpp:44:22:44:26 | f1 | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:14:44:18 | x1 | pointer_to_member.cpp:44:13:44:18 | & ... | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:21:44:26 | & ... | pointer_to_member.cpp:44:11:44:28 | {...} | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:22:44:26 | f1 | pointer_to_member.cpp:44:21:44:26 | & ... | Standard edge, only from QL | uninstantiated | | staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | | | staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | | | staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:3:39:34 | declaration | staticlocals.cpp:39:18:39:33 | initializer for i | Standard edge, only from QL | uninstantiated | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | initializer for i | staticlocals.cpp:39:18:39:33 | value | Standard edge, only from QL | uninstantiated | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | value | staticlocals.cpp:40:1:40:1 | return ... | Standard edge, only from QL | uninstantiated | diff --git a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected index 802903a40b6..99a6201c59c 100644 --- a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected +++ b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected @@ -317,8 +317,8 @@ | test.cpp:19:9:19:24 | call to expression | | test.cpp:19:9:19:25 | ExprStmt | | test.cpp:19:9:19:25 | ExprStmt | -| test.cpp:19:15:19:18 | Unknown literal | | test.cpp:19:15:19:18 | call to funx | +| test.cpp:19:15:19:18 | funx | | test.cpp:19:20:19:23 | (reference to) | | test.cpp:19:20:19:23 | valx | | test.cpp:19:20:19:23 | valx | @@ -356,8 +356,8 @@ | test.cpp:30:13:30:22 | call to expression | | test.cpp:30:13:30:23 | ExprStmt | | test.cpp:30:13:30:23 | ExprStmt | -| test.cpp:30:15:30:20 | Unknown literal | | test.cpp:30:15:30:20 | call to eparse | +| test.cpp:30:15:30:20 | eparse | | test.cpp:31:9:31:9 | return ... | | test.cpp:31:9:31:9 | return ... | | test.cpp:34:6:34:11 | define | From ddf1ef8a7d65ceb869fae56b83be92da6a768c0c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 7 Nov 2019 10:35:26 +0000 Subject: [PATCH 189/232] C++: Add new test case for template member change We now output literals for accesses to members of template parameters: So for `foo` in the following example: ``` template void bar(T& t) { T.foo(1) } ``` --- .../CPP-172-template-members/test.cpp | 19 +++++++++++++++++++ .../CPP-172-template-members/test.expected | 2 ++ .../CPP-172-template-members/test.ql | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp new file mode 100644 index 00000000000..9a624d5d9f0 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp @@ -0,0 +1,19 @@ + + +class A { +public: + void foo(); + int k; +}; + +class B { +public: + template + B(T x) { + int k = x.k; + x.foo(); + } +}; + +A a; +B b(a); diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected new file mode 100644 index 00000000000..29d00dc147a --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected @@ -0,0 +1,2 @@ +| test.cpp:13:15:13:15 | k | +| test.cpp:14:7:14:9 | foo | diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql new file mode 100644 index 00000000000..233c7cdce8d --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Literal l +select l From db2039d8a75cdd76bc31c35be122d579d9015584 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 7 Nov 2019 13:17:57 +0000 Subject: [PATCH 190/232] docs: learn codeql terminology note --- docs/language/learn-ql/index.rst | 12 +++++++++ docs/language/learn-ql/terminology-note.rst | 27 +++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docs/language/learn-ql/terminology-note.rst diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 76649890131..5a3c70c4580 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -9,6 +9,18 @@ Here, you can query open source projects directly, without having to download Co CodeQL is based on a powerful query language called QL. The following topics help you understand QL in general, as well as how to use it when analyzing code with CodeQL. +.. pull-quote:: + + Important + + If you've previously used QL, you may notice some slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. + +.. toctree:: + :hidden: + + terminology-note + + .. _getting-started: Getting started diff --git a/docs/language/learn-ql/terminology-note.rst b/docs/language/learn-ql/terminology-note.rst new file mode 100644 index 00000000000..794106d5705 --- /dev/null +++ b/docs/language/learn-ql/terminology-note.rst @@ -0,0 +1,27 @@ +Recent terminology changes +=========================== + +We recently started using new terminology to make it clearer to users what our products do. +This note gives some information about what has changed. + +CodeQL +------ + +CodeQL is the code analysis platform formerly known as QL. +CodeQL treats code as data, and CodeQL analysis is based on running queries against your code to check for errors and find bugs and vulnerabilities. +The CodeQL product includes the tools, scripts, queries, and libraries used in CodeQL analysis. + +QL +--- + +Previously we used the term QL to refer to the whole code analysis platform, which has been renamed CodeQL. +The name QL now only refers to the query language that powers CodeQL analysis. + +The CodeQL queries and libraries used to analyze source code are written in QL. +These queries and libraries are open source, and can be found in the `CodeQL repository `__. +QL is a general-purpose, object-oriented language that can be used to query any kind of data. + +CodeQL databases +---------------- + +QL snapshots have been renamed CodeQL databases. CodeQL databases contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. From 8544850945898dee993de50e7f909e22f711f79c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 12:00:50 +0000 Subject: [PATCH 191/232] JS: Generalize StringOps::Includes to ::InclusionTest --- javascript/ql/src/javascript.qll | 1 + .../src/semmle/javascript/InclusionTests.qll | 173 ++++++++++++++++++ .../ql/src/semmle/javascript/StringOps.qll | 157 +--------------- .../javascript/dataflow/TaintTracking.qll | 15 +- 4 files changed, 188 insertions(+), 158 deletions(-) create mode 100644 javascript/ql/src/semmle/javascript/InclusionTests.qll diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 9e75e032b1c..a6df138c592 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -28,6 +28,7 @@ import semmle.javascript.Functions import semmle.javascript.GlobalAccessPaths import semmle.javascript.HTML import semmle.javascript.HtmlSanitizers +import semmle.javascript.InclusionTests import semmle.javascript.JSDoc import semmle.javascript.JSON import semmle.javascript.JsonParsers diff --git a/javascript/ql/src/semmle/javascript/InclusionTests.qll b/javascript/ql/src/semmle/javascript/InclusionTests.qll new file mode 100644 index 00000000000..7a90dbf1583 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/InclusionTests.qll @@ -0,0 +1,173 @@ +/** + * Contains classes for recognizing array and string inclusion tests. + */ +private import javascript + +/** + * A expression that checks if an element is contained in an array + * or is a substring of another string. + * + * Examples: + * ``` + * A.includes(B) + * A.indexOf(B) !== -1 + * A.indexOf(B) >= 0 + * ~A.indexOf(B) + * ``` + */ +class InclusionTest extends DataFlow::Node { + InclusionTest::Range range; + + InclusionTest() { this = range } + + /** Gets the `A` in `A.includes(B)`. */ + DataFlow::Node getContainerNode() { result = range.getContainerNode() } + + /** Gets the `B` in `A.includes(B)`. */ + DataFlow::Node getContainedNode() { result = range.getContainedNode() } + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = range.getPolarity() } +} + +module InclusionTest { + /** + * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. + * + * Note that this also includes calls to the array method named `includes`. + */ + abstract class Range extends DataFlow::Node { + /** Gets the `A` in `A.includes(B)`. */ + abstract DataFlow::Node getContainerNode(); + + /** Gets the `B` in `A.includes(B)`. */ + abstract DataFlow::Node getContainedNode(); + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = true } + } + + /** + * A call to a method named `includes`, assumed to refer to `String.prototype.includes` + * or `Array.prototype.includes`. + */ + private class Includes_Native extends Range, DataFlow::MethodCallNode { + Includes_Native() { + getMethodName() = "includes" and + getNumArgument() = 1 + } + + override DataFlow::Node getContainerNode() { result = getReceiver() } + + override DataFlow::Node getContainedNode() { result = getArgument(0) } + } + + /** + * A call to `_.includes` or similar, assumed to operate on strings. + */ + private class Includes_Library extends Range, DataFlow::CallNode { + Includes_Library() { + exists(string name | + this = LodashUnderscore::member(name).getACall() and + (name = "includes" or name = "include" or name = "contains") + or + this = Closure::moduleImport("goog.string." + name).getACall() and + (name = "contains" or name = "caseInsensitiveContains") + ) + } + + override DataFlow::Node getContainerNode() { result = getArgument(0) } + + override DataFlow::Node getContainedNode() { result = getArgument(1) } + } + + /** + * A check of form `A.indexOf(B) !== -1` or similar. + */ + private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override EqualityTest astNode; + + Includes_IndexOfEquals() { + exists(Expr index | astNode.hasOperands(indexOf, index) | + // one operand is of the form `whitelist.indexOf(x)` + indexOf.getMethodName() = "indexOf" and + // and the other one is -1 + index.getIntValue() = -1 + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } + } + + /** + * A check of form `A.indexOf(B) >= 0` or similar. + */ + private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override RelationalComparison astNode; + boolean polarity; + + Includes_IndexOfRelational() { + exists(Expr lesser, Expr greater | + astNode.getLesserOperand() = lesser and + astNode.getGreaterOperand() = greater and + indexOf.getMethodName() = "indexOf" and + indexOf.getNumArgument() = 1 + | + polarity = true and + greater = indexOf and + ( + lesser.getIntValue() = 0 and astNode.isInclusive() + or + lesser.getIntValue() = -1 and not astNode.isInclusive() + ) + or + polarity = false and + lesser = indexOf and + ( + greater.getIntValue() = -1 and astNode.isInclusive() + or + greater.getIntValue() = 0 and not astNode.isInclusive() + ) + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = polarity } + } + + /** + * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. + */ + private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override BitNotExpr astNode; + + Includes_IndexOfBitwise() { + astNode.getOperand() = indexOf and + indexOf.getMethodName() = "indexOf" + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + } +} diff --git a/javascript/ql/src/semmle/javascript/StringOps.qll b/javascript/ql/src/semmle/javascript/StringOps.qll index f33dbd9f74d..d916e8e469d 100644 --- a/javascript/ql/src/semmle/javascript/StringOps.qll +++ b/javascript/ql/src/semmle/javascript/StringOps.qll @@ -185,162 +185,15 @@ module StringOps { /** * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. * - * Note that this also includes calls to the array method named `includes`. + * Note that this class is equivalent to `InclusionTest`, which also matches + * inclusion tests on array objects. */ - class Includes extends DataFlow::Node { - Includes::Range range; - - Includes() { this = range } - + class Includes extends InclusionTest { /** Gets the `A` in `A.includes(B)`. */ - DataFlow::Node getBaseString() { result = range.getBaseString() } + DataFlow::Node getBaseString() { result = getContainerNode() } /** Gets the `B` in `A.includes(B)`. */ - DataFlow::Node getSubstring() { result = range.getSubstring() } - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = range.getPolarity() } - } - - module Includes { - /** - * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. - * - * Note that this also includes calls to the array method named `includes`. - */ - abstract class Range extends DataFlow::Node { - /** Gets the `A` in `A.includes(B)`. */ - abstract DataFlow::Node getBaseString(); - - /** Gets the `B` in `A.includes(B)`. */ - abstract DataFlow::Node getSubstring(); - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = true } - } - - /** - * A call to a method named `includes`, assumed to refer to `String.prototype.includes`. - */ - private class Includes_Native extends Range, DataFlow::MethodCallNode { - Includes_Native() { - getMethodName() = "includes" and - getNumArgument() = 1 - } - - override DataFlow::Node getBaseString() { result = getReceiver() } - - override DataFlow::Node getSubstring() { result = getArgument(0) } - } - - /** - * A call to `_.includes` or similar, assumed to operate on strings. - */ - private class Includes_Library extends Range, DataFlow::CallNode { - Includes_Library() { - exists(string name | - this = LodashUnderscore::member(name).getACall() and - (name = "includes" or name = "include" or name = "contains") - or - this = Closure::moduleImport("goog.string." + name).getACall() and - (name = "contains" or name = "caseInsensitiveContains") - ) - } - - override DataFlow::Node getBaseString() { result = getArgument(0) } - - override DataFlow::Node getSubstring() { result = getArgument(1) } - } - - /** - * A check of form `A.indexOf(B) !== -1` or similar. - */ - private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override EqualityTest astNode; - - Includes_IndexOfEquals() { - exists(Expr index | astNode.hasOperands(indexOf, index) | - // one operand is of the form `whitelist.indexOf(x)` - indexOf.getMethodName() = "indexOf" and - // and the other one is -1 - index.getIntValue() = -1 - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } - } - - /** - * A check of form `A.indexOf(B) >= 0` or similar. - */ - private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override RelationalComparison astNode; - boolean polarity; - - Includes_IndexOfRelational() { - exists(Expr lesser, Expr greater | - astNode.getLesserOperand() = lesser and - astNode.getGreaterOperand() = greater and - indexOf.getMethodName() = "indexOf" and - indexOf.getNumArgument() = 1 - | - polarity = true and - greater = indexOf and - ( - lesser.getIntValue() = 0 and astNode.isInclusive() - or - lesser.getIntValue() = -1 and not astNode.isInclusive() - ) - or - polarity = false and - lesser = indexOf and - ( - greater.getIntValue() = -1 and astNode.isInclusive() - or - greater.getIntValue() = 0 and not astNode.isInclusive() - ) - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = polarity } - } - - /** - * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. - */ - private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override BitNotExpr astNode; - - Includes_IndexOfBitwise() { - astNode.getOperand() = indexOf and - indexOf.getMethodName() = "indexOf" - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - } + DataFlow::Node getSubstring() { result = getContainedNode() } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 06a0d904261..a8a8356e6e2 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -781,15 +781,18 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } - /** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */ - class StringInclusionSanitizer extends AdditionalSanitizerGuardNode { - StringOps::Includes includes; + /** DEPRECATED. This class has been renamed to `InclusionSanitizer`. */ + deprecated class StringInclusionSanitizer = InclusionSanitizer; - StringInclusionSanitizer() { this = includes } + /** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */ + class InclusionSanitizer extends AdditionalSanitizerGuardNode { + InclusionTest inclusion; + + InclusionSanitizer() { this = inclusion } override predicate sanitizes(boolean outcome, Expr e) { - outcome = includes.getPolarity() and - e = includes.getSubstring().asExpr() + outcome = inclusion.getPolarity() and + e = inclusion.getContainedNode().asExpr() } override predicate appliesTo(Configuration cfg) { any() } From d31ec56ea68b5354d458924a360b36675222935a Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 7 Nov 2019 14:39:52 +0000 Subject: [PATCH 192/232] Update docs/language/learn-ql/index.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 5a3c70c4580..add850f5806 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -13,7 +13,7 @@ CodeQL is based on a powerful query language called QL. The following topics hel Important - If you've previously used QL, you may notice some slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. + If you've previously used QL, you may notice slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. .. toctree:: :hidden: @@ -98,4 +98,4 @@ Search .. * :ref:`genindex` remove index for the time being as we currently have no tags -* :ref:`search` \ No newline at end of file +* :ref:`search` From 8178e3e67117ed4af20b7a2c5320a01ae86c811f Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 7 Nov 2019 14:40:04 +0000 Subject: [PATCH 193/232] Update docs/language/learn-ql/terminology-note.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/terminology-note.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/terminology-note.rst b/docs/language/learn-ql/terminology-note.rst index 794106d5705..552d7b2789c 100644 --- a/docs/language/learn-ql/terminology-note.rst +++ b/docs/language/learn-ql/terminology-note.rst @@ -24,4 +24,4 @@ QL is a general-purpose, object-oriented language that can be used to query any CodeQL databases ---------------- -QL snapshots have been renamed CodeQL databases. CodeQL databases contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. +QL snapshots have been renamed CodeQL databases. :doc:`CodeQL databases ` contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. From b5af4e5acd50d5cd19c22c398247fc8a99b11c31 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Thu, 7 Nov 2019 16:32:18 +0000 Subject: [PATCH 194/232] C++: Remove tests for CFG differences Now that we have switched over, they are no longer interesting. --- .../syntax-zoo/drawDifferent.expected | 108 ------------------ .../library-tests/syntax-zoo/drawDifferent.ql | 10 -- .../syntax-zoo/tellDifferent.expected | 14 --- .../library-tests/syntax-zoo/tellDifferent.ql | 13 --- 4 files changed, 145 deletions(-) delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected deleted file mode 100644 index 6e255ec81b2..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected +++ /dev/null @@ -1,108 +0,0 @@ -| pointer_to_member__pmIsConstT_extractor | false | 21747 | 21747 | pmIsConstT | -| pointer_to_member__pmIsConstT_extractor | false | 21756 | 21756 | declaration | -| pointer_to_member__pmIsConstT_extractor | false | 21759 | 21759 | return ... | -| pointer_to_member__pmIsConstT_extractor | false | 21762 | 21762 | { ... } | -| pointer_to_member__pmIsConstT_extractor | false | 21766 | 21766 | {...} | -| pointer_to_member__pmIsConstT_extractor | false | 21773 | 21773 | x1 | -| pointer_to_member__pmIsConstT_extractor | false | 21777 | 21777 | & ... | -| pointer_to_member__pmIsConstT_extractor | false | 21784 | 21784 | f1 | -| pointer_to_member__pmIsConstT_extractor | false | 21788 | 21788 | & ... | -| pointer_to_member__pmIsConstT_extractor | false | 21791 | 21791 | initializer for pms | -| pointer_to_member__pmIsConstT_extractor | true | 21756 | 21759 | | -| pointer_to_member__pmIsConstT_extractor | true | 21759 | 21747 | | -| pointer_to_member__pmIsConstT_extractor | true | 21762 | 21756 | | -| pointer_to_member__pmIsConstT_ql | false | 21747 | 21747 | pmIsConstT | -| pointer_to_member__pmIsConstT_ql | false | 21756 | 21756 | declaration | -| pointer_to_member__pmIsConstT_ql | false | 21759 | 21759 | return ... | -| pointer_to_member__pmIsConstT_ql | false | 21762 | 21762 | { ... } | -| pointer_to_member__pmIsConstT_ql | false | 21766 | 21766 | {...} | -| pointer_to_member__pmIsConstT_ql | false | 21773 | 21773 | x1 | -| pointer_to_member__pmIsConstT_ql | false | 21777 | 21777 | & ... | -| pointer_to_member__pmIsConstT_ql | false | 21784 | 21784 | f1 | -| pointer_to_member__pmIsConstT_ql | false | 21788 | 21788 | & ... | -| pointer_to_member__pmIsConstT_ql | false | 21791 | 21791 | initializer for pms | -| pointer_to_member__pmIsConstT_ql | true | 21756 | 21791 | | -| pointer_to_member__pmIsConstT_ql | true | 21759 | 21747 | | -| pointer_to_member__pmIsConstT_ql | true | 21762 | 21756 | | -| pointer_to_member__pmIsConstT_ql | true | 21766 | 21759 | | -| pointer_to_member__pmIsConstT_ql | true | 21773 | 21777 | | -| pointer_to_member__pmIsConstT_ql | true | 21777 | 21784 | | -| pointer_to_member__pmIsConstT_ql | true | 21784 | 21788 | | -| pointer_to_member__pmIsConstT_ql | true | 21788 | 21766 | | -| pointer_to_member__pmIsConstT_ql | true | 21791 | 21773 | | -| staticlocals__staticlocals_f2_extractor | false | 31503 | 31503 | f2 | -| staticlocals__staticlocals_f2_extractor | false | 31509 | 31509 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31512 | 31512 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31515 | 31515 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31518 | 31518 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31521 | 31521 | return ... | -| staticlocals__staticlocals_f2_extractor | false | 31524 | 31524 | { ... } | -| staticlocals__staticlocals_f2_extractor | false | 31527 | 31527 | call to C | -| staticlocals__staticlocals_f2_extractor | false | 31530 | 31530 | initializer for c | -| staticlocals__staticlocals_f2_extractor | false | 31533 | 31533 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 31539 | 31539 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 31544 | 31544 | initializer for j | -| staticlocals__staticlocals_f2_extractor | false | 31546 | 31546 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 31554 | 31554 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 31556 | 31556 | initializer for two | -| staticlocals__staticlocals_f2_extractor | false | 31560 | 31560 | two | -| staticlocals__staticlocals_f2_extractor | false | 31568 | 31568 | initializer for i | -| staticlocals__staticlocals_f2_extractor | true | 31509 | 31556 | | -| staticlocals__staticlocals_f2_extractor | true | 31512 | 31515 | | -| staticlocals__staticlocals_f2_extractor | true | 31515 | 31518 | | -| staticlocals__staticlocals_f2_extractor | true | 31518 | 31521 | | -| staticlocals__staticlocals_f2_extractor | true | 31521 | 31503 | | -| staticlocals__staticlocals_f2_extractor | true | 31524 | 31509 | | -| staticlocals__staticlocals_f2_extractor | true | 31554 | 31512 | | -| staticlocals__staticlocals_f2_extractor | true | 31556 | 31554 | | -| staticlocals__staticlocals_f2_ql | false | 31503 | 31503 | f2 | -| staticlocals__staticlocals_f2_ql | false | 31509 | 31509 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31512 | 31512 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31515 | 31515 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31518 | 31518 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31521 | 31521 | return ... | -| staticlocals__staticlocals_f2_ql | false | 31524 | 31524 | { ... } | -| staticlocals__staticlocals_f2_ql | false | 31527 | 31527 | call to C | -| staticlocals__staticlocals_f2_ql | false | 31530 | 31530 | initializer for c | -| staticlocals__staticlocals_f2_ql | false | 31533 | 31533 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 31539 | 31539 | 2 | -| staticlocals__staticlocals_f2_ql | false | 31544 | 31544 | initializer for j | -| staticlocals__staticlocals_f2_ql | false | 31546 | 31546 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 31554 | 31554 | 2 | -| staticlocals__staticlocals_f2_ql | false | 31556 | 31556 | initializer for two | -| staticlocals__staticlocals_f2_ql | false | 31560 | 31560 | two | -| staticlocals__staticlocals_f2_ql | false | 31568 | 31568 | initializer for i | -| staticlocals__staticlocals_f2_ql | true | 31509 | 31556 | | -| staticlocals__staticlocals_f2_ql | true | 31512 | 31515 | | -| staticlocals__staticlocals_f2_ql | true | 31515 | 31518 | | -| staticlocals__staticlocals_f2_ql | true | 31518 | 31521 | | -| staticlocals__staticlocals_f2_ql | true | 31518 | 31530 | | -| staticlocals__staticlocals_f2_ql | true | 31521 | 31503 | | -| staticlocals__staticlocals_f2_ql | true | 31524 | 31509 | | -| staticlocals__staticlocals_f2_ql | true | 31527 | 31521 | | -| staticlocals__staticlocals_f2_ql | true | 31530 | 31527 | | -| staticlocals__staticlocals_f2_ql | true | 31554 | 31512 | | -| staticlocals__staticlocals_f2_ql | true | 31556 | 31554 | | -| staticlocals__staticlocals_f3_extractor | false | 31473 | 31473 | f3 | -| staticlocals__staticlocals_f3_extractor | false | 31477 | 31477 | declaration | -| staticlocals__staticlocals_f3_extractor | false | 31480 | 31480 | return ... | -| staticlocals__staticlocals_f3_extractor | false | 31483 | 31483 | { ... } | -| staticlocals__staticlocals_f3_extractor | false | 31492 | 31492 | value | -| staticlocals__staticlocals_f3_extractor | false | 31496 | 31496 | (int)... | -| staticlocals__staticlocals_f3_extractor | false | 31498 | 31498 | initializer for i | -| staticlocals__staticlocals_f3_extractor | true | 31477 | 31480 | | -| staticlocals__staticlocals_f3_extractor | true | 31480 | 31473 | | -| staticlocals__staticlocals_f3_extractor | true | 31483 | 31477 | | -| staticlocals__staticlocals_f3_ql | false | 31473 | 31473 | f3 | -| staticlocals__staticlocals_f3_ql | false | 31477 | 31477 | declaration | -| staticlocals__staticlocals_f3_ql | false | 31480 | 31480 | return ... | -| staticlocals__staticlocals_f3_ql | false | 31483 | 31483 | { ... } | -| staticlocals__staticlocals_f3_ql | false | 31492 | 31492 | value | -| staticlocals__staticlocals_f3_ql | false | 31496 | 31496 | (int)... | -| staticlocals__staticlocals_f3_ql | false | 31498 | 31498 | initializer for i | -| staticlocals__staticlocals_f3_ql | true | 31477 | 31480 | | -| staticlocals__staticlocals_f3_ql | true | 31477 | 31498 | | -| staticlocals__staticlocals_f3_ql | true | 31480 | 31473 | | -| staticlocals__staticlocals_f3_ql | true | 31483 | 31477 | | -| staticlocals__staticlocals_f3_ql | true | 31492 | 31480 | | -| staticlocals__staticlocals_f3_ql | true | 31498 | 31492 | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql deleted file mode 100644 index 5b80f3c92a0..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql +++ /dev/null @@ -1,10 +0,0 @@ -// query-type: graph -import Compare - -from - Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, - string label -where - AllCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label) and - differentScope(scopeElement) -select scopeString, isEdge, x, y, label diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected deleted file mode 100644 index ae6f3429892..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected +++ /dev/null @@ -1,14 +0,0 @@ -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:44:11:44:28 | initializer for pms | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from extractor | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | initializer for pms | pointer_to_member.cpp:44:14:44:18 | x1 | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | {...} | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:13:44:18 | & ... | pointer_to_member.cpp:44:22:44:26 | f1 | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:14:44:18 | x1 | pointer_to_member.cpp:44:13:44:18 | & ... | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:21:44:26 | & ... | pointer_to_member.cpp:44:11:44:28 | {...} | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:22:44:26 | f1 | pointer_to_member.cpp:44:21:44:26 | & ... | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:3:39:34 | declaration | staticlocals.cpp:39:18:39:33 | initializer for i | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | initializer for i | staticlocals.cpp:39:18:39:33 | value | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | value | staticlocals.cpp:40:1:40:1 | return ... | Standard edge, only from QL | uninstantiated | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql deleted file mode 100644 index f4b2509c17b..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql +++ /dev/null @@ -1,13 +0,0 @@ -import Compare - -string describeTemplate(ControlFlowNode node) { - node.isFromTemplateInstantiation(_) and - result = "instantiation" - or - node.isFromUninstantiatedTemplate(_) and - result = "uninstantiated" -} - -from ControlFlowNode n1, ControlFlowNode n2, string msg -where differentEdge(n1, n2, msg) -select getScopeName(n1), n1, n2, msg, concat(describeTemplate(n1), ", ") From ae1377447e925f17a4b61db23f8231dcae1f6915 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 7 Nov 2019 13:55:49 -0800 Subject: [PATCH 195/232] C++: only generate uninits when needed --- .../internal/TranslatedDeclarationEntry.qll | 2 +- .../raw/internal/TranslatedInitialization.qll | 2 +- .../test/library-tests/ir/ir/raw_ir.expected | 102 ++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 114 +++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 102 ++++++++-------- 5 files changed, 158 insertions(+), 164 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index c3572bd0e79..15b5db3ef74 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -121,7 +121,7 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or getInitialization() instanceof TranslatedListInitialization or - getInitialization() instanceof TranslatedStringLiteralInitialization + getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 21ad11513bd..c6911a048c7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -340,7 +340,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati * Holds if the `elementCount` array elements starting at `startIndex` must be * zero initialized. */ - private predicate zeroInitRange(int startIndex, int elementCount) { + predicate zeroInitRange(int startIndex, int elementCount) { exists(int targetCount | startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b4480e1c580..e763b3c1263 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2675,58 +2675,56 @@ ir.cpp: # 572| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 # 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 # 573| r0_12(glval) = VariableAddress[a_nopad] : -# 573| mu0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 -# 573| r0_14(glval) = StringConstant["foo"] : -# 573| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 -# 573| mu0_16(char[4]) = Store : &:r0_12, r0_15 -# 574| r0_17(glval) = VariableAddress[a_infer] : -# 574| mu0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 -# 574| r0_19(glval) = StringConstant["blah"] : -# 574| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 -# 574| mu0_21(char[5]) = Store : &:r0_17, r0_20 -# 575| r0_22(glval) = VariableAddress[b] : -# 575| mu0_23(char[2]) = Uninitialized[b] : &:r0_22 -# 576| r0_24(glval) = VariableAddress[c] : -# 576| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 -# 576| r0_26(int) = Constant[0] : -# 576| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 -# 576| r0_28(unknown[2]) = Constant[0] : -# 576| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 -# 577| r0_30(glval) = VariableAddress[d] : -# 577| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 -# 577| r0_32(int) = Constant[0] : -# 577| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 -# 577| r0_34(char) = Constant[0] : -# 577| mu0_35(char) = Store : &:r0_33, r0_34 -# 577| r0_36(int) = Constant[1] : -# 577| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 -# 577| r0_38(char) = Constant[0] : -# 577| mu0_39(char) = Store : &:r0_37, r0_38 -# 578| r0_40(glval) = VariableAddress[e] : -# 578| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 -# 578| r0_42(int) = Constant[0] : -# 578| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 -# 578| r0_44(char) = Constant[0] : -# 578| mu0_45(char) = Store : &:r0_43, r0_44 -# 578| r0_46(int) = Constant[1] : -# 578| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 -# 578| r0_48(char) = Constant[1] : -# 578| mu0_49(char) = Store : &:r0_47, r0_48 -# 579| r0_50(glval) = VariableAddress[f] : -# 579| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 -# 579| r0_52(int) = Constant[0] : -# 579| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 -# 579| r0_54(char) = Constant[0] : -# 579| mu0_55(char) = Store : &:r0_53, r0_54 -# 579| r0_56(int) = Constant[1] : -# 579| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 -# 579| r0_58(unknown[2]) = Constant[0] : -# 579| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 -# 580| v0_60(void) = NoOp : -# 571| v0_61(void) = ReturnVoid : -# 571| v0_62(void) = UnmodeledUse : mu* -# 571| v0_63(void) = AliasedUse : ~mu0_2 -# 571| v0_64(void) = ExitFunction : +# 573| r0_13(glval) = StringConstant["foo"] : +# 573| r0_14(char[4]) = Load : &:r0_13, ~mu0_2 +# 573| mu0_15(char[4]) = Store : &:r0_12, r0_14 +# 574| r0_16(glval) = VariableAddress[a_infer] : +# 574| r0_17(glval) = StringConstant["blah"] : +# 574| r0_18(char[5]) = Load : &:r0_17, ~mu0_2 +# 574| mu0_19(char[5]) = Store : &:r0_16, r0_18 +# 575| r0_20(glval) = VariableAddress[b] : +# 575| mu0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 576| r0_22(glval) = VariableAddress[c] : +# 576| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 576| r0_24(int) = Constant[0] : +# 576| r0_25(glval) = PointerAdd[1] : r0_22, r0_24 +# 576| r0_26(unknown[2]) = Constant[0] : +# 576| mu0_27(unknown[2]) = Store : &:r0_25, r0_26 +# 577| r0_28(glval) = VariableAddress[d] : +# 577| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 577| r0_30(int) = Constant[0] : +# 577| r0_31(glval) = PointerAdd[1] : r0_28, r0_30 +# 577| r0_32(char) = Constant[0] : +# 577| mu0_33(char) = Store : &:r0_31, r0_32 +# 577| r0_34(int) = Constant[1] : +# 577| r0_35(glval) = PointerAdd[1] : r0_28, r0_34 +# 577| r0_36(char) = Constant[0] : +# 577| mu0_37(char) = Store : &:r0_35, r0_36 +# 578| r0_38(glval) = VariableAddress[e] : +# 578| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 578| r0_40(int) = Constant[0] : +# 578| r0_41(glval) = PointerAdd[1] : r0_38, r0_40 +# 578| r0_42(char) = Constant[0] : +# 578| mu0_43(char) = Store : &:r0_41, r0_42 +# 578| r0_44(int) = Constant[1] : +# 578| r0_45(glval) = PointerAdd[1] : r0_38, r0_44 +# 578| r0_46(char) = Constant[1] : +# 578| mu0_47(char) = Store : &:r0_45, r0_46 +# 579| r0_48(glval) = VariableAddress[f] : +# 579| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 579| r0_50(int) = Constant[0] : +# 579| r0_51(glval) = PointerAdd[1] : r0_48, r0_50 +# 579| r0_52(char) = Constant[0] : +# 579| mu0_53(char) = Store : &:r0_51, r0_52 +# 579| r0_54(int) = Constant[1] : +# 579| r0_55(glval) = PointerAdd[1] : r0_48, r0_54 +# 579| r0_56(unknown[2]) = Constant[0] : +# 579| mu0_57(unknown[2]) = Store : &:r0_55, r0_56 +# 580| v0_58(void) = NoOp : +# 571| v0_59(void) = ReturnVoid : +# 571| v0_60(void) = UnmodeledUse : mu* +# 571| v0_61(void) = AliasedUse : ~mu0_2 +# 571| v0_62(void) = ExitFunction : # 584| void VarArgs() # 584| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index bc2bea75e11..893f1a1dd19 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -887,61 +887,59 @@ ssa.cpp: # 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9 # 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12 # 215| r0_14(glval) = VariableAddress[a_nopad] : -# 215| m0_15(char[4]) = Uninitialized[a_nopad] : &:r0_14 -# 215| r0_16(glval) = StringConstant["foo"] : -# 215| r0_17(char[4]) = Load : &:r0_16, ~m0_1 -# 215| m0_18(char[4]) = Store : &:r0_14, r0_17 -# 216| r0_19(glval) = VariableAddress[a_infer] : -# 216| m0_20(char[5]) = Uninitialized[a_infer] : &:r0_19 -# 216| r0_21(glval) = StringConstant["blah"] : -# 216| r0_22(char[5]) = Load : &:r0_21, ~m0_1 -# 216| m0_23(char[5]) = Store : &:r0_19, r0_22 -# 217| r0_24(glval) = VariableAddress[b] : -# 217| m0_25(char[2]) = Uninitialized[b] : &:r0_24 -# 218| r0_26(glval) = VariableAddress[c] : -# 218| m0_27(char[2]) = Uninitialized[c] : &:r0_26 -# 218| r0_28(int) = Constant[0] : -# 218| r0_29(glval) = PointerAdd[1] : r0_26, r0_28 -# 218| r0_30(unknown[2]) = Constant[0] : -# 218| m0_31(unknown[2]) = Store : &:r0_29, r0_30 -# 219| r0_32(glval) = VariableAddress[d] : -# 219| m0_33(char[2]) = Uninitialized[d] : &:r0_32 -# 219| r0_34(int) = Constant[0] : -# 219| r0_35(glval) = PointerAdd[1] : r0_32, r0_34 -# 219| r0_36(char) = Constant[0] : -# 219| m0_37(char) = Store : &:r0_35, r0_36 -# 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 -# 219| r0_39(int) = Constant[1] : -# 219| r0_40(glval) = PointerAdd[1] : r0_32, r0_39 -# 219| r0_41(char) = Constant[0] : -# 219| m0_42(char) = Store : &:r0_40, r0_41 -# 219| m0_43(char[2]) = Chi : total:m0_38, partial:m0_42 -# 220| r0_44(glval) = VariableAddress[e] : -# 220| m0_45(char[2]) = Uninitialized[e] : &:r0_44 -# 220| r0_46(int) = Constant[0] : -# 220| r0_47(glval) = PointerAdd[1] : r0_44, r0_46 -# 220| r0_48(char) = Constant[0] : -# 220| m0_49(char) = Store : &:r0_47, r0_48 -# 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 -# 220| r0_51(int) = Constant[1] : -# 220| r0_52(glval) = PointerAdd[1] : r0_44, r0_51 -# 220| r0_53(char) = Constant[1] : -# 220| m0_54(char) = Store : &:r0_52, r0_53 -# 220| m0_55(char[2]) = Chi : total:m0_50, partial:m0_54 -# 221| r0_56(glval) = VariableAddress[f] : -# 221| m0_57(char[3]) = Uninitialized[f] : &:r0_56 -# 221| r0_58(int) = Constant[0] : -# 221| r0_59(glval) = PointerAdd[1] : r0_56, r0_58 -# 221| r0_60(char) = Constant[0] : -# 221| m0_61(char) = Store : &:r0_59, r0_60 -# 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 -# 221| r0_63(int) = Constant[1] : -# 221| r0_64(glval) = PointerAdd[1] : r0_56, r0_63 -# 221| r0_65(unknown[2]) = Constant[0] : -# 221| m0_66(unknown[2]) = Store : &:r0_64, r0_65 -# 221| m0_67(char[3]) = Chi : total:m0_62, partial:m0_66 -# 222| v0_68(void) = NoOp : -# 213| v0_69(void) = ReturnVoid : -# 213| v0_70(void) = UnmodeledUse : mu* -# 213| v0_71(void) = AliasedUse : ~m0_1 -# 213| v0_72(void) = ExitFunction : +# 215| r0_15(glval) = StringConstant["foo"] : +# 215| r0_16(char[4]) = Load : &:r0_15, ~m0_1 +# 215| m0_17(char[4]) = Store : &:r0_14, r0_16 +# 216| r0_18(glval) = VariableAddress[a_infer] : +# 216| r0_19(glval) = StringConstant["blah"] : +# 216| r0_20(char[5]) = Load : &:r0_19, ~m0_1 +# 216| m0_21(char[5]) = Store : &:r0_18, r0_20 +# 217| r0_22(glval) = VariableAddress[b] : +# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 218| r0_24(glval) = VariableAddress[c] : +# 218| m0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 218| r0_26(int) = Constant[0] : +# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 218| r0_28(unknown[2]) = Constant[0] : +# 218| m0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 219| r0_30(glval) = VariableAddress[d] : +# 219| m0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 219| r0_32(int) = Constant[0] : +# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 219| r0_34(char) = Constant[0] : +# 219| m0_35(char) = Store : &:r0_33, r0_34 +# 219| m0_36(char[2]) = Chi : total:m0_31, partial:m0_35 +# 219| r0_37(int) = Constant[1] : +# 219| r0_38(glval) = PointerAdd[1] : r0_30, r0_37 +# 219| r0_39(char) = Constant[0] : +# 219| m0_40(char) = Store : &:r0_38, r0_39 +# 219| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40 +# 220| r0_42(glval) = VariableAddress[e] : +# 220| m0_43(char[2]) = Uninitialized[e] : &:r0_42 +# 220| r0_44(int) = Constant[0] : +# 220| r0_45(glval) = PointerAdd[1] : r0_42, r0_44 +# 220| r0_46(char) = Constant[0] : +# 220| m0_47(char) = Store : &:r0_45, r0_46 +# 220| m0_48(char[2]) = Chi : total:m0_43, partial:m0_47 +# 220| r0_49(int) = Constant[1] : +# 220| r0_50(glval) = PointerAdd[1] : r0_42, r0_49 +# 220| r0_51(char) = Constant[1] : +# 220| m0_52(char) = Store : &:r0_50, r0_51 +# 220| m0_53(char[2]) = Chi : total:m0_48, partial:m0_52 +# 221| r0_54(glval) = VariableAddress[f] : +# 221| m0_55(char[3]) = Uninitialized[f] : &:r0_54 +# 221| r0_56(int) = Constant[0] : +# 221| r0_57(glval) = PointerAdd[1] : r0_54, r0_56 +# 221| r0_58(char) = Constant[0] : +# 221| m0_59(char) = Store : &:r0_57, r0_58 +# 221| m0_60(char[3]) = Chi : total:m0_55, partial:m0_59 +# 221| r0_61(int) = Constant[1] : +# 221| r0_62(glval) = PointerAdd[1] : r0_54, r0_61 +# 221| r0_63(unknown[2]) = Constant[0] : +# 221| m0_64(unknown[2]) = Store : &:r0_62, r0_63 +# 221| m0_65(char[3]) = Chi : total:m0_60, partial:m0_64 +# 222| v0_66(void) = NoOp : +# 213| v0_67(void) = ReturnVoid : +# 213| v0_68(void) = UnmodeledUse : mu* +# 213| v0_69(void) = AliasedUse : ~m0_1 +# 213| v0_70(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 93f27b13f02..0014e15c784 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -849,55 +849,53 @@ ssa.cpp: # 214| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 # 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 # 215| r0_12(glval) = VariableAddress[a_nopad] : -# 215| m0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 -# 215| r0_14(glval) = StringConstant["foo"] : -# 215| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 -# 215| m0_16(char[4]) = Store : &:r0_12, r0_15 -# 216| r0_17(glval) = VariableAddress[a_infer] : -# 216| m0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 -# 216| r0_19(glval) = StringConstant["blah"] : -# 216| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 -# 216| m0_21(char[5]) = Store : &:r0_17, r0_20 -# 217| r0_22(glval) = VariableAddress[b] : -# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 -# 218| r0_24(glval) = VariableAddress[c] : -# 218| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 -# 218| r0_26(int) = Constant[0] : -# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 -# 218| r0_28(unknown[2]) = Constant[0] : -# 218| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 -# 219| r0_30(glval) = VariableAddress[d] : -# 219| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 -# 219| r0_32(int) = Constant[0] : -# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 -# 219| r0_34(char) = Constant[0] : -# 219| mu0_35(char) = Store : &:r0_33, r0_34 -# 219| r0_36(int) = Constant[1] : -# 219| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 -# 219| r0_38(char) = Constant[0] : -# 219| mu0_39(char) = Store : &:r0_37, r0_38 -# 220| r0_40(glval) = VariableAddress[e] : -# 220| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 -# 220| r0_42(int) = Constant[0] : -# 220| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 -# 220| r0_44(char) = Constant[0] : -# 220| mu0_45(char) = Store : &:r0_43, r0_44 -# 220| r0_46(int) = Constant[1] : -# 220| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 -# 220| r0_48(char) = Constant[1] : -# 220| mu0_49(char) = Store : &:r0_47, r0_48 -# 221| r0_50(glval) = VariableAddress[f] : -# 221| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 -# 221| r0_52(int) = Constant[0] : -# 221| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 -# 221| r0_54(char) = Constant[0] : -# 221| mu0_55(char) = Store : &:r0_53, r0_54 -# 221| r0_56(int) = Constant[1] : -# 221| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 -# 221| r0_58(unknown[2]) = Constant[0] : -# 221| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 -# 222| v0_60(void) = NoOp : -# 213| v0_61(void) = ReturnVoid : -# 213| v0_62(void) = UnmodeledUse : mu* -# 213| v0_63(void) = AliasedUse : ~mu0_2 -# 213| v0_64(void) = ExitFunction : +# 215| r0_13(glval) = StringConstant["foo"] : +# 215| r0_14(char[4]) = Load : &:r0_13, ~mu0_2 +# 215| m0_15(char[4]) = Store : &:r0_12, r0_14 +# 216| r0_16(glval) = VariableAddress[a_infer] : +# 216| r0_17(glval) = StringConstant["blah"] : +# 216| r0_18(char[5]) = Load : &:r0_17, ~mu0_2 +# 216| m0_19(char[5]) = Store : &:r0_16, r0_18 +# 217| r0_20(glval) = VariableAddress[b] : +# 217| m0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 218| r0_22(glval) = VariableAddress[c] : +# 218| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 218| r0_24(int) = Constant[0] : +# 218| r0_25(glval) = PointerAdd[1] : r0_22, r0_24 +# 218| r0_26(unknown[2]) = Constant[0] : +# 218| mu0_27(unknown[2]) = Store : &:r0_25, r0_26 +# 219| r0_28(glval) = VariableAddress[d] : +# 219| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 219| r0_30(int) = Constant[0] : +# 219| r0_31(glval) = PointerAdd[1] : r0_28, r0_30 +# 219| r0_32(char) = Constant[0] : +# 219| mu0_33(char) = Store : &:r0_31, r0_32 +# 219| r0_34(int) = Constant[1] : +# 219| r0_35(glval) = PointerAdd[1] : r0_28, r0_34 +# 219| r0_36(char) = Constant[0] : +# 219| mu0_37(char) = Store : &:r0_35, r0_36 +# 220| r0_38(glval) = VariableAddress[e] : +# 220| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 220| r0_40(int) = Constant[0] : +# 220| r0_41(glval) = PointerAdd[1] : r0_38, r0_40 +# 220| r0_42(char) = Constant[0] : +# 220| mu0_43(char) = Store : &:r0_41, r0_42 +# 220| r0_44(int) = Constant[1] : +# 220| r0_45(glval) = PointerAdd[1] : r0_38, r0_44 +# 220| r0_46(char) = Constant[1] : +# 220| mu0_47(char) = Store : &:r0_45, r0_46 +# 221| r0_48(glval) = VariableAddress[f] : +# 221| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 221| r0_50(int) = Constant[0] : +# 221| r0_51(glval) = PointerAdd[1] : r0_48, r0_50 +# 221| r0_52(char) = Constant[0] : +# 221| mu0_53(char) = Store : &:r0_51, r0_52 +# 221| r0_54(int) = Constant[1] : +# 221| r0_55(glval) = PointerAdd[1] : r0_48, r0_54 +# 221| r0_56(unknown[2]) = Constant[0] : +# 221| mu0_57(unknown[2]) = Store : &:r0_55, r0_56 +# 222| v0_58(void) = NoOp : +# 213| v0_59(void) = ReturnVoid : +# 213| v0_60(void) = UnmodeledUse : mu* +# 213| v0_61(void) = AliasedUse : ~mu0_2 +# 213| v0_62(void) = ExitFunction : From 4ea8569081e003e4fb274c3d03e709ea7ba86fe4 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 7 Nov 2019 16:40:03 -0800 Subject: [PATCH 196/232] [CPP-434] Squelch query alerts if ALL files were compiled with `-fwrapv` or `-fno-strict-overflow` --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index bd79a114172..648846a7dc1 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -23,5 +23,9 @@ where globalValueNumber(expr1) = globalValueNumber(expr2) and add.getUnspecifiedType().(IntegralType).isSigned() and not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and - exprMightOverflowPositively(add) + exprMightOverflowPositively(add) and + exists(Compilation c | c.getAFileCompiled() = ro.getFile() | + not c.getAnArgument() = "-fwrapv" and + not c.getAnArgument() = "-fno-strict-overflow" + ) select ro, "Testing for signed overflow may produce undefined results." From 17f76c251679acdb09ff7dc30ccc71aa6c2aa7c2 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Thu, 7 Nov 2019 22:02:15 -0700 Subject: [PATCH 197/232] C++: Fix merge conflicts --- .../ir/ssa/aliased_ssa_ir.expected | 26 +++++++++++++++++++ .../ir/ssa/unaliased_ssa_ir.expected | 25 ++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 46f8cf19aea..f306d3e14c2 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -877,3 +877,29 @@ ssa.cpp: # 207| v0_27(void) = UnmodeledUse : mu* # 207| v0_28(void) = AliasedUse : ~m0_1 # 207| v0_29(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| m0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| m0_5(unknown) = ^CallSideEffect : ~m0_1 +# 216| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 +# 218| r0_7(glval) = VariableAddress[s] : +# 218| r0_8(glval) = StringConstant["Literal"] : +# 218| r0_9(char *) = Convert : r0_8 +# 218| m0_10(char *) = Store : &:r0_7, r0_9 +# 219| r0_11(glval) = VariableAddress[#return] : +# 219| r0_12(glval) = VariableAddress[s] : +# 219| r0_13(char *) = Load : &:r0_12, m0_10 +# 219| r0_14(int) = Constant[2] : +# 219| r0_15(glval) = PointerAdd[1] : r0_13, r0_14 +# 219| r0_16(char) = Load : &:r0_15, ~m0_1 +# 219| m0_17(char) = Store : &:r0_11, r0_16 +# 215| r0_18(glval) = VariableAddress[#return] : +# 215| v0_19(void) = ReturnValue : &:r0_18, m0_17 +# 215| v0_20(void) = UnmodeledUse : mu* +# 215| v0_21(void) = AliasedUse : ~m0_6 +# 215| v0_22(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 7aae6b70dfd..48d698a1291 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -841,3 +841,28 @@ ssa.cpp: # 207| v0_24(void) = UnmodeledUse : mu* # 207| v0_25(void) = AliasedUse : ~mu0_2 # 207| v0_26(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| mu0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| mu0_5(unknown) = ^CallSideEffect : ~mu0_2 +# 218| r0_6(glval) = VariableAddress[s] : +# 218| r0_7(glval) = StringConstant["Literal"] : +# 218| r0_8(char *) = Convert : r0_7 +# 218| m0_9(char *) = Store : &:r0_6, r0_8 +# 219| r0_10(glval) = VariableAddress[#return] : +# 219| r0_11(glval) = VariableAddress[s] : +# 219| r0_12(char *) = Load : &:r0_11, m0_9 +# 219| r0_13(int) = Constant[2] : +# 219| r0_14(glval) = PointerAdd[1] : r0_12, r0_13 +# 219| r0_15(char) = Load : &:r0_14, ~mu0_2 +# 219| m0_16(char) = Store : &:r0_10, r0_15 +# 215| r0_17(glval) = VariableAddress[#return] : +# 215| v0_18(void) = ReturnValue : &:r0_17, m0_16 +# 215| v0_19(void) = UnmodeledUse : mu* +# 215| v0_20(void) = AliasedUse : ~mu0_2 +# 215| v0_21(void) = ExitFunction : From e8510fe71a3c4fc1eab65e9a1f6095213dacb3b2 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Fri, 8 Nov 2019 09:17:05 +0000 Subject: [PATCH 198/232] TypeScript: Skip Touchstone files. --- .../semmle/js/extractor/FileExtractor.java | 28 +++++++++++++------ .../tests/ts/input/touchstone-file.ts | 2 ++ .../tests/ts/input/touchstone-file2.ts | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 javascript/extractor/tests/ts/input/touchstone-file.ts create mode 100644 javascript/extractor/tests/ts/input/touchstone-file2.ts diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index d80ddeaf303..278a7ec2e63 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -1,5 +1,16 @@ package com.semmle.js.extractor; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.regex.Pattern; + import com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase; import com.semmle.js.extractor.trapcache.CachingTrapWriter; import com.semmle.js.extractor.trapcache.ITrapCache; @@ -10,15 +21,6 @@ import com.semmle.util.files.FileUtil; import com.semmle.util.io.WholeIO; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Pattern; /** * The file extractor extracts a single file and handles source archive population and TRAP caching; @@ -167,6 +169,9 @@ public class FileExtractor { return true; } + // Avoid Touchstone files + if (isTouchstone(bytes, length)) return true; + return false; } catch (IOException e) { Exceptions.ignore(e, "Let extractor handle this one."); @@ -198,6 +203,11 @@ public class FileExtractor { return false; } + private boolean isTouchstone(byte[] bytes, int length) { + String s = new String(bytes, 0, length, StandardCharsets.US_ASCII); + return s.startsWith("! TOUCHSTONE file ") || s.startsWith("[Version] 2.0"); + } + /** * Returns true if the byte sequence contains invalid UTF-8 or unprintable ASCII characters. */ diff --git a/javascript/extractor/tests/ts/input/touchstone-file.ts b/javascript/extractor/tests/ts/input/touchstone-file.ts new file mode 100644 index 00000000000..a72a1dc56af --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file.ts @@ -0,0 +1,2 @@ +! TOUCHSTONE file generated by me +[Version] 2.0 diff --git a/javascript/extractor/tests/ts/input/touchstone-file2.ts b/javascript/extractor/tests/ts/input/touchstone-file2.ts new file mode 100644 index 00000000000..d642e0260b1 --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file2.ts @@ -0,0 +1 @@ +[Version] 2.0 From 0554de06a13b5ded396d693a8f218f310587f790 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 8 Nov 2019 09:32:20 +0000 Subject: [PATCH 199/232] docs: update banner links --- docs/language/global-sphinx-files/_templates/layout.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index de3b189e1ee..000503e5798 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -62,8 +62,8 @@