diff --git a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql index 1e03c089e8..afa664448a 100644 --- a/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql +++ b/c/cert/src/rules/CON30-C/CleanUpThreadSpecificStorage.ql @@ -19,8 +19,8 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.ConcurrencyNew +import semmle.code.cpp.dataflow.new.DataFlow module TssCreateToTssDeleteConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { diff --git a/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql b/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql index c9bcaa6bd2..dadb21985e 100644 --- a/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql +++ b/c/cert/src/rules/CON33-C/RaceConditionsWhenUsingLibraryFunctions.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from ThreadedCFN node where diff --git a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql index 4fb034406b..10cdec5c73 100644 --- a/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql +++ b/c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql @@ -20,8 +20,8 @@ import cpp import codingstandards.c.cert import codingstandards.c.Objects -import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.ConcurrencyNew +import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.commons.Alloc from C11ThreadCreateCall tcc, Expr arg @@ -53,6 +53,7 @@ where not exists(TSSSetFunctionCall tss, DataFlow::Node src | // there should be dataflow from somewhere (the same somewhere) // into each of the first arguments + exists(Expr e | e = src.asDefinition() or e = src.asDefiningArgument()) and DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0))) ) diff --git a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql index 07b114d6ca..40acc1e3ea 100644 --- a/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql +++ b/c/cert/src/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.ql @@ -20,8 +20,8 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency -import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.ConcurrencyNew +import semmle.code.cpp.dataflow.new.DataFlow from TSSGetFunctionCall tsg, ThreadedFunction tf where @@ -31,7 +31,8 @@ where // however, there does not exist a proper sequencing. not exists(TSSSetFunctionCall tss, DataFlow::Node src | // there should be dataflow from somewhere (the same somewhere) - // into each of the first arguments + // into each of the first argument + exists(Expr e | e = src.asDefinition() or e = src.asDefiningArgument()) and DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0))) ) diff --git a/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql b/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql index 17691f24dd..72fe5b5923 100644 --- a/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql +++ b/c/cert/src/rules/CON37-C/DoNotCallSignalInMultithreadedProgram.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from FunctionCall fc // This should only be applied in the context of a multi-threaded program (since diff --git a/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql b/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql index 0ec195868f..cc85cd9d1c 100644 --- a/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql +++ b/c/cert/src/rules/CON40-C/AtomicVariableTwiceInExpression.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from MacroInvocation mi, Variable v, Locatable whereFound where diff --git a/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql b/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql index 57be1bc488..d7754973fe 100644 --- a/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql +++ b/c/cert/src/rules/CON41-C/WrapFunctionsThatCanFailSpuriouslyInLoop.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.c.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from AtomicCompareExchange ace where diff --git a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql index ad3a2c8192..d9b96d3c86 100644 --- a/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql +++ b/c/cert/src/rules/FIO37-C/SuccessfulFgetsOrFgetwsMayReturnAnEmptyString.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.c.cert import codingstandards.cpp.FgetsErrorManagement import codingstandards.cpp.Dereferenced -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow /* * CFG nodes that follows a successful call to `fgets` diff --git a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected index f3ea87136a..e03b665a1c 100644 --- a/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected +++ b/c/cert/test/rules/CON30-C/CleanUpThreadSpecificStorage.expected @@ -1,9 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:25,46-54) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:26,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:35,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:45,35-43) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:53,36-44) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (CleanUpThreadSpecificStorage.ql:55,36-44) | test.c:27:3:27:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:49:3:49:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | | test.c:71:3:71:12 | call to tss_create | Resources used by thread specific storage may not be cleaned up. | diff --git a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected index 2cd844f81b..c3cdc8bd7b 100644 --- a/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected +++ b/c/cert/test/rules/CON34-C/AppropriateThreadObjectStorageDurations.expected @@ -1,16 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:35,14-22) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:37,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:39,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:42,45-53) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,33-41) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,58-66) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:53,42-50) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:56,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:56,34-42) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:57,9-17) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:57,34-42) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:42,9-22) -WARNING: module 'TaintTracking' has been deprecated and may be removed in future (AppropriateThreadObjectStorageDurations.ql:52,7-20) | test.c:23:3:23:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:23:24:23:29 | & ... | Shared object | | test.c:74:3:74:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:74:24:74:24 | p | Shared object | | test.c:85:3:85:13 | call to thrd_create | $@ not declared with appropriate storage duration | test.c:85:24:85:24 | p | Shared object | diff --git a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected index b2ac853fbf..95d0a20041 100644 --- a/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected +++ b/c/cert/test/rules/CON34-C/ThreadObjectStorageDurationsNotInitialized.expected @@ -1,6 +1 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:32,38-46) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:35,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:35,30-38) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:36,5-13) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ThreadObjectStorageDurationsNotInitialized.ql:36,30-38) | test.c:14:7:14:13 | call to tss_get | Call to a thread specific storage function from within a threaded context on an object that may not be owned by this thread. | diff --git a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected index 7d3cbe355b..20c108cfa0 100644 --- a/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected +++ b/c/cert/test/rules/FIO40-C/ResetStringsOnFgetsOrFgetwsFailure.expected @@ -1,6 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,11-19) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:47,31-39) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (ResetStringsOnFgetsOrFgetwsFailure.ql:48,13-21) | test.c:20:10:20:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:15:7:15:11 | call to fgets | call to fgets | | test.c:57:10:57:12 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:52:7:52:11 | call to fgets | call to fgets | | test.c:66:18:66:20 | buf | The buffer is not reset before being referenced following a failed $@. | test.c:61:7:61:11 | call to fgets | call to fgets | diff --git a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll index 2906883ae9..cf32f9bdc6 100644 --- a/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll +++ b/c/common/src/codingstandards/c/initialization/GlobalInitializationAnalysis.qll @@ -1,6 +1,6 @@ import cpp import codingstandards.c.Objects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type signature module GlobalInitializationAnalysisConfigSig { diff --git a/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected b/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected index 75866b8503..f9fe72c2a4 100644 --- a/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected +++ b/c/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected @@ -4,19 +4,27 @@ problems | test.c:13:10:13:11 | p4 | test.c:5:14:5:15 | l2 | test.c:13:10:13:11 | p4 | Subtraction between left operand pointing to array $@ and other operand pointing to array $@. | test.c:3:7:3:8 | l2 | l2 | test.c:2:7:2:8 | l1 | l1 | | test.c:13:15:13:16 | l1 | test.c:13:15:13:16 | l1 | test.c:13:15:13:16 | l1 | Subtraction between right operand pointing to array $@ and other operand pointing to array $@. | test.c:2:7:2:8 | l1 | l1 | test.c:3:7:3:8 | l2 | l2 | edges -| test.c:4:14:4:15 | l1 | test.c:4:14:4:18 | access to array | provenance | Config | -| test.c:4:14:4:18 | access to array | test.c:10:10:10:11 | p1 | provenance | | -| test.c:4:14:4:18 | access to array | test.c:12:10:12:11 | p1 | provenance | | -| test.c:5:14:5:15 | l2 | test.c:5:14:5:19 | access to array | provenance | Config | -| test.c:5:14:5:19 | access to array | test.c:11:10:11:11 | p2 | provenance | | -| test.c:5:14:5:19 | access to array | test.c:12:15:12:16 | p2 | provenance | | -| test.c:5:14:5:19 | access to array | test.c:13:10:13:11 | p4 | provenance | | -| test.c:5:14:5:19 | access to array | test.c:14:10:14:11 | p4 | provenance | | +| test.c:4:13:4:18 | & ... | test.c:4:13:4:18 | & ... | provenance | | +| test.c:4:13:4:18 | & ... | test.c:10:10:10:11 | p1 | provenance | | +| test.c:4:13:4:18 | & ... | test.c:12:10:12:11 | p1 | provenance | | +| test.c:4:14:4:15 | l1 | test.c:4:13:4:18 | & ... | provenance | Config | +| test.c:5:13:5:19 | & ... | test.c:5:13:5:19 | & ... | provenance | | +| test.c:5:13:5:19 | & ... | test.c:6:13:6:14 | p2 | provenance | | +| test.c:5:13:5:19 | & ... | test.c:11:10:11:11 | p2 | provenance | | +| test.c:5:13:5:19 | & ... | test.c:12:15:12:16 | p2 | provenance | | +| test.c:5:14:5:15 | l2 | test.c:5:13:5:19 | & ... | provenance | Config | +| test.c:6:13:6:14 | p2 | test.c:7:13:7:14 | p3 | provenance | | +| test.c:7:13:7:14 | p3 | test.c:13:10:13:11 | p4 | provenance | | +| test.c:7:13:7:14 | p3 | test.c:14:10:14:11 | p4 | provenance | | nodes +| test.c:4:13:4:18 | & ... | semmle.label | & ... | +| test.c:4:13:4:18 | & ... | semmle.label | & ... | | test.c:4:14:4:15 | l1 | semmle.label | l1 | -| test.c:4:14:4:18 | access to array | semmle.label | access to array | +| test.c:5:13:5:19 | & ... | semmle.label | & ... | +| test.c:5:13:5:19 | & ... | semmle.label | & ... | | test.c:5:14:5:15 | l2 | semmle.label | l2 | -| test.c:5:14:5:19 | access to array | semmle.label | access to array | +| test.c:6:13:6:14 | p2 | semmle.label | p2 | +| test.c:7:13:7:14 | p3 | semmle.label | p3 | | test.c:10:10:10:11 | p1 | semmle.label | p1 | | test.c:10:15:10:16 | l1 | semmle.label | l1 | | test.c:11:10:11:11 | p2 | semmle.label | p2 | diff --git a/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql index edf3705a9b..768a2b1ae2 100644 --- a/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql +++ b/c/misra/src/rules/DIR-5-1/PossibleDataRaceBetweenThreads.ql @@ -17,7 +17,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.Objects import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew newtype TNonReentrantOperation = TReadWrite(SubObject object) { diff --git a/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql b/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql index 4bb526306b..cb12a8156b 100644 --- a/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql +++ b/c/misra/src/rules/DIR-5-3/BannedDynamicThreadCreation.ql @@ -18,7 +18,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from CThreadCreateCall tc, Function enclosingFunction where diff --git a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql index 207e763fa7..11f76de7ae 100644 --- a/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql +++ b/c/misra/src/rules/DIR-5-3/ThreadCreatedByThread.ql @@ -17,7 +17,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew class CThreadRoot extends Function { CThreadCreateCall threadCreate; diff --git a/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql b/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql index 6a520447d1..a8fea9558e 100644 --- a/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql +++ b/c/misra/src/rules/RULE-18-6/ThreadLocalObjectAddressCopiedToGlobalObject.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.Objects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from AssignExpr assignment, Element threadLocal, ObjectIdentity static where diff --git a/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql b/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql index d92b4ccea6..15a437e7ed 100644 --- a/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql +++ b/c/misra/src/rules/RULE-22-12/NonstandardUseOfThreadingObject.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type predicate isThreadingObject(Type t) { t instanceof PossiblySpecified::Type } diff --git a/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql b/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql index 066cf3c295..18f3671202 100644 --- a/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql +++ b/c/misra/src/rules/RULE-22-13/ThreadingObjectWithInvalidStorageDuration.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.Objects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type from ObjectIdentity obj, StorageDuration storageDuration, Type type diff --git a/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql b/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql index a122a0bec4..cda50fbf73 100644 --- a/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql +++ b/c/misra/src/rules/RULE-22-14/MutexInitWithInvalidMutexType.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew predicate isBaseMutexType(EnumConstantAccess access) { access.getTarget().hasName(["mtx_plain", "mtx_timed"]) diff --git a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql index 497fdaf14d..4b6afe9f5f 100644 --- a/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql +++ b/c/misra/src/rules/RULE-22-14/MutexInitializedInsideThread.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from C11MutexSource mutexCreate, ThreadedFunction thread where diff --git a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql index f78c25f981..7df3a2dc4d 100644 --- a/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql +++ b/c/misra/src/rules/RULE-22-14/MutexNotInitializedBeforeUse.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.Objects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type import codingstandards.c.initialization.GlobalInitializationAnalysis diff --git a/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql index ec4631ef1b..9f06f441d1 100644 --- a/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql +++ b/c/misra/src/rules/RULE-22-15/ThreadResourceDisposedBeforeThreadsJoined.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew newtype TThreadKind = TSpawned(C11ThreadCreateCall tcc) or diff --git a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql index 252b4a7d9f..f2bb0a519c 100644 --- a/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql +++ b/c/misra/src/rules/RULE-22-17/InvalidOperationOnUnlockedMutex.ql @@ -16,9 +16,8 @@ import cpp import codingstandards.c.misra import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.dominance.BehavioralSet -import semmle.code.cpp.dataflow.new.DataFlow::DataFlow as NewDF /* A call to mtx_unlock() or cnd_wait() or cnd_timedwait(), which require a locked mutex */ class RequiresLockOperation extends FunctionCall { diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql index 17762b3eee..c1ace4489b 100644 --- a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLocked.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type from diff --git a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql index 7e002585b6..1df7c03825 100644 --- a/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql +++ b/c/misra/src/rules/RULE-22-18/NonRecursiveMutexRecursivelyLockedAudit.ql @@ -18,7 +18,7 @@ import cpp import codeql.util.Boolean import codingstandards.c.misra import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type predicate isTrackableMutex(CMutexFunctionCall lockCall, Boolean recursive) { diff --git a/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql index 0d5aa5399f..ce05c2dc74 100644 --- a/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql +++ b/c/misra/src/rules/RULE-22-19/ConditionVariableUsedWithMultipleMutexes.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.SubObjects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew bindingset[cond, mutex] int countMutexesForConditionVariable(SubObject cond, SubObject mutex) { diff --git a/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql index 1edf4aa9c3..9a9d924247 100644 --- a/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql +++ b/c/misra/src/rules/RULE-22-20/ThreadStorageNotInitializedBeforeUse.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra import codingstandards.c.Objects -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import codingstandards.cpp.Type import codingstandards.c.initialization.GlobalInitializationAnalysis diff --git a/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql b/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql index 3c40ea7116..4b7c64d914 100644 --- a/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql +++ b/c/misra/src/rules/RULE-22-20/ThreadStoragePointerInitializedInsideThread.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.c.misra -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from TSSCreateFunctionCall tssCreate, ThreadedFunction thread where diff --git a/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql b/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql index 642813bbab..581439c629 100644 --- a/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql +++ b/c/misra/src/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.standardlibrary.FileAccess -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.controlflow.SubBasicBlocks diff --git a/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql b/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql index 2439d4ca47..2468caa61e 100644 --- a/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql +++ b/c/misra/src/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.ql @@ -14,7 +14,7 @@ import cpp import codingstandards.c.misra import codingstandards.cpp.standardlibrary.FileAccess -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow module FileDFConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { diff --git a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected index 0365f4980d..6111072ba8 100644 --- a/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected +++ b/c/misra/test/rules/RULE-22-3/FileOpenForReadAndWriteOnDifferentStreams.expected @@ -1,4 +1,3 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (FileOpenForReadAndWriteOnDifferentStreams.ql:39,9-17) | test.c:6:14:6:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:5:14:5:18 | call to fopen | here | | test.c:17:14:17:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:16:14:16:18 | call to fopen | here | | test.c:33:14:33:18 | call to fopen | The same file was already opened $@. Files should not be read and written at the same time using different streams. | test.c:32:14:32:18 | call to fopen | here | diff --git a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected index dbf08e3d3d..0bfce133c5 100644 --- a/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected +++ b/c/misra/test/rules/RULE-22-4/AttemptToWriteToAReadOnlyStream.expected @@ -1,8 +1,2 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:19,32-40) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:20,22-30) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:25,20-28) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:31,21-29) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:33,6-14) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (AttemptToWriteToAReadOnlyStream.ql:36,28-36) | test.c:10:3:10:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:9:14:9:18 | call to fopen | stream | | test.c:15:3:15:9 | call to fprintf | Attempt to write to a $@ opened as read-only. | test.c:18:14:18:18 | call to fopen | stream | diff --git a/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql b/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql index c36bda6cdd..6b94c68cff 100644 --- a/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql +++ b/cpp/autosar/src/rules/A7-5-1/InvalidFunctionReturnType.ql @@ -16,7 +16,7 @@ import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow from Parameter p, ReturnStmt ret where diff --git a/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql b/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql index d6d4f6130a..29feaa22d5 100644 --- a/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql +++ b/cpp/autosar/src/rules/M5-0-17/PointerSubtractionOnDifferentArrays.ql @@ -15,7 +15,7 @@ import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import ArrayToPointerDiffOperandFlow::PathGraph module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { @@ -34,6 +34,8 @@ module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { // Add a flow step from the base to the array expression to track pointers to elements of the array. exists(ArrayExpr e | e.getArrayBase() = pred.asExpr() and e = succ.asExpr()) } + + predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } module ArrayToPointerDiffOperandFlow = DataFlow::Global; diff --git a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected index 3287ba88d1..b6d9490803 100644 --- a/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected +++ b/cpp/autosar/test/rules/A7-5-1/InvalidFunctionReturnType.expected @@ -1,5 +1,2 @@ -WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,3-11) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,23-31) -WARNING: module 'DataFlow' has been deprecated and may be removed in future (InvalidFunctionReturnType.ql:27,51-59) | test.cpp:5:3:5:11 | return ... | Function test_refconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:4:44:4:44 | x | parameter | | test.cpp:8:3:8:14 | return ... | Function test_ptrconst_return returns a reference or a pointer to $@ that is passed by reference to const. | test.cpp:7:44:7:44 | x | parameter | diff --git a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql index 67edf2fc22..a462e60edb 100644 --- a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql +++ b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from LockProtectedControlFlowNode n where diff --git a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql index 09ec2fa3d5..99ad966efa 100644 --- a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql +++ b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit.ql @@ -19,7 +19,7 @@ import cpp import codingstandards.cpp.cert -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew from LockProtectedControlFlowNode n where diff --git a/cpp/common/src/codingstandards/cpp/ConcurrencyNew.qll b/cpp/common/src/codingstandards/cpp/ConcurrencyNew.qll new file mode 100644 index 0000000000..37aea01889 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/ConcurrencyNew.qll @@ -0,0 +1,15 @@ +import cpp +import semmle.code.cpp.dataflow.new.TaintTracking +import codingstandards.cpp.concurrency.Atomic +import codingstandards.cpp.concurrency.CConditionOperation +import codingstandards.cpp.concurrency.ControlFlow +import codingstandards.cpp.concurrency.ConditionalWait +import codingstandards.cpp.concurrency.LockingOperationNew +import codingstandards.cpp.concurrency.LockProtectedControlFlow +import codingstandards.cpp.concurrency.MutexDestroyer +import codingstandards.cpp.concurrency.ThreadCreation +import codingstandards.cpp.concurrency.ThreadedFunction +import codingstandards.cpp.concurrency.ThreadDependentMutexNew +import codingstandards.cpp.concurrency.ThreadSpecificStorageNew +import codingstandards.cpp.concurrency.ThreadWaitDetach +import codingstandards.cpp.concurrency.Types diff --git a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll index 4f99b02e2e..7342b92f32 100644 --- a/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll +++ b/cpp/common/src/codingstandards/cpp/FgetsErrorManagement.qll @@ -4,7 +4,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import semmle.code.cpp.controlflow.Guards /* diff --git a/cpp/common/src/codingstandards/cpp/concurrency/LockingOperationNew.qll b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperationNew.qll new file mode 100644 index 0000000000..114b569204 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/LockingOperationNew.qll @@ -0,0 +1,235 @@ +import cpp +import semmle.code.cpp.dataflow.new.TaintTracking + +abstract class LockingOperation extends FunctionCall { + /** + * Returns the target of the lock underlying this RAII-style lock. + */ + abstract Variable getLock(); + + /** + * Returns the lock underlying this RAII-style lock. + */ + abstract Expr getLockExpr(); + + /** + * Holds if this is a lock operation + */ + abstract predicate isLock(); + + /** + * Holds if this is an unlock operation + */ + abstract predicate isUnlock(); + + /** + * Holds if this locking operation is really a locking operation within a + * designated locking operation. This library assumes the underlying locking + * operations are implemented correctly in that calling a `LockingOperation` + * results in the creation of a singular lock. + */ + predicate isLockingOperationWithinLockingOperation(LockingOperation inner) { + exists(LockingOperation outer | outer.getTarget() = inner.getEnclosingFunction()) + } +} + +/** + * Common base class providing an interface into function call + * based mutex locks. + */ +abstract class MutexFunctionCall extends LockingOperation { + abstract predicate isRecursive(); + + abstract predicate isSpeculativeLock(); + + abstract predicate unlocks(MutexFunctionCall fc); +} + +/** + * Models calls to various mutex types found in CPP. + */ +class CPPMutexFunctionCall extends MutexFunctionCall { + VariableAccess var; + + CPPMutexFunctionCall() { + getTarget() + .(MemberFunction) + .getDeclaringType() + .hasQualifiedName("std", + ["mutex", "timed_mutex", "shared_timed_mutex", "recursive_mutex", "recursive_timed_mutex"]) and + var = getQualifier() + } + + /** + * Holds if this mutex is a recursive mutex. + */ + override predicate isRecursive() { + getTarget() + .(MemberFunction) + .getDeclaringType() + .hasQualifiedName("std", ["recursive_mutex", "recursive_timed_mutex"]) + } + + /** + * Holds if this `CPPMutexFunctionCall` is a lock. + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + getTarget().getName() = "lock" + } + + /** + * Holds if this `CPPMutexFunctionCall` is a speculative lock, defined as calling + * one of the speculative locking functions such as `try_lock`. + */ + override predicate isSpeculativeLock() { + getTarget().getName() in [ + "try_lock", "try_lock_for", "try_lock_until", "try_lock_shared_for", "try_lock_shared_until" + ] + } + + /** + * Returns the lock to which this `CPPMutexFunctionCall` refers to. + */ + override Variable getLock() { result = getQualifier().(VariableAccess).getTarget() } + + /** + * Returns the qualifier for this `CPPMutexFunctionCall`. + */ + override Expr getLockExpr() { result = var } + + /** + * Holds if this is a `unlock` and *may* unlock the previously locked `MutexFunctionCall`. + * This predicate does not check that the mutex is currently locked. + */ + override predicate unlocks(MutexFunctionCall fc) { + isUnlock() and + fc.getQualifier().(VariableAccess).getTarget() = getQualifier().(VariableAccess).getTarget() + } + + /** + * Holds if this is an unlock call. + */ + override predicate isUnlock() { getTarget().getName() = "unlock" } +} + +/** + * Models calls to various mutex types specialized to C code. + */ +class CMutexFunctionCall extends MutexFunctionCall { + Expr arg; + + CMutexFunctionCall() { + // the non recursive kinds + getTarget().getName() = ["mtx_lock", "mtx_unlock", "mtx_timedlock", "mtx_trylock"] and + arg = getArgument(0) + } + + /** + * Holds if this mutex is a recursive mutex. + */ + override predicate isRecursive() { none() } + + /** + * Holds if this `CMutexFunctionCall` is a lock. + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + getTarget().getName() = ["mtx_lock", "mtx_timedlock", "mtx_trylock"] + } + + /** + * Holds if this `CMutexFunctionCall` is a speculative lock, defined as calling + * one of the speculative locking functions such as `try_lock`. + */ + override predicate isSpeculativeLock() { + getTarget().getName() in ["mtx_timedlock", "mtx_trylock"] + } + + /** + * Returns the `Variable` to which this `CMutexFunctionCall` refers to. For this + * style of lock it can reference a number of different variables. + */ + override Variable getLock() { + exists(VariableAccess va | + TaintTracking::localTaint(DataFlow::exprNode(va), DataFlow::exprNode(getLockExpr())) and + result = va.getTarget() + ) + } + + /** + * Returns the expression for this `CMutexFunctionCall`. + */ + override Expr getLockExpr() { result = arg } + + /** + * Holds if this is a `unlock` and *may* unlock the previously locked `CMutexFunctionCall`. + * This predicate does not check that the mutex is currently locked. + */ + override predicate unlocks(MutexFunctionCall fc) { + isUnlock() and + fc.getLock() = getLock() + } + + /** + * Holds if this is an unlock call. + */ + override predicate isUnlock() { getTarget().getName() = "mtx_unlock" } +} + +/** + * Models a RAII-Style lock. + */ +class RAIIStyleLock extends LockingOperation { + VariableAccess lock; + + RAIIStyleLock() { + ( + getTarget().getDeclaringType().hasQualifiedName("std", "lock_guard") or + getTarget().getDeclaringType().hasQualifiedName("std", "unique_lock") or + getTarget().getDeclaringType().hasQualifiedName("std", "scoped_lock") + ) and + ( + lock = getArgument(0).getAChild*() + or + this instanceof DestructorCall and + exists(RAIIStyleLock constructor | + constructor = getQualifier().(VariableAccess).getTarget().getInitializer().getExpr() and + lock = constructor.getArgument(0).getAChild*() + ) + ) + } + + /** + * Holds if this is a lock operation + */ + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + this instanceof ConstructorCall and + lock = getArgument(0).getAChild*() and + // defer_locks don't cause a lock + not exists(Expr exp | + exp = getArgument(1) and + exp.(VariableAccess) + .getTarget() + .getUnderlyingType() + .(Class) + .hasQualifiedName("std", "defer_lock_t") + ) + } + + /** + * Holds if this is an unlock operation + */ + override predicate isUnlock() { this instanceof DestructorCall } + + /** + * Returns the target of the lock underlying this RAII-style lock. + */ + override Variable getLock() { result = lock.getTarget() } + + /** + * Returns the lock underlying this RAII-style lock. + */ + override Expr getLockExpr() { result = lock } +} diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutexNew.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutexNew.qll new file mode 100644 index 0000000000..c761e2b1be --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadDependentMutexNew.qll @@ -0,0 +1,246 @@ +import cpp +import semmle.code.cpp.dataflow.new.TaintTracking +private import codingstandards.cpp.concurrency.ControlFlow +private import codingstandards.cpp.concurrency.ThreadedFunction + +abstract class MutexSource extends FunctionCall { } + +/** + * Models a C++ style mutex. + */ +class CPPMutexSource extends MutexSource, ConstructorCall { + CPPMutexSource() { getTarget().getDeclaringType().hasQualifiedName("std", "mutex") } +} + +/** + * Models a C11 style mutex. + */ +class C11MutexSource extends MutexSource, FunctionCall { + C11MutexSource() { getTarget().hasName("mtx_init") } + + Expr getMutexExpr() { result = getArgument(0) } + + Expr getMutexTypeExpr() { result = getArgument(1) } + + predicate isRecursive() { + exists(EnumConstantAccess recursive | + recursive = getMutexTypeExpr().getAChild*() and + recursive.getTarget().hasName("mtx_recursive") + ) + } +} + +/** + * Models a thread dependent mutex. A thread dependent mutex is a mutex + * that is used by a thread. This dependency is established either by directly + * passing in a mutex or by referencing a mutex that is in the local scope. The utility + * of this class is it captures the `DataFlow::Node` source at which the mutex + * came from. For example, if it is passed in from a local function to a thread. + * This functionality is critical, since it allows one to inspect how the thread + * behaves with respect to the owner of a resource. + * + * To model the myriad ways this can happen, the subclasses of this class are + * responsible for implementing the various usage patterns. + */ +abstract class ThreadDependentMutex extends DataFlow::Node { + DataFlow::Node sink; + + DataFlow::Node getASource() { + // the source is either the thing that declared + // the mutex + result = this + or + // or the thread we are using it in + result = getAThreadSource() + } + + /** + * Gets the dataflow nodes corresponding to thread local usages of the + * dependent mutex. + */ + DataFlow::Node getAThreadSource() { + // here we line up the actual parameter at the thread creation + // site with the formal parameter in the target thread. + // Note that there are differences between the C and C++ versions + // of the argument ordering in the thread creation function. However, + // since the C version only takes one parameter (as opposed to multiple) + // we can simplify this search by considering only the first argument. + exists(FunctionCall fc, Function f, int n | + // Get the argument to which the mutex flowed. + fc.getArgument(n) = sink.asExpr() and + // Get the thread function we are calling. + f = fc.getArgument(0).(FunctionAccess).getTarget() and + // in C++, there is an extra argument to the `std::thread` call + // so we must subtract 1 since this is not passed to the thread. + ( + result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) + or + // In C, only one argument is allowed. Thus IF the flow predicate holds, + // it will be to the first argument + result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) + ) + ) + } + + /** + * Produces the set of dataflow nodes to thread creation for threads + * that are dependent on this mutex. + */ + DataFlow::Node getADependentThreadCreationExpr() { + exists(FunctionCall fc | + fc.getAnArgument() = sink.asExpr() and + result = DataFlow::exprNode(fc) + ) + } + + /** + * Gets a set of usages of this mutex in both the local and thread scope. + * In the case of scoped usage, this also captures typical accesses of variables. + */ + DataFlow::Node getAUsage() { TaintTracking::localTaint(getASource(), result) } +} + +/** + * This class models the type of thread/mutex dependency that is established + * through the typical parameter passing mechanisms found in C++. + */ +class FlowBasedThreadDependentMutex extends ThreadDependentMutex { + FlowBasedThreadDependentMutex() { + // some sort of dataflow, likely through parameter passing. + ThreadDependentMutexFlow::flow(this, sink) + } +} + +/** + * This class models the type of thread/mutex dependency that is established by + * either scope based accesses (e.g., global variables) or block scope differences. + */ +class AccessBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + AccessBasedThreadDependentMutex() { + // encapsulates usages from outside scopes not directly expressed + // in dataflow. + exists(MutexSource mutexSrc, ThreadedFunction f | + DataFlow::exprNode(mutexSrc) = this and + // find a variable that was assigned the mutex + TaintTracking::localTaint(DataFlow::exprNode(mutexSrc), + DataFlow::exprNode(variableSource.getAnAssignedValue())) and + // find all subsequent accesses of that variable that are within a + // function and set those to the sink + exists(VariableAccess va | + va = variableSource.getAnAccess() and + va.getEnclosingFunction() = f and + sink = DataFlow::exprNode(va) + ) + ) + } + + override DataFlow::Node getAUsage() { DataFlow::exprNode(variableSource.getAnAccess()) = result } +} + +/** + * In the typical C thread model, a mutex is a created by a function that is not responsible + * for creating the variable. Thus this class encodes a slightly different semantics + * wherein the usage pattern is that of variables that have been both initialized + * and then subsequently passed into a thread directly. + */ +class DeclarationInitBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + DeclarationInitBasedThreadDependentMutex() { + exists(MutexSource ms, ThreadCreationFunction tcf | + this = DataFlow::exprNode(ms) and + // accessed as a mutex source + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), + DataFlow::exprNode(ms.getAnArgument())) and + // subsequently passed to a thread creation function (order not strictly + // enforced for performance reasons) + sink = DataFlow::exprNode(tcf.getAnArgument()) and + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), sink) + ) + } + + override DataFlow::Node getAUsage() { + TaintTracking::localTaint(getASource(), result) or + DataFlow::exprNode(variableSource.getAnAccess()) = result + } + + override DataFlow::Node getASource() { + // the source is either the thing that declared + // the mutex + result = this + or + // or the thread we are using it in + result = getAThreadSource() + } + + DataFlow::Node getSink() { result = sink } + + /** + * Gets the dataflow nodes corresponding to thread local usages of the + * dependent mutex. + */ + override DataFlow::Node getAThreadSource() { + // here we line up the actual parameter at the thread creation + // site with the formal parameter in the target thread. + // Note that there are differences between the C and C++ versions + // of the argument ordering in the thread creation function. However, + // since the C version only takes one parameter (as opposed to multiple) + // we can simplify this search by considering only the first argument. + exists( + FunctionCall fc, Function f, int n // CPP Version + | + fc.getArgument(n) = sink.asExpr() and + f = fc.getArgument(0).(FunctionAccess).getTarget() and + // in C++, there is an extra argument to the `std::thread` call + // so we must subtract 1 since this is not passed to the thread. + result = DataFlow::exprNode(f.getParameter(n - 1).getAnAccess()) + ) + or + exists( + FunctionCall fc, Function f // C Version + | + fc.getAnArgument() = sink.asExpr() and + // in C, the second argument is the function + f = fc.getArgument(1).(FunctionAccess).getTarget() and + // in C, the passed argument is always the zeroth argument + result = DataFlow::exprNode(f.getParameter(0).getAnAccess()) + ) + } +} + +/** + * In the typical C model, another way to use mutexes is to work with global variables + * that can be initialized at various points -- one of which must be inside a thread. + * This class encapsulates this pattern. + */ +class DeclarationInitAccessBasedThreadDependentMutex extends ThreadDependentMutex { + Variable variableSource; + + DeclarationInitAccessBasedThreadDependentMutex() { + exists(MutexSource ms, ThreadedFunction tf, VariableAccess va | + this = DataFlow::exprNode(ms) and + // accessed as a mutex source + TaintTracking::localTaint(DataFlow::exprNode(variableSource.getAnAccess()), + DataFlow::exprNode(ms.getAnArgument())) and + // is accessed somewhere else + va = variableSource.getAnAccess() and + sink = DataFlow::exprNode(va) and + // one of which must be a thread + va.getEnclosingFunction() = tf + ) + } + + override DataFlow::Node getAUsage() { result = DataFlow::exprNode(variableSource.getAnAccess()) } +} + +module ThreadDependentMutexConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof MutexSource } + + predicate isSink(DataFlow::Node node) { + exists(ThreadCreationFunction f | f.getAnArgument() = node.asExpr()) + } +} + +module ThreadDependentMutexFlow = TaintTracking::Global; diff --git a/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorageNew.qll b/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorageNew.qll new file mode 100644 index 0000000000..6dcb169250 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/concurrency/ThreadSpecificStorageNew.qll @@ -0,0 +1,59 @@ +import cpp +private import semmle.code.cpp.dataflow.new.DataFlow +private import codingstandards.cpp.concurrency.ThreadCreation + +/** + * Models calls to thread specific storage function calls. + */ +abstract class ThreadSpecificStorageFunctionCall extends FunctionCall { + /** + * Gets the key to which this call references. + */ + Expr getKey() { getArgument(0) = result } +} + +/** + * Models calls to `tss_get`. + */ +class TSSGetFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSGetFunctionCall() { getTarget().getName() = "tss_get" } +} + +/** + * Models calls to `tss_set`. + */ +class TSSSetFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSSetFunctionCall() { getTarget().getName() = "tss_set" } +} + +/** + * Models calls to `tss_create` + */ +class TSSCreateFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSCreateFunctionCall() { getTarget().getName() = "tss_create" } + + predicate hasDeallocator() { + not exists(MacroInvocation mi, NullMacro nm | + getArgument(1) = mi.getExpr() and + mi = nm.getAnInvocation() + ) + } +} + +/** + * Models calls to `tss_delete` + */ +class TSSDeleteFunctionCall extends ThreadSpecificStorageFunctionCall { + TSSDeleteFunctionCall() { getTarget().getName() = "tss_delete" } +} + +/** + * Gets a call to `DeallocationExpr` that deallocates memory owned by thread specific + * storage. + */ +predicate getAThreadSpecificStorageDeallocationCall(C11ThreadCreateCall tcc, DeallocationExpr dexp) { + exists(TSSGetFunctionCall tsg | + tcc.getFunction().getEntryPoint().getASuccessor*() = tsg and + DataFlow::localFlow(DataFlow::exprNode(tsg), DataFlow::exprNode(dexp.getFreedExpr())) + ) +} diff --git a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll index 4ab01520f6..412a571fe4 100644 --- a/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll +++ b/cpp/common/src/codingstandards/cpp/rules/danglingcapturewhenreturninglambdaobject/DanglingCaptureWhenReturningLambdaObject.qll @@ -5,7 +5,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions diff --git a/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll b/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll index adb9785814..16f9638294 100644 --- a/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll +++ b/cpp/common/src/codingstandards/cpp/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow import ArrayToPointerDiffOperandFlow::PathGraph module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { @@ -25,6 +25,8 @@ module ArrayToPointerDiffOperandConfig implements DataFlow::ConfigSig { // Add a flow step from the base to the array expression to track pointers to elements of the array. exists(ArrayExpr e | e.getArrayBase() = pred.asExpr() and e = succ.asExpr()) } + + predicate isBarrierIn(DataFlow::Node node) { isSource(node) } } module ArrayToPointerDiffOperandFlow = DataFlow::Global; diff --git a/cpp/common/src/codingstandards/cpp/rules/guardaccesstobitfields/GuardAccessToBitFields.qll b/cpp/common/src/codingstandards/cpp/rules/guardaccesstobitfields/GuardAccessToBitFields.qll index 5b03a4f8bd..8bac7e15ee 100644 --- a/cpp/common/src/codingstandards/cpp/rules/guardaccesstobitfields/GuardAccessToBitFields.qll +++ b/cpp/common/src/codingstandards/cpp/rules/guardaccesstobitfields/GuardAccessToBitFields.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew abstract class GuardAccessToBitFieldsSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll index b26421c72c..b11050e491 100644 --- a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll +++ b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll @@ -5,7 +5,6 @@ */ import cpp -import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.Exclusions import codingstandards.cpp.standardlibrary.FileStreams import codingstandards.cpp.standardlibrary.FileAccess diff --git a/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll b/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll index 5ccbe83c72..4b09e85873 100644 --- a/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll +++ b/cpp/common/src/codingstandards/cpp/rules/joinordetachthreadonlyonce/JoinOrDetachThreadOnlyOnce.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew abstract class JoinOrDetachThreadOnlyOnceSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/preservesafetywhenusingconditionvariables/PreserveSafetyWhenUsingConditionVariables.qll b/cpp/common/src/codingstandards/cpp/rules/preservesafetywhenusingconditionvariables/PreserveSafetyWhenUsingConditionVariables.qll index 94d9d201c4..0851fe980a 100644 --- a/cpp/common/src/codingstandards/cpp/rules/preservesafetywhenusingconditionvariables/PreserveSafetyWhenUsingConditionVariables.qll +++ b/cpp/common/src/codingstandards/cpp/rules/preservesafetywhenusingconditionvariables/PreserveSafetyWhenUsingConditionVariables.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew abstract class PreserveSafetyWhenUsingConditionVariablesSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll b/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll index db755293c6..25e169b139 100644 --- a/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll +++ b/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew import semmle.code.cpp.controlflow.Dominance abstract class PreventDeadlockByLockingInPredefinedOrderSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll b/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll index fd56f5d899..cb0bc765e6 100644 --- a/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll +++ b/cpp/common/src/codingstandards/cpp/rules/stringnumberconversionmissingerrorcheck/StringNumberConversionMissingErrorCheck.qll @@ -7,7 +7,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.dataflow.new.TaintTracking import codingstandards.cpp.standardlibrary.CharStreams abstract class StringNumberConversionMissingErrorCheckSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll b/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll index 3b0abbad0d..f9ffb4fc9a 100644 --- a/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll +++ b/cpp/common/src/codingstandards/cpp/rules/useonlyarrayindexingforpointerarithmetic/UseOnlyArrayIndexingForPointerArithmetic.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow abstract class UseOnlyArrayIndexingForPointerArithmeticSharedQuery extends Query { } diff --git a/cpp/common/src/codingstandards/cpp/rules/wrapspuriousfunctioninloop/WrapSpuriousFunctionInLoop.qll b/cpp/common/src/codingstandards/cpp/rules/wrapspuriousfunctioninloop/WrapSpuriousFunctionInLoop.qll index 99bdbeee5d..382cda1ae8 100644 --- a/cpp/common/src/codingstandards/cpp/rules/wrapspuriousfunctioninloop/WrapSpuriousFunctionInLoop.qll +++ b/cpp/common/src/codingstandards/cpp/rules/wrapspuriousfunctioninloop/WrapSpuriousFunctionInLoop.qll @@ -6,7 +6,7 @@ import cpp import codingstandards.cpp.Customizations import codingstandards.cpp.Exclusions -import codingstandards.cpp.Concurrency +import codingstandards.cpp.ConcurrencyNew abstract class WrapSpuriousFunctionInLoopSharedQuery extends Query { } diff --git a/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected b/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected index 2d293e6928..89f6cec56a 100644 --- a/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected +++ b/cpp/common/test/rules/donotsubtractpointersaddressingdifferentarrays/DoNotSubtractPointersAddressingDifferentArrays.expected @@ -4,19 +4,27 @@ problems | test.cpp:13:10:13:11 | p4 | test.cpp:5:14:5:15 | l2 | test.cpp:13:10:13:11 | p4 | Subtraction between left operand pointing to array $@ and other operand pointing to array $@. | test.cpp:3:7:3:8 | l2 | l2 | test.cpp:2:7:2:8 | l1 | l1 | | test.cpp:13:15:13:16 | l1 | test.cpp:13:15:13:16 | l1 | test.cpp:13:15:13:16 | l1 | Subtraction between right operand pointing to array $@ and other operand pointing to array $@. | test.cpp:2:7:2:8 | l1 | l1 | test.cpp:3:7:3:8 | l2 | l2 | edges -| test.cpp:4:14:4:15 | l1 | test.cpp:4:14:4:18 | access to array | provenance | Config | -| test.cpp:4:14:4:18 | access to array | test.cpp:10:10:10:11 | p1 | provenance | | -| test.cpp:4:14:4:18 | access to array | test.cpp:12:10:12:11 | p1 | provenance | | -| test.cpp:5:14:5:15 | l2 | test.cpp:5:14:5:19 | access to array | provenance | Config | -| test.cpp:5:14:5:19 | access to array | test.cpp:11:10:11:11 | p2 | provenance | | -| test.cpp:5:14:5:19 | access to array | test.cpp:12:15:12:16 | p2 | provenance | | -| test.cpp:5:14:5:19 | access to array | test.cpp:13:10:13:11 | p4 | provenance | | -| test.cpp:5:14:5:19 | access to array | test.cpp:14:10:14:11 | p4 | provenance | | +| test.cpp:4:13:4:18 | & ... | test.cpp:4:13:4:18 | & ... | provenance | | +| test.cpp:4:13:4:18 | & ... | test.cpp:10:10:10:11 | p1 | provenance | | +| test.cpp:4:13:4:18 | & ... | test.cpp:12:10:12:11 | p1 | provenance | | +| test.cpp:4:14:4:15 | l1 | test.cpp:4:13:4:18 | & ... | provenance | Config | +| test.cpp:5:13:5:19 | & ... | test.cpp:5:13:5:19 | & ... | provenance | | +| test.cpp:5:13:5:19 | & ... | test.cpp:6:13:6:14 | p2 | provenance | | +| test.cpp:5:13:5:19 | & ... | test.cpp:11:10:11:11 | p2 | provenance | | +| test.cpp:5:13:5:19 | & ... | test.cpp:12:15:12:16 | p2 | provenance | | +| test.cpp:5:14:5:15 | l2 | test.cpp:5:13:5:19 | & ... | provenance | Config | +| test.cpp:6:13:6:14 | p2 | test.cpp:7:13:7:14 | p3 | provenance | | +| test.cpp:7:13:7:14 | p3 | test.cpp:13:10:13:11 | p4 | provenance | | +| test.cpp:7:13:7:14 | p3 | test.cpp:14:10:14:11 | p4 | provenance | | nodes +| test.cpp:4:13:4:18 | & ... | semmle.label | & ... | +| test.cpp:4:13:4:18 | & ... | semmle.label | & ... | | test.cpp:4:14:4:15 | l1 | semmle.label | l1 | -| test.cpp:4:14:4:18 | access to array | semmle.label | access to array | +| test.cpp:5:13:5:19 | & ... | semmle.label | & ... | +| test.cpp:5:13:5:19 | & ... | semmle.label | & ... | | test.cpp:5:14:5:15 | l2 | semmle.label | l2 | -| test.cpp:5:14:5:19 | access to array | semmle.label | access to array | +| test.cpp:6:13:6:14 | p2 | semmle.label | p2 | +| test.cpp:7:13:7:14 | p3 | semmle.label | p3 | | test.cpp:10:10:10:11 | p1 | semmle.label | p1 | | test.cpp:10:15:10:16 | l1 | semmle.label | l1 | | test.cpp:11:10:11:11 | p2 | semmle.label | p2 |