From 00891fa45518e2ad0b2c969868c5bccc4bd0a2b8 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 19 Sep 2022 10:31:02 -0400 Subject: [PATCH 001/164] Android Manifest Incomplete provider permissions initial commit Initial work on checking provider elements in Android manifests for complete permissions. --- .../ContentProviderIncompletePermissions.ql | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql new file mode 100644 index 00000000000..647b3b707c2 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql @@ -0,0 +1,23 @@ +/** + * @name Missing read or write permission configuration + * @description Defining an incomplete set of permissions + * @kind problem + * @problem.severity warning + * @security-severity 7.8 + * @id java/android/incomplete-provider-permissions + * @tags security + * external/cwe/cwe-276 + * @precision medium + */ + +import java +import semmle.code.xml.AndroidManifest + +from AndroidProviderXmlElement provider +where + ( + provider.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() or + provider.getAnAttribute().(AndroidPermissionXmlAttribute).isRead() + ) and + not provider.requiresPermissions() +select provider, "Incomplete permissions" From e37f62bb5eb7aff3036c39169def3d50111ecc60 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 19 Sep 2022 10:32:02 -0400 Subject: [PATCH 002/164] Android ContentProvider.openFile does not check `mode` initital commit Initial commit for work on a query finding instances where the `mode` parameter of an override of the `openFile` method of the `android.content.ContentProvider` class --- .../CWE-276/MisconfiguedContentProviderUse.ql | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql diff --git a/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql b/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql new file mode 100644 index 00000000000..06c68403d53 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql @@ -0,0 +1,27 @@ +/** + * @name Misconfigured ContentProvider use + * @description ContentProvider#openFile override which does not use `mode` argument. + * @kind problem + * @id java/android/misconfigured-content-provider + * @problem.severity warning + * @security-severity 7.8 + * @tags security external/cwe/cwe-276 + * @precision medium + */ + +import java + +class ContentProviderOpenFileMethod extends Method { + ContentProviderOpenFileMethod() { + this.hasName("openFile") and + this.getDeclaringType().getASupertype*().hasQualifiedName("android.content", "ContentProvider") + } + + predicate doesNotCheckMode() { + exists(Parameter p | p = this.getParameter(1) | not exists(p.getAnAccess())) + } +} + +from ContentProviderOpenFileMethod ofm +where ofm.doesNotCheckMode() +select ofm, "Open file" From f1efc76e8c127dcdbaf4e0682800f9c642503caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 22 Sep 2022 17:06:04 +0200 Subject: [PATCH 003/164] C++: Initial commit of `cpp/comma-before-missing-indentation` --- .../CommaBeforeMisleadingIndentation.cpp | 0 .../CommaBeforeMisleadingIndentation.qhelp | 18 ++++++++++++++++++ .../CommaBeforeMisleadingIndentation.ql | 1 + .../CommaBeforeMisleadingIndentation.expected | 1 + .../CommaBeforeMisleadingIndentation.qlref | 1 + .../CommaBeforeMisleadingIndentation/test.cpp | 19 +++++++++++++++++++ 6 files changed, 40 insertions(+) create mode 100644 cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp create mode 100644 cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp create mode 100644 cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql create mode 100644 cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected create mode 100644 cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.qlref create mode 100644 cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp new file mode 100644 index 00000000000..5483ddfe921 --- /dev/null +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -0,0 +1,18 @@ + + + + +

...

+
+ + +

...

+
+ + + + + +
diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql new file mode 100644 index 00000000000..82198eaf87b --- /dev/null +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -0,0 +1 @@ +select 1 diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected new file mode 100644 index 00000000000..2a4f078a25f --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected @@ -0,0 +1 @@ +| 1 | diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.qlref b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.qlref new file mode 100644 index 00000000000..02b5f38e358 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.qlref @@ -0,0 +1 @@ +Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp new file mode 100644 index 00000000000..ed35190fee9 --- /dev/null +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -0,0 +1,19 @@ + +void test(int i, int j, int (*foo)(int)) +{ + if (i) + (void)i, // GOOD + (void)j; + + if (i) + (void)i, // BAD + (void)j; + + foo((i++, j++)); // GOOD + foo((i++, // GOOD + j++)); + foo((i++ + , j++)); // GOOD + foo((i++, + j++)); // BAD (?) +} From dca13f5c89905977e1ddecb6b05e2f8afa27b7c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 22 Sep 2022 17:42:28 +0200 Subject: [PATCH 004/164] C++: Initial `cpp/comma-before-misleading-indentation` MRVA top 1000 run at: https://github.com/github/semmle-code/actions/runs/3106828111 --- .../CommaBeforeMisleadingIndentation.ql | 20 ++++++++++++++++++- .../CommaBeforeMisleadingIndentation.expected | 3 ++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 82198eaf87b..12bb7d551f8 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -1 +1,19 @@ -select 1 +/** + * @name Comma before misleading indentation + * @description The expressions before and after the comma operator can be misread because of an unusual difference in start columns. + * @kind problem + * @id cpp/comma-before-misleading-indentation + * @problem.severity recommendation + * @tags maintainability + * readability + */ + +import cpp + +from CommaExpr ce +where + ce.fromSource() and + not exists(MacroInvocation me | ce = me.getAnAffectedElement()) and + ce.getLeftOperand().getLocation().getStartColumn() > + ce.getRightOperand().getLocation().getStartColumn() +select ce, "Comma before misleading indentation." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected index 2a4f078a25f..a977b9ce72f 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected @@ -1 +1,2 @@ -| 1 | +| test.cpp:9:3:10:8 | ... , ... | Comma before misleading indentation. | +| test.cpp:17:7:18:4 | ... , ... | Comma before misleading indentation. | From 0e9b77e7c314509beea26479cb10b47a4044d5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 23 Sep 2022 11:46:31 +0200 Subject: [PATCH 005/164] C++: Initial .qhelp file --- .../CommaBeforeMisleadingIndentation.cpp | 32 +++++++++++++++++++ .../CommaBeforeMisleadingIndentation.qhelp | 10 ++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp index e69de29bb2d..2b30b6ba1f1 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp @@ -0,0 +1,32 @@ +/* + * Here, the comma should have been a semicolon: + */ + +enum privileges entitlements = NONE; + +if (is_admin) + entitlements = FULL, // BAD + +restrict_privileges(entitlements); + +/* + * This is misleading, because the code is unexpectedly equivalent to: + */ + +enum privileges entitlements = NONE; + +if (is_admin) { + entitlements = FULL; + restrict_privileges(entitlements); +} + +/* + * Whereas the following code was probably intended: + */ + +enum privileges entitlements = NONE; + +if (is_admin) + entitlements = FULL; // GOOD + +restrict_privileges(entitlements); diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp index 5483ddfe921..b54a0e4800a 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -4,11 +4,17 @@ -

...

+

+If the expression to the right of a comma operator starts at an earlier column than the expression to the left, then +this suspicious indentation likely indicates a logic error caused by a typo that may escape visual inspection. +

-

...

+

+Use standard indentation around the comma operator: begin the right-hand-side operand at the same level of +indentation as the left-hand-side operand. +

From cacf78838c61bb855e7bf212a77606552b2fe7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Tue, 27 Sep 2022 18:48:32 +0200 Subject: [PATCH 006/164] C++: Tests (w/ FPs) from MRVA top 1000 run --- .../CommaBeforeMisleadingIndentation/test.cpp | 144 +++++++++++++++++- 1 file changed, 136 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index ed35190fee9..a9ebab951e2 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -1,6 +1,22 @@ +// clang-format off -void test(int i, int j, int (*foo)(int)) +typedef unsigned size_t; + +struct X { + int foo(int y) { return y; } +} x; + +#define FOO(x) ( \ + (x), \ + (x) \ +) + +#define BAR(x, y) ((x), (y)) + +int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) { + // Comma in simple if statement (prototypical example): + if (i) (void)i, // GOOD (void)j; @@ -9,11 +25,123 @@ void test(int i, int j, int (*foo)(int)) (void)i, // BAD (void)j; - foo((i++, j++)); // GOOD - foo((i++, // GOOD - j++)); - foo((i++ - , j++)); // GOOD - foo((i++, - j++)); // BAD (?) + // Parenthesized comma (borderline example): + + foo(i++), j++; // GOOD + (foo(i++), j++); // GOOD + (foo(i++), // GOOD + j++); + (foo(i++), + j++); // BAD (?) + + x.foo(i++), j++; // GOOD + (x.foo(i++), j++); // GOOD + (x.foo(i++), // GOOD [FALSE POSITIVE] + j++); + (x.foo(i++), + j++); // BAD (?) + + FOO(i++), j++; // GOOD + (FOO(i++), j++); // GOOD + (FOO(i++), // GOOD + j++); + (FOO(i++), + j++); // BAD (?) + + (void)(i++), j++; // GOOD + ((void)(i++), j++); // GOOD + ((void)(i++), // GOOD [FALSE POSITIVE] + j++); + ((void)(i++), + j++); // BAD (?) + + // Comma in argument list doesn't count: + + bar(i++, j++); // GOOD + bar(i++, + j++); // GOOD + bar(i++ + , j++); // GOOD + bar(i++, + j++); // GOOD: common pattern and unlikely to be misread. + + BAR(i++, j++); // GOOD + BAR(i++, + j++); // GOOD + BAR(i++ + , j++); // GOOD + BAR(i++, + j++); // GOOD: common pattern and unlikely to be misread. + + using T = decltype(x.foo(i++), // GOOD [FALSE POSITIVE] + j++); + (void)sizeof(x.foo(i++), // GOOD [FALSE POSITIVE] + j++); + + // Comma in loops + + while (i = foo(j++), // GOOD + i != j && i != 42 && + !foo(j)) { + i = j = i + j; + } + + // Mixed tabs and spaces (ugly case): + + for (i = 0, // GOOD if tab >= 4 spaces else BAD + j = 0; + i + j < 10; + i++, // GOOD if tab >= 4 spaces else BAD + j++); + + if (i) + (void)i, // GOOD if tab >= 4 spaces else BAD + (void)j; + + // One char difference (common but borderline): + + for (i = 0, // GOOD? [FALSE POSITIVE] + j = 1; + i + j < 10; + i++, j++); + + for (i = 0, + j = 1; i < 10; i += 2, // GOOD? [FALSE POSITIVE] + j++) {} + + // LHS ends on same line RHS begins on: + + int k = (foo( + i++ + ), j++); // GOOD? [FALSE POSITIVE] + + // Weird case: + + if (foo(j)) + return i++ + , i++ // GOOD(?) [FALSE POSITIVE] + ? 1 + : 2; + + return 0; } + +// Comma in variadic template splice: + +namespace std { + template + struct index_sequence {}; +} + +template +struct zip_index {}; + +template +int& at(zip_index) { throw 1; } + +template +void for_each_input(Fn&& fn, std::index_sequence) { + (fn(zip_index{}, at(zip_index{})), ...); // GOOD +} + +// clang-format on From e7c1fadd94471883da51eb5bcdfd2d421d3c32a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 15:02:22 +0200 Subject: [PATCH 007/164] C++: Fix member-call- and C-cast-related FPs --- .../CommaBeforeMisleadingIndentation.ql | 23 +++++++++++++++---- .../CommaBeforeMisleadingIndentation/test.cpp | 8 +++---- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 12bb7d551f8..900b08994c7 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -9,11 +9,24 @@ */ import cpp +import semmle.code.cpp.commons.Exclusions -from CommaExpr ce +Expr normalizeExpr(Expr e) { + if exists(e.(Call).getQualifier()) + then result = normalizeExpr(e.(Call).getQualifier()) + else + if e.hasExplicitConversion() + then result = normalizeExpr(e.getFullyConverted()) + else result = e +} + +from CommaExpr ce, Expr left, Expr right, int leftStartColumn, int rightStartColumn where ce.fromSource() and - not exists(MacroInvocation me | ce = me.getAnAffectedElement()) and - ce.getLeftOperand().getLocation().getStartColumn() > - ce.getRightOperand().getLocation().getStartColumn() -select ce, "Comma before misleading indentation." + not isFromMacroDefinition(ce) and + left = normalizeExpr(ce.getLeftOperand()) and + right = normalizeExpr(ce.getRightOperand()) and + leftStartColumn = left.getLocation().getStartColumn() and + rightStartColumn = right.getLocation().getStartColumn() and + leftStartColumn > rightStartColumn +select right, "The indentation level after the comma can be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index a9ebab951e2..8aae39668f6 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -36,7 +36,7 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) x.foo(i++), j++; // GOOD (x.foo(i++), j++); // GOOD - (x.foo(i++), // GOOD [FALSE POSITIVE] + (x.foo(i++), // GOOD j++); (x.foo(i++), j++); // BAD (?) @@ -50,7 +50,7 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) (void)(i++), j++; // GOOD ((void)(i++), j++); // GOOD - ((void)(i++), // GOOD [FALSE POSITIVE] + ((void)(i++), // GOOD j++); ((void)(i++), j++); // BAD (?) @@ -73,9 +73,9 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) BAR(i++, j++); // GOOD: common pattern and unlikely to be misread. - using T = decltype(x.foo(i++), // GOOD [FALSE POSITIVE] + using T = decltype(x.foo(i++), // GOOD j++); - (void)sizeof(x.foo(i++), // GOOD [FALSE POSITIVE] + (void)sizeof(x.foo(i++), // GOOD j++); // Comma in loops From 0128b1702e5568df4ca66e61362c6c78a50f9ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 15:36:01 +0200 Subject: [PATCH 008/164] C++: Fix "LHS-end = RHS-begin" FP --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 9 +++++---- .../CommaBeforeMisleadingIndentation/test.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 900b08994c7..a786f4aec33 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -20,13 +20,14 @@ Expr normalizeExpr(Expr e) { else result = e } -from CommaExpr ce, Expr left, Expr right, int leftStartColumn, int rightStartColumn +from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc where ce.fromSource() and not isFromMacroDefinition(ce) and left = normalizeExpr(ce.getLeftOperand()) and right = normalizeExpr(ce.getRightOperand()) and - leftStartColumn = left.getLocation().getStartColumn() and - rightStartColumn = right.getLocation().getStartColumn() and - leftStartColumn > rightStartColumn + leftLoc = left.getLocation() and + rightLoc = right.getLocation() and + leftLoc.getEndLine() < rightLoc.getStartLine() and + leftLoc.getStartColumn() > rightLoc.getStartColumn() select right, "The indentation level after the comma can be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 8aae39668f6..642161f6549 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -113,7 +113,7 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) int k = (foo( i++ - ), j++); // GOOD? [FALSE POSITIVE] + ), j++); // GOOD? // Weird case: From 823b0109f092b037268531b375da95b5fe7e967f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 16:20:13 +0200 Subject: [PATCH 009/164] C++: Mark FPs that are hard to solve w/o source code --- .../CommaBeforeMisleadingIndentation/test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 642161f6549..cdbb46bed95 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -88,25 +88,25 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) // Mixed tabs and spaces (ugly case): - for (i = 0, // GOOD if tab >= 4 spaces else BAD + for (i = 0, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ j = 0; i + j < 10; - i++, // GOOD if tab >= 4 spaces else BAD + i++, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ j++); if (i) - (void)i, // GOOD if tab >= 4 spaces else BAD + (void)i, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ (void)j; // One char difference (common but borderline): - for (i = 0, // GOOD? [FALSE POSITIVE] + for (i = 0, // GOOD? [FALSE POSITIVE] -- can't exclude w/o source code text :/ j = 1; i + j < 10; i++, j++); for (i = 0, - j = 1; i < 10; i += 2, // GOOD? [FALSE POSITIVE] + j = 1; i < 10; i += 2, // GOOD? [FALSE POSITIVE] -- can't exclude w/o source code text :/ j++) {} // LHS ends on same line RHS begins on: @@ -119,7 +119,7 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) if (foo(j)) return i++ - , i++ // GOOD(?) [FALSE POSITIVE] + , i++ // GOOD(?) [FALSE POSITIVE] -- can't exclude w/o source code text :/ ? 1 : 2; From 67d12cdc7d7f4d67aca8d2164f3e1a53d38a0c27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 17:14:15 +0000 Subject: [PATCH 010/164] JS: Bump patch version of ML-powered library and query packs --- .../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index d7698ed15b9..b437e4de0ba 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -version: 0.3.3 +version: 0.3.4 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 8c6ac3ea38f..0942785b20a 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.3.3 +version: 0.3.4 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: From 592bc18a97a6fe16a48042d599ce312993ac8ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 19:38:41 +0200 Subject: [PATCH 011/164] C++: Reduce FPs by excluding all commas in loop heads This leads to a 50% reduction of alerts in MRVA 1000. --- .../CommaBeforeMisleadingIndentation.ql | 9 ++++++++- .../CommaBeforeMisleadingIndentation/test.cpp | 20 +++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index a786f4aec33..f2cd6bed55f 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -20,6 +20,12 @@ Expr normalizeExpr(Expr e) { else result = e } +predicate isInLoopHead(CommaExpr ce) { + ce.getParent*() = [any(Loop l).getCondition(), any(ForStmt f).getUpdate()] + or + ce.getEnclosingStmt() = any(ForStmt f).getInitialization() +} + from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc where ce.fromSource() and @@ -28,6 +34,7 @@ where right = normalizeExpr(ce.getRightOperand()) and leftLoc = left.getLocation() and rightLoc = right.getLocation() and + not isInLoopHead(ce) and // HACK to reduce FPs in loop heads; assumption: unlikely to be misread due to '(', ')' delimiters leftLoc.getEndLine() < rightLoc.getStartLine() and leftLoc.getStartColumn() > rightLoc.getStartColumn() -select right, "The indentation level after the comma can be misleading (for some tab sizes)." +select right, "The indentation after the comma may be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index cdbb46bed95..8237bb7253e 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -86,6 +86,15 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) i = j = i + j; } + for (i = 0, // GOOD? Currently ignoring loop heads. + j = 1; + i + j < 10; + i++, j++); + + for (i = 0, + j = 1; i < 10; i += 2, // GOOD? Currently ignoring loop heads. + j++) {} + // Mixed tabs and spaces (ugly case): for (i = 0, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ @@ -98,17 +107,6 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) (void)i, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ (void)j; - // One char difference (common but borderline): - - for (i = 0, // GOOD? [FALSE POSITIVE] -- can't exclude w/o source code text :/ - j = 1; - i + j < 10; - i++, j++); - - for (i = 0, - j = 1; i < 10; i += 2, // GOOD? [FALSE POSITIVE] -- can't exclude w/o source code text :/ - j++) {} - // LHS ends on same line RHS begins on: int k = (foo( From 6d5df14547fd004f1005e46c76971a419399d108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 20:01:14 +0200 Subject: [PATCH 012/164] C++: Remove arguable FPs re: sizeof/decltype --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 10 +++++++++- .../CommaBeforeMisleadingIndentation/test.cpp | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index f2cd6bed55f..acc6cd94618 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -11,6 +11,7 @@ import cpp import semmle.code.cpp.commons.Exclusions +/** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { if exists(e.(Call).getQualifier()) then result = normalizeExpr(e.(Call).getQualifier()) @@ -26,6 +27,12 @@ predicate isInLoopHead(CommaExpr ce) { ce.getEnclosingStmt() = any(ForStmt f).getInitialization() } +predicate isInDecltypeOrSizeof(CommaExpr ce) { + ce.getParent*() instanceof SizeofExprOperator + or + ce.getParent*() = any(Decltype d).getExpr() +} + from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc where ce.fromSource() and @@ -34,7 +41,8 @@ where right = normalizeExpr(ce.getRightOperand()) and leftLoc = left.getLocation() and rightLoc = right.getLocation() and - not isInLoopHead(ce) and // HACK to reduce FPs in loop heads; assumption: unlikely to be misread due to '(', ')' delimiters + not isInLoopHead(ce) and // <- HACK to reduce FPs in loop heads; assumption: unlikely to be misread due to '(', ')' delimiters + not isInDecltypeOrSizeof(ce) and // <- Removes arguable FPs since, like function calls (and loop heads), these Exprs have clear delimiters. leftLoc.getEndLine() < rightLoc.getStartLine() and leftLoc.getStartColumn() > rightLoc.getStartColumn() select right, "The indentation after the comma may be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 8237bb7253e..44a22c01cda 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -77,6 +77,10 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) j++); (void)sizeof(x.foo(i++), // GOOD j++); + using U = decltype(x.foo(i++), // GOOD? Unlikely to be misread + j++); + (void)sizeof(x.foo(i++), // GOOD? Unlikely to be misread + j++); // Comma in loops @@ -86,6 +90,11 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) i = j = i + j; } + while (i = foo(j++), // GOOD??? Currently ignoring loop heads + i != j && i != 42 && !foo(j)) { + i = j = i + j; + } + for (i = 0, // GOOD? Currently ignoring loop heads. j = 1; i + j < 10; From 96c73bcb19accddc3aeebbadb2f86eb55eee5c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 20:37:22 +0200 Subject: [PATCH 013/164] C++: Fix FP: bad Location for FieldAccess exprs --- .../CommaBeforeMisleadingIndentation.ql | 11 +++++++---- .../CommaBeforeMisleadingIndentation/test.cpp | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index acc6cd94618..ddb747b7b9b 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -16,9 +16,12 @@ Expr normalizeExpr(Expr e) { if exists(e.(Call).getQualifier()) then result = normalizeExpr(e.(Call).getQualifier()) else - if e.hasExplicitConversion() - then result = normalizeExpr(e.getFullyConverted()) - else result = e + if exists(e.(FieldAccess).getQualifier()) + then result = normalizeExpr(e.(FieldAccess).getQualifier()) + else + if e.hasExplicitConversion() + then result = normalizeExpr(e.getFullyConverted()) + else result = e } predicate isInLoopHead(CommaExpr ce) { @@ -45,4 +48,4 @@ where not isInDecltypeOrSizeof(ce) and // <- Removes arguable FPs since, like function calls (and loop heads), these Exprs have clear delimiters. leftLoc.getEndLine() < rightLoc.getStartLine() and leftLoc.getStartColumn() > rightLoc.getStartColumn() -select right, "The indentation after the comma may be misleading (for some tab sizes)." +select right, "The indentation level may be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 44a22c01cda..032df5fda3c 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -122,7 +122,7 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) i++ ), j++); // GOOD? - // Weird case: + // Weird cases: if (foo(j)) return i++ @@ -130,7 +130,18 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) ? 1 : 2; - return 0; + struct { + struct { + void tutu() {} + long toto() { return 42; } + } titi; + } *tata; + + int quux = + (tata->titi.tutu(), + foo(tata->titi.toto())); // GOOD + + return quux; } // Comma in variadic template splice: From 19a9c5d7d3947042dcd45ee089b43130fe3e800a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 28 Sep 2022 21:19:45 +0200 Subject: [PATCH 014/164] C++: Identified another real-life FP --- .../Likely Errors/CommaBeforeMisleadingIndentation/test.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 032df5fda3c..2588d309af4 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -13,6 +13,8 @@ struct X { #define BAR(x, y) ((x), (y)) +#define BAZ //printf + int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) { // Comma in simple if statement (prototypical example): @@ -82,6 +84,9 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) (void)sizeof(x.foo(i++), // GOOD? Unlikely to be misread j++); + BAZ("%d %d\n", i, + j); // GOOD [FALSE POSITIVE] -- but can only be excluded by excluding all parenthesized commas (which sounds like a good idea actually) + // Comma in loops while (i = foo(j++), // GOOD From 909b36a0787b7b1a636600317935b57f2a60cd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 13:14:36 +0200 Subject: [PATCH 015/164] C++: Fix implicit-this FP, uncovered non-funptr FP --- .../CommaBeforeMisleadingIndentation.ql | 4 +- .../CommaBeforeMisleadingIndentation/test.cpp | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index ddb747b7b9b..617cf8c771b 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -13,10 +13,10 @@ import semmle.code.cpp.commons.Exclusions /** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { - if exists(e.(Call).getQualifier()) + if forex(Expr q | q = e.(Call).getQualifier() | not q instanceof ThisExpr) then result = normalizeExpr(e.(Call).getQualifier()) else - if exists(e.(FieldAccess).getQualifier()) + if forex(Expr q | q = e.(FieldAccess).getQualifier() | not q instanceof ThisExpr) then result = normalizeExpr(e.(FieldAccess).getQualifier()) else if e.hasExplicitConversion() diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 2588d309af4..d57bc3d4574 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -15,7 +15,24 @@ struct X { #define BAZ //printf -int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) +struct Foo { + int i; + int j; + virtual int foo(int) = 0; + virtual int bar(int, int) = 0; + int test(int (*baz)(int)); + + struct Tata { + struct Titi { + void tutu() {} + long toto() { return 42; } + } titi; + } *tata; + + Tata::Titi **titi_ptr_ptr; +}; + +int Foo::test(int (*baz)(int)) { // Comma in simple if statement (prototypical example): @@ -123,9 +140,13 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) // LHS ends on same line RHS begins on: - int k = (foo( + int k1 = (foo( i++ - ), j++); // GOOD? + ), j++); // GOOD? [FALSE POSITIVE] + + int k2 = (baz( + i++ + ), j++); // GOOD when it's a function-pointer call!? // Weird cases: @@ -135,17 +156,13 @@ int test(int i, int j, int (*foo)(int), int (*bar)(int, int)) ? 1 : 2; - struct { - struct { - void tutu() {} - long toto() { return 42; } - } titi; - } *tata; - int quux = (tata->titi.tutu(), foo(tata->titi.toto())); // GOOD + (*titi_ptr_ptr)->tutu(), // GOOD + (&i)[0] += (int)(*titi_ptr_ptr)->toto(); + return quux; } From 64903336f79bbcc95d91b150fc6c1d03669a2fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 15:49:29 +0200 Subject: [PATCH 016/164] C++: Exclude all parenthesized CommaExprs. --- .../CommaBeforeMisleadingIndentation.ql | 11 +++++-- .../CommaBeforeMisleadingIndentation/test.cpp | 33 ++++++++++++------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 617cf8c771b..7592f077ba8 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -36,6 +36,14 @@ predicate isInDecltypeOrSizeof(CommaExpr ce) { ce.getParent*() = any(Decltype d).getExpr() } +predicate isParenthesized(CommaExpr ce) { + isInLoopHead(ce) + or + isInDecltypeOrSizeof(ce) + or + ce.getParent*().(Expr).isParenthesised() +} + from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc where ce.fromSource() and @@ -44,8 +52,7 @@ where right = normalizeExpr(ce.getRightOperand()) and leftLoc = left.getLocation() and rightLoc = right.getLocation() and - not isInLoopHead(ce) and // <- HACK to reduce FPs in loop heads; assumption: unlikely to be misread due to '(', ')' delimiters - not isInDecltypeOrSizeof(ce) and // <- Removes arguable FPs since, like function calls (and loop heads), these Exprs have clear delimiters. + not isParenthesized(ce) and leftLoc.getEndLine() < rightLoc.getStartLine() and leftLoc.getStartColumn() > rightLoc.getStartColumn() select right, "The indentation level may be misleading (for some tab sizes)." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index d57bc3d4574..3b044b377fe 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -44,6 +44,9 @@ int Foo::test(int (*baz)(int)) (void)i, // BAD (void)j; + if (1) FOO(i), + (void)x.foo(j); // BAD + // Parenthesized comma (borderline example): foo(i++), j++; // GOOD @@ -51,28 +54,36 @@ int Foo::test(int (*baz)(int)) (foo(i++), // GOOD j++); (foo(i++), - j++); // BAD (?) + foo(i++), + j++, // GOOD (?) -- Currently explicitly excluded + j++); x.foo(i++), j++; // GOOD (x.foo(i++), j++); // GOOD (x.foo(i++), // GOOD j++); (x.foo(i++), - j++); // BAD (?) + x.foo(i++), + j++, // GOOD (?) -- Currently explicitly excluded + j++); FOO(i++), j++; // GOOD (FOO(i++), j++); // GOOD (FOO(i++), // GOOD j++); (FOO(i++), - j++); // BAD (?) + FOO(i++), + j++, // GOOD (?) -- Currently explicitly excluded + j++); (void)(i++), j++; // GOOD ((void)(i++), j++); // GOOD ((void)(i++), // GOOD j++); ((void)(i++), - j++); // BAD (?) + (void)(i++), + j++, // GOOD (?) -- Currently explicitly excluded + j++); // Comma in argument list doesn't count: @@ -102,7 +113,7 @@ int Foo::test(int (*baz)(int)) j++); BAZ("%d %d\n", i, - j); // GOOD [FALSE POSITIVE] -- but can only be excluded by excluding all parenthesized commas (which sounds like a good idea actually) + j); // GOOD -- Currently explicitly excluded // Comma in loops @@ -128,10 +139,10 @@ int Foo::test(int (*baz)(int)) // Mixed tabs and spaces (ugly case): - for (i = 0, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ + for (i = 0, // GOOD if tab >= 4 spaces else BAD -- Currently ignoring loop heads. j = 0; i + j < 10; - i++, // GOOD if tab >= 4 spaces else BAD -- can't exclude w/o source code text :/ + i++, // GOOD if tab >= 4 spaces else BAD -- Currently ignoring loop heads. j++); if (i) @@ -140,13 +151,13 @@ int Foo::test(int (*baz)(int)) // LHS ends on same line RHS begins on: - int k1 = (foo( + if (1) foo( i++ - ), j++); // GOOD? [FALSE POSITIVE] + ), j++; // GOOD? [FALSE POSITIVE] - int k2 = (baz( + if (1) baz( i++ - ), j++); // GOOD when it's a function-pointer call!? + ), j++; // GOOD... when calling a function pointer..!? // Weird cases: From 29d7c0e21bed08eac3f0f4bb493d907c0fd22f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 16:29:57 +0200 Subject: [PATCH 017/164] C++: Exclude commas in if-conditions. --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 2 ++ .../Likely Errors/CommaBeforeMisleadingIndentation/test.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 7592f077ba8..8f1d994ec62 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -42,6 +42,8 @@ predicate isParenthesized(CommaExpr ce) { isInDecltypeOrSizeof(ce) or ce.getParent*().(Expr).isParenthesised() + or + ce.getParent*() = any(IfStmt i).getCondition() } from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index 3b044b377fe..b508d2e878e 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -137,6 +137,12 @@ int Foo::test(int (*baz)(int)) j = 1; i < 10; i += 2, // GOOD? Currently ignoring loop heads. j++) {} + // Comma in if-conditions: + + if (i = foo(j++), + i == j) // GOOD(?) -- Currently ignoring if-conditions for the same reason as other parenthesized commas. + i = 0; + // Mixed tabs and spaces (ugly case): for (i = 0, // GOOD if tab >= 4 spaces else BAD -- Currently ignoring loop heads. From 28bd59110793e5bb17671ea252eb3762e7f2b9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 17:04:11 +0200 Subject: [PATCH 018/164] C++: Fix explicit this-> FP. --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 4 ++-- .../Likely Errors/CommaBeforeMisleadingIndentation/test.cpp | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 8f1d994ec62..a54adc49cfe 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -13,10 +13,10 @@ import semmle.code.cpp.commons.Exclusions /** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { - if forex(Expr q | q = e.(Call).getQualifier() | not q instanceof ThisExpr) + if forex(Expr q | q = e.(Call).getQualifier() | not q.(ThisExpr).isCompilerGenerated()) then result = normalizeExpr(e.(Call).getQualifier()) else - if forex(Expr q | q = e.(FieldAccess).getQualifier() | not q instanceof ThisExpr) + if forex(Expr q | q = e.(FieldAccess).getQualifier() | not q.(ThisExpr).isCompilerGenerated()) then result = normalizeExpr(e.(FieldAccess).getQualifier()) else if e.hasExplicitConversion() diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index b508d2e878e..e242bc23bbf 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -40,6 +40,10 @@ int Foo::test(int (*baz)(int)) (void)i, // GOOD (void)j; + if (i) + this->foo(i), // GOOD + foo(i); + if (i) (void)i, // BAD (void)j; From 891bc342bea9a00a61e97cccdcfd77457ddc403d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 18:42:23 +0200 Subject: [PATCH 019/164] C++: Fix another implicit/explicit this FP --- .../CommaBeforeMisleadingIndentation.ql | 27 +++++++++++++++++-- .../CommaBeforeMisleadingIndentation/test.cpp | 12 ++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index a54adc49cfe..1129d49d017 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -11,12 +11,35 @@ import cpp import semmle.code.cpp.commons.Exclusions +/** + * Holds if this is an implicit `this`. + * + * ThisExpr.isCompilerGenerated() is currently not being extracted, so use a heuristic. + */ +predicate isCompilerGenerated(ThisExpr te) { + exists( + string filepath, int line, int colStart, int colEnd, boolean zeroDiff, boolean sameLocAsCall + | + te.getLocation().hasLocationInfo(filepath, line, colStart, line, colEnd) and + (if colStart = colEnd then zeroDiff = true else zeroDiff = false) and + ( + if exists(Call c | c.getQualifier() = te | c.getLocation() = te.getLocation()) + then sameLocAsCall = true + else sameLocAsCall = false + ) + | + zeroDiff = true + or + zeroDiff = false and sameLocAsCall = true + ) +} + /** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { - if forex(Expr q | q = e.(Call).getQualifier() | not q.(ThisExpr).isCompilerGenerated()) + if forex(Expr q | q = e.(Call).getQualifier() | not isCompilerGenerated(q.(ThisExpr))) then result = normalizeExpr(e.(Call).getQualifier()) else - if forex(Expr q | q = e.(FieldAccess).getQualifier() | not q.(ThisExpr).isCompilerGenerated()) + if forex(Expr q | q = e.(FieldAccess).getQualifier() | not isCompilerGenerated(q.(ThisExpr))) then result = normalizeExpr(e.(FieldAccess).getQualifier()) else if e.hasExplicitConversion() diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp index e242bc23bbf..dbf792db338 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/test.cpp @@ -16,7 +16,7 @@ struct X { #define BAZ //printf struct Foo { - int i; + int i, i_array[3]; int j; virtual int foo(int) = 0; virtual int bar(int, int) = 0; @@ -27,9 +27,9 @@ struct Foo { void tutu() {} long toto() { return 42; } } titi; - } *tata; - Tata::Titi **titi_ptr_ptr; + Titi *operator->() { return &titi; } + } *tata; }; int Foo::test(int (*baz)(int)) @@ -38,7 +38,7 @@ int Foo::test(int (*baz)(int)) if (i) (void)i, // GOOD - (void)j; + j++; if (i) this->foo(i), // GOOD @@ -181,8 +181,8 @@ int Foo::test(int (*baz)(int)) (tata->titi.tutu(), foo(tata->titi.toto())); // GOOD - (*titi_ptr_ptr)->tutu(), // GOOD - (&i)[0] += (int)(*titi_ptr_ptr)->toto(); + (*tata)->toto(), // GOOD + i_array[i] += (int)(*tata)->toto(); return quux; } From dedd29e1b33bf69c3b102a26d6da5c84186b1021 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 14:05:18 -0400 Subject: [PATCH 020/164] Incomplete Android content provider permissions documentation --- ...ContentProviderIncompletePermissions.qhelp | 57 +++++++++++++++++++ ...ntentProviderIncompletePermissionsFull.xml | 12 ++++ ...tProviderIncompletePermissionsReadOnly.xml | 12 ++++ ...ProviderIncompletePermissionsReadWrite.xml | 13 +++++ ...ProviderIncompletePermissionsWriteOnly.xml | 12 ++++ 5 files changed, 106 insertions(+) create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml create mode 100644 java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp new file mode 100644 index 00000000000..b8b26696208 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp @@ -0,0 +1,57 @@ + + + +

In the Android manifest file, an application's provider elements + define the permissions necessary to access a resource using that provider. + Permissions are specified with + the android:readPermission, android:writePermission, + or android:permission attributes. If an application only + specifies the android:readPermission + or android:writePermission attribute, no permissions will be + required to do other operations. +

+ +

Content providers should either define both the read and write permissions +attributes, or define the general android:permission attribute.

+
+ + + To prevent permission bypass, provider elements should either + specify both the android:readPermission + and android:writePermission attributes, or specify + the android:permission attribute. + + + + +

In the following two (bad) examples, the provider is configured with only + read or write permissions.

+ + + + + +

In the following (good) examples, the provider is configured with full permissions.

+ + + + +
+ + +
  • + Android Documentation: + Provider element +
  • +
  • + CVE-2021-41166: Insufficient + permission control in Nextcloud Android app +
  • +
  • + GitHub Security Lab Research: + Insufficient permission control in Nextcloud Android app +
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml new file mode 100644 index 00000000000..95dbb0a92f3 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml new file mode 100644 index 00000000000..278dbb1bb0b --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml new file mode 100644 index 00000000000..1154c6e7534 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml new file mode 100644 index 00000000000..1428c6f1d03 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml @@ -0,0 +1,12 @@ + + + + + + + From e72963986fa352c6d4d9d0998df81b1f347cfa59 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 14:06:18 -0400 Subject: [PATCH 021/164] Moved Android manifest incomplete permission logic into library --- java/ql/lib/semmle/code/xml/AndroidManifest.qll | 11 +++++++++++ .../CWE-276/ContentProviderIncompletePermissions.ql | 11 +++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/xml/AndroidManifest.qll b/java/ql/lib/semmle/code/xml/AndroidManifest.qll index f53da67a650..22c4ca58f23 100644 --- a/java/ql/lib/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/lib/semmle/code/xml/AndroidManifest.qll @@ -180,6 +180,17 @@ class AndroidProviderXmlElement extends AndroidComponentXmlElement { attr.getValue() = "true" ) } + + /** + * Holds if the provider element provides only `android:readPermission` or `android:writePermission`. + */ + predicate hasIncompletePermissions() { + ( + this.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() or + this.getAnAttribute().(AndroidPermissionXmlAttribute).isRead() + ) and + not this.requiresPermissions() + } } /** diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql index 647b3b707c2..5d03dec32cd 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql @@ -15,9 +15,8 @@ import semmle.code.xml.AndroidManifest from AndroidProviderXmlElement provider where - ( - provider.getAnAttribute().(AndroidPermissionXmlAttribute).isWrite() or - provider.getAnAttribute().(AndroidPermissionXmlAttribute).isRead() - ) and - not provider.requiresPermissions() -select provider, "Incomplete permissions" + not provider.getFile().(AndroidManifestXmlFile).isInBuildDirectory() and + provider.isExported() and + provider.hasIncompletePermissions() +select provider, "Exported provider $@ has incomplete permissions.", provider, + provider.getResolvedComponentName() From f2bda1525aba3621ee0e5721581afbbea44c5232 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 14:43:18 -0400 Subject: [PATCH 022/164] Revert "Android ContentProvider.openFile does not check `mode` initital commit" This reverts commit e37f62bb5eb7aff3036c39169def3d50111ecc60. The MisconfiguedContentProviderUse.ql file provided a sample query which will be useful in future checks for CVE-2021-41166, but is not needed for the current manifest-focused check --- .../CWE-276/MisconfiguedContentProviderUse.ql | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql diff --git a/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql b/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql deleted file mode 100644 index 06c68403d53..00000000000 --- a/java/ql/src/Security/CWE/CWE-276/MisconfiguedContentProviderUse.ql +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @name Misconfigured ContentProvider use - * @description ContentProvider#openFile override which does not use `mode` argument. - * @kind problem - * @id java/android/misconfigured-content-provider - * @problem.severity warning - * @security-severity 7.8 - * @tags security external/cwe/cwe-276 - * @precision medium - */ - -import java - -class ContentProviderOpenFileMethod extends Method { - ContentProviderOpenFileMethod() { - this.hasName("openFile") and - this.getDeclaringType().getASupertype*().hasQualifiedName("android.content", "ContentProvider") - } - - predicate doesNotCheckMode() { - exists(Parameter p | p = this.getParameter(1) | not exists(p.getAnAccess())) - } -} - -from ContentProviderOpenFileMethod ofm -where ofm.doesNotCheckMode() -select ofm, "Open file" From 29e34ac970aa260f538f9352fc9b04197a61ae16 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 16:07:54 -0400 Subject: [PATCH 023/164] ContentProvider Incomplete Permissions Test Cases --- ...ProviderIncompletePermissionsTest.expected | 0 ...ontentProviderIncompletePermissionsTest.ql | 21 ++++++++++++++ .../TestFull/AndroidManifest.xml | 25 +++++++++++++++++ .../TestReadOnly/AndroidManifest.xml | 27 ++++++++++++++++++ .../TestReadWrite/AndroidManifest.xml | 28 +++++++++++++++++++ .../TestWriteOnly/AndroidManifest.xml | 27 ++++++++++++++++++ .../Testbuild/AndroidManifest.xml | 25 +++++++++++++++++ 7 files changed, 153 insertions(+) create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql new file mode 100644 index 00000000000..99312213752 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql @@ -0,0 +1,21 @@ +import java +import semmle.code.xml.AndroidManifest +import TestUtilities.InlineExpectationsTest + +class ContentProviderIncompletePermissionsTest extends InlineExpectationsTest { + ContentProviderIncompletePermissionsTest() { this = "ContentProviderIncompletePermissionsTest" } + + override string getARelevantTag() { result = "hasIncompletePermissions" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasIncompletePermissions" and + exists(AndroidProviderXmlElement provider | + provider.getLocation() = location and + provider.toString() = element and + value = "" + | + not provider.getFile().(AndroidManifestXmlFile).isInBuildDirectory() and + provider.hasIncompletePermissions() + ) + } +} diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml new file mode 100644 index 00000000000..f056b13311a --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml new file mode 100644 index 00000000000..2bdd26bd1b4 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml new file mode 100644 index 00000000000..720cbede958 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml new file mode 100644 index 00000000000..d95be29ade2 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml new file mode 100644 index 00000000000..61eca7c0825 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + From 90590429e3c398184d44586cf2ee60bda7a4a434 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 16:17:52 -0400 Subject: [PATCH 024/164] Added change note for ContentProvider query --- .../2022-09-29-contentprovider-incomplete-permissions.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2022-09-29-contentprovider-incomplete-permissions.md diff --git a/java/ql/lib/change-notes/2022-09-29-contentprovider-incomplete-permissions.md b/java/ql/lib/change-notes/2022-09-29-contentprovider-incomplete-permissions.md new file mode 100644 index 00000000000..db4da90e5e9 --- /dev/null +++ b/java/ql/lib/change-notes/2022-09-29-contentprovider-incomplete-permissions.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added a new predicate, `hasIncompletePermissions`, in the `AndroidProviderXmlElement` class. This predicate detects if a provider element does not provide both read and write permissions. From e3c0e6f52a8103d96c59b8fd6a1118869e5bd7d8 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 16:20:48 -0400 Subject: [PATCH 025/164] Remove location link from alert message Follow the style suggestion from the github-code-scanning bot and remove provider element from alert link --- .../CWE/CWE-276/ContentProviderIncompletePermissions.ql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql index 5d03dec32cd..33f452ea30f 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql @@ -18,5 +18,4 @@ where not provider.getFile().(AndroidManifestXmlFile).isInBuildDirectory() and provider.isExported() and provider.hasIncompletePermissions() -select provider, "Exported provider $@ has incomplete permissions.", provider, - provider.getResolvedComponentName() +select provider, "Exported provider has incomplete permissions." From 2a2878fc7bbb964a700a0793b485f82df5671185 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 29 Sep 2022 16:33:22 -0400 Subject: [PATCH 026/164] Move text into paragraph tag --- .../CWE/CWE-276/ContentProviderIncompletePermissions.qhelp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp index b8b26696208..9efb27d77b8 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp @@ -18,10 +18,11 @@ attributes, or define the general android:permission attribute.

    - To prevent permission bypass, provider elements should either +

    To prevent permission bypass, provider elements should either specify both the android:readPermission and android:writePermission attributes, or specify the android:permission attribute. +

    From 2a046352cee9002324ba87fa0ce7c69bd7933b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 23:06:17 +0200 Subject: [PATCH 027/164] C++: Simplify --- .../CommaBeforeMisleadingIndentation.ql | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 1129d49d017..d737f6a914f 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -17,20 +17,12 @@ import semmle.code.cpp.commons.Exclusions * ThisExpr.isCompilerGenerated() is currently not being extracted, so use a heuristic. */ predicate isCompilerGenerated(ThisExpr te) { - exists( - string filepath, int line, int colStart, int colEnd, boolean zeroDiff, boolean sameLocAsCall + exists(int line, int colStart, int colEnd | + te.getLocation().hasLocationInfo(_, line, colStart, line, colEnd) | - te.getLocation().hasLocationInfo(filepath, line, colStart, line, colEnd) and - (if colStart = colEnd then zeroDiff = true else zeroDiff = false) and - ( - if exists(Call c | c.getQualifier() = te | c.getLocation() = te.getLocation()) - then sameLocAsCall = true - else sameLocAsCall = false - ) - | - zeroDiff = true + colStart = colEnd or - zeroDiff = false and sameLocAsCall = true + exists(Call c | c.getQualifier() = te | c.getLocation() = te.getLocation()) ) } @@ -47,28 +39,18 @@ Expr normalizeExpr(Expr e) { else result = e } -predicate isInLoopHead(CommaExpr ce) { +predicate isParenthesized(CommaExpr ce) { + ce.getParent*().(Expr).isParenthesised() + or + ce.isUnevaluated() // sizeof(), decltype(), alignof(), noexcept(), typeid() + or + ce.getParent*() = any(IfStmt i).getCondition() + or ce.getParent*() = [any(Loop l).getCondition(), any(ForStmt f).getUpdate()] or ce.getEnclosingStmt() = any(ForStmt f).getInitialization() } -predicate isInDecltypeOrSizeof(CommaExpr ce) { - ce.getParent*() instanceof SizeofExprOperator - or - ce.getParent*() = any(Decltype d).getExpr() -} - -predicate isParenthesized(CommaExpr ce) { - isInLoopHead(ce) - or - isInDecltypeOrSizeof(ce) - or - ce.getParent*().(Expr).isParenthesised() - or - ce.getParent*() = any(IfStmt i).getCondition() -} - from CommaExpr ce, Expr left, Expr right, Location leftLoc, Location rightLoc where ce.fromSource() and From 68b473377ab5d74b6232eec959727465136d468f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 23:19:49 +0200 Subject: [PATCH 028/164] C++: Fix QL-on-QL Redundant Cast warning --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index d737f6a914f..30d4d68a41e 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -28,10 +28,10 @@ predicate isCompilerGenerated(ThisExpr te) { /** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { - if forex(Expr q | q = e.(Call).getQualifier() | not isCompilerGenerated(q.(ThisExpr))) + if forex(Expr q | q = e.(Call).getQualifier() | not isCompilerGenerated(q)) then result = normalizeExpr(e.(Call).getQualifier()) else - if forex(Expr q | q = e.(FieldAccess).getQualifier() | not isCompilerGenerated(q.(ThisExpr))) + if forex(Expr q | q = e.(FieldAccess).getQualifier() | not isCompilerGenerated(q)) then result = normalizeExpr(e.(FieldAccess).getQualifier()) else if e.hasExplicitConversion() From 981a9798b8a5af60ee69508623c6b69b78866034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Thu, 29 Sep 2022 23:59:22 +0200 Subject: [PATCH 029/164] C++: Update .qhelp with precision disclaimer. --- .../CommaBeforeMisleadingIndentation.qhelp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp index b54a0e4800a..8991ce31529 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -6,14 +6,21 @@

    If the expression to the right of a comma operator starts at an earlier column than the expression to the left, then -this suspicious indentation likely indicates a logic error caused by a typo that may escape visual inspection. +this suspicious indentation possibly indicates a logic error, caused by a typo that may escape visual inspection.

    + +This query has medium precision because CodeQL currently does not distinguish between tabs and spaces in whitespace. +Alerts may therefore flag code that appears readable for one value of tab size but not another. +

    Use standard indentation around the comma operator: begin the right-hand-side operand at the same level of -indentation as the left-hand-side operand. +indentation (column number) as the left-hand-side operand. +

    +

    +When it comes to whitespace, either do not mix tabs and spaces, or mix them consistently.

    From a124dcf43654ed6e851deb4e1a78ffaa646a8a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 00:06:53 +0200 Subject: [PATCH 030/164] C++: Update QLDoc Arguably warning, not just recommendation; it may be a logic error. TODO: What CWE/CVEs should I tag this with? --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 30d4d68a41e..d059e92d1c9 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -3,7 +3,8 @@ * @description The expressions before and after the comma operator can be misread because of an unusual difference in start columns. * @kind problem * @id cpp/comma-before-misleading-indentation - * @problem.severity recommendation + * @problem.severity warning + * @precision medium * @tags maintainability * readability */ From 6eac4f52d94f2d9bcfa943f888a3dbab3edfad39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 00:13:23 +0200 Subject: [PATCH 031/164] C++: Accept Test Output Some tricky FPs are preserved in there. --- .../CommaBeforeMisleadingIndentation.expected | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected index a977b9ce72f..93911c1d9bb 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected @@ -1,2 +1,5 @@ -| test.cpp:9:3:10:8 | ... , ... | Comma before misleading indentation. | -| test.cpp:17:7:18:4 | ... , ... | Comma before misleading indentation. | +| test.cpp:49:2:49:8 | (void)... | The indentation level may be misleading (for some tab sizes). | +| test.cpp:52:8:52:8 | x | The indentation level may be misleading (for some tab sizes). | +| test.cpp:160:3:160:9 | (void)... | The indentation level may be misleading (for some tab sizes). | +| test.cpp:166:5:166:7 | ... ++ | The indentation level may be misleading (for some tab sizes). | +| test.cpp:176:6:178:6 | ... ? ... : ... | The indentation level may be misleading (for some tab sizes). | From 818be2765e9dcf9303b74841051119543c1b51cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 00:28:12 +0200 Subject: [PATCH 032/164] C++: Add Change Note --- .../2022-09-30-comma-before-missing-indentation.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/src/change-notes/2022-09-30-comma-before-missing-indentation.md diff --git a/cpp/ql/src/change-notes/2022-09-30-comma-before-missing-indentation.md b/cpp/ql/src/change-notes/2022-09-30-comma-before-missing-indentation.md new file mode 100644 index 00000000000..dad3b0b3377 --- /dev/null +++ b/cpp/ql/src/change-notes/2022-09-30-comma-before-missing-indentation.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new medium-precision query, `cpp/comma-before-misleading-indentation`, which detects instances of whitespace that have readability issues. From 4938de9185ef1ab9d9dda84c33191eaa670329d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 12:28:18 +0200 Subject: [PATCH 033/164] C++: Fix docstring per suggestion Co-authored-by: Mathias Vorreiter Pedersen --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index d059e92d1c9..c3bde8c3e6e 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -13,7 +13,7 @@ import cpp import semmle.code.cpp.commons.Exclusions /** - * Holds if this is an implicit `this`. + * Holds if `te` is an implicit `this`. * * ThisExpr.isCompilerGenerated() is currently not being extracted, so use a heuristic. */ From 9a94222dbec29f13bfed9642f0408ce1fea90a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 12:31:55 +0200 Subject: [PATCH 034/164] C++: Exclude commas from SwitchStmt.getExpr() --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index c3bde8c3e6e..66446a5dce8 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -45,7 +45,7 @@ predicate isParenthesized(CommaExpr ce) { or ce.isUnevaluated() // sizeof(), decltype(), alignof(), noexcept(), typeid() or - ce.getParent*() = any(IfStmt i).getCondition() + ce.getParent*() = [any(IfStmt i).getCondition(), any(SwitchStmt s).getExpr()] or ce.getParent*() = [any(Loop l).getCondition(), any(ForStmt f).getUpdate()] or From 28606c561d6e69d1d2a93bb6ddc35174bf632bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Fri, 30 Sep 2022 14:35:54 +0200 Subject: [PATCH 035/164] C++: Simplify normalizeExpr This has a comparable but different set of FPs as the previous version. But arguably it's an improvement. --- .../CommaBeforeMisleadingIndentation.ql | 31 +++++-------------- .../CommaBeforeMisleadingIndentation.expected | 2 +- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 66446a5dce8..35ab00a8fdd 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -12,32 +12,15 @@ import cpp import semmle.code.cpp.commons.Exclusions -/** - * Holds if `te` is an implicit `this`. - * - * ThisExpr.isCompilerGenerated() is currently not being extracted, so use a heuristic. - */ -predicate isCompilerGenerated(ThisExpr te) { - exists(int line, int colStart, int colEnd | - te.getLocation().hasLocationInfo(_, line, colStart, line, colEnd) - | - colStart = colEnd - or - exists(Call c | c.getQualifier() = te | c.getLocation() = te.getLocation()) - ) -} - /** Gets the sub-expression of 'e' with the earliest-starting Location */ Expr normalizeExpr(Expr e) { - if forex(Expr q | q = e.(Call).getQualifier() | not isCompilerGenerated(q)) - then result = normalizeExpr(e.(Call).getQualifier()) - else - if forex(Expr q | q = e.(FieldAccess).getQualifier() | not isCompilerGenerated(q)) - then result = normalizeExpr(e.(FieldAccess).getQualifier()) - else - if e.hasExplicitConversion() - then result = normalizeExpr(e.getFullyConverted()) - else result = e + result = + min(Expr child | + child.getParentWithConversions*() = e.getFullyConverted() and + not child.getParentWithConversions*() = any(Call c).getAnArgument() + | + child order by child.getLocation().getStartColumn(), count(child.getParentWithConversions*()) + ) } predicate isParenthesized(CommaExpr ce) { diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected index 93911c1d9bb..0cc6e7f4fc4 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected @@ -1,5 +1,5 @@ | test.cpp:49:2:49:8 | (void)... | The indentation level may be misleading (for some tab sizes). | -| test.cpp:52:8:52:8 | x | The indentation level may be misleading (for some tab sizes). | +| test.cpp:52:2:52:15 | (void)... | The indentation level may be misleading (for some tab sizes). | | test.cpp:160:3:160:9 | (void)... | The indentation level may be misleading (for some tab sizes). | | test.cpp:166:5:166:7 | ... ++ | The indentation level may be misleading (for some tab sizes). | | test.cpp:176:6:178:6 | ... ? ... : ... | The indentation level may be misleading (for some tab sizes). | From 28e70497225a12d8d72025105afaa8d90bb833cf Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 3 Oct 2022 10:52:42 -0400 Subject: [PATCH 036/164] Add exported requirement to ContentProvider permissions test --- .../ContentProviderIncompletePermissionsTest.ql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql index 99312213752..9ba691685eb 100644 --- a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql @@ -15,7 +15,8 @@ class ContentProviderIncompletePermissionsTest extends InlineExpectationsTest { value = "" | not provider.getFile().(AndroidManifestXmlFile).isInBuildDirectory() and - provider.hasIncompletePermissions() + provider.hasIncompletePermissions() and + provider.isExported() ) } } From cfc0bb595f81b599d04c29743c14a6c2a345cc8b Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Mon, 3 Oct 2022 11:20:15 -0400 Subject: [PATCH 037/164] Documentation fix for `hasIncompletePermissions` Co-authored-by: Tony Torralba --- java/ql/lib/semmle/code/xml/AndroidManifest.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/xml/AndroidManifest.qll b/java/ql/lib/semmle/code/xml/AndroidManifest.qll index 22c4ca58f23..c18b32751ed 100644 --- a/java/ql/lib/semmle/code/xml/AndroidManifest.qll +++ b/java/ql/lib/semmle/code/xml/AndroidManifest.qll @@ -182,7 +182,7 @@ class AndroidProviderXmlElement extends AndroidComponentXmlElement { } /** - * Holds if the provider element provides only `android:readPermission` or `android:writePermission`. + * Holds if the provider element is only protected by either `android:readPermission` or `android:writePermission`. */ predicate hasIncompletePermissions() { ( From 2970e8c76a48236e5b6c6f0dfc6f76ad06168911 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Mon, 3 Oct 2022 11:21:02 -0400 Subject: [PATCH 038/164] Remove redundant documentation Co-authored-by: Jami <57204504+jcogs33@users.noreply.github.com> --- .../CWE/CWE-276/ContentProviderIncompletePermissions.qhelp | 2 -- 1 file changed, 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp index 9efb27d77b8..c615a7c13ca 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp @@ -13,8 +13,6 @@ required to do other operations.

    -

    Content providers should either define both the read and write permissions -attributes, or define the general android:permission attribute.

    From 071f082b647c9b284656eeedb6692b478a9d1910 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Mon, 3 Oct 2022 11:21:33 -0400 Subject: [PATCH 039/164] Add mention of content provider in query description Co-authored-by: Tony Torralba --- .../CWE/CWE-276/ContentProviderIncompletePermissions.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql index 33f452ea30f..4a6c75febeb 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql @@ -1,5 +1,5 @@ /** - * @name Missing read or write permission configuration + * @name Missing read or write permission in a content provider * @description Defining an incomplete set of permissions * @kind problem * @problem.severity warning From 09077935b170e6588527bada2bfd54f18758c7f1 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 3 Oct 2022 11:30:43 -0400 Subject: [PATCH 040/164] Added query change note --- .../2022-09-29-contentprovider-incomplete-permissions.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/src/change-notes/2022-09-29-contentprovider-incomplete-permissions.md diff --git a/java/ql/src/change-notes/2022-09-29-contentprovider-incomplete-permissions.md b/java/ql/src/change-notes/2022-09-29-contentprovider-incomplete-permissions.md new file mode 100644 index 00000000000..bdbd092f037 --- /dev/null +++ b/java/ql/src/change-notes/2022-09-29-contentprovider-incomplete-permissions.md @@ -0,0 +1,4 @@ +--- +category: newQuery +--- +* Added a new query, `java/android/incomplete-provider-permissions`, to detect if an Android ContentProvider is not protected with a correct set of permissions. From 52d519765a3aea5cb32aee64eee22c60433488d4 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 3 Oct 2022 12:16:45 -0400 Subject: [PATCH 041/164] Merge ContentProvider tests into one manifest Merge the read-only, write-only, read-write, and full test cases into one AndroidManifest.xml file. Also added the not-exported test case. --- .../AndroidManifest.xml | 67 +++++++++++++++++++ .../TestFull/AndroidManifest.xml | 25 ------- .../TestReadOnly/AndroidManifest.xml | 27 -------- .../TestReadWrite/AndroidManifest.xml | 28 -------- .../TestWriteOnly/AndroidManifest.xml | 27 -------- 5 files changed, 67 insertions(+), 107 deletions(-) create mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml delete mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml delete mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml delete mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml delete mode 100644 java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml new file mode 100644 index 00000000000..928dc72a665 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml deleted file mode 100644 index f056b13311a..00000000000 --- a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestFull/AndroidManifest.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml deleted file mode 100644 index 2bdd26bd1b4..00000000000 --- a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadOnly/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml deleted file mode 100644 index 720cbede958..00000000000 --- a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestReadWrite/AndroidManifest.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml deleted file mode 100644 index d95be29ade2..00000000000 --- a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/TestWriteOnly/AndroidManifest.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - From c6f91500f044cb6600be8f3a0ab11dea86116101 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 3 Oct 2022 13:12:53 -0400 Subject: [PATCH 042/164] Update query description to better describe issue --- .../CWE/CWE-276/ContentProviderIncompletePermissions.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql index 4a6c75febeb..9e57ccfddfb 100644 --- a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql @@ -1,6 +1,6 @@ /** * @name Missing read or write permission in a content provider - * @description Defining an incomplete set of permissions + * @description Android content providers which do not configure both read and write permissions can allow permission bypass * @kind problem * @problem.severity warning * @security-severity 7.8 From 2bbfdcf5985d743146a1b9be96477f2006ef392a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 4 Oct 2022 13:51:35 +0200 Subject: [PATCH 043/164] C#: Use api info string ordering and results to avoid multiplicity issues. --- csharp/ql/src/Telemetry/ExternalApi.qll | 22 +++++++++---------- .../src/Telemetry/SupportedExternalSinks.ql | 18 +++++++++------ .../src/Telemetry/SupportedExternalSources.ql | 18 +++++++++------ .../src/Telemetry/SupportedExternalTaint.ql | 18 +++++++++------ .../src/Telemetry/UnsupportedExternalAPIs.ql | 20 ++++++++++------- 5 files changed, 56 insertions(+), 40 deletions(-) diff --git a/csharp/ql/src/Telemetry/ExternalApi.qll b/csharp/ql/src/Telemetry/ExternalApi.qll index 685eda64e50..4f261aa0df8 100644 --- a/csharp/ql/src/Telemetry/ExternalApi.qll +++ b/csharp/ql/src/Telemetry/ExternalApi.qll @@ -114,29 +114,29 @@ class ExternalApi extends DotNet::Callable { int resultLimit() { result = 1000 } /** - * Holds if the relevant usage count of `api` is `usages`. + * Holds if the relevant usage count of api with `apiInfo` is `usages`. */ -signature predicate relevantUsagesSig(ExternalApi api, int usages); +signature predicate relevantUsagesSig(string apiInfo, int usages); /** * Given a predicate to count relevant API usages, this module provides a predicate * for restricting the number or returned results based on a certain limit. */ module Results { - private int getOrder(ExternalApi api) { - api = - rank[result](ExternalApi a, int usages | - getRelevantUsages(a, usages) + private int getOrder(string apiInfo) { + apiInfo = + rank[result](string info, int usages | + getRelevantUsages(info, usages) | - a order by usages desc, a.getInfo() + info order by usages desc, info ) } /** - * Holds if `api` is being used `usages` times and if it is - * in the top results (guarded by resultLimit). + * Holds if there exists an API with `apiInfo` that is being used `usages` times + * and if it is in the top results (guarded by resultLimit). */ - predicate restrict(ExternalApi api, int usages) { - getRelevantUsages(api, usages) and getOrder(api) <= resultLimit() + predicate restrict(string apiInfo, int usages) { + getRelevantUsages(apiInfo, usages) and getOrder(apiInfo) <= resultLimit() } } diff --git a/csharp/ql/src/Telemetry/SupportedExternalSinks.ql b/csharp/ql/src/Telemetry/SupportedExternalSinks.ql index 74d36bc4cec..c09d438073e 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalSinks.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalSinks.ql @@ -10,12 +10,16 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { - not api.isUninteresting() and - api.isSink() and - usages = strictcount(DispatchCall c | c = api.getACall()) +private predicate getRelevantUsages(string apiInfo, int usages) { + usages = + strictcount(DispatchCall c, ExternalApi api | + apiInfo = api.getInfo() and + c = api.getACall() and + not api.isUninteresting() and + api.isSink() + ) } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getInfo() as info, usages order by usages desc +from string info, int usages +where Results::restrict(info, usages) +select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/SupportedExternalSources.ql b/csharp/ql/src/Telemetry/SupportedExternalSources.ql index 9e57adb9b22..6bd3dc1376e 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalSources.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalSources.ql @@ -10,12 +10,16 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { - not api.isUninteresting() and - api.isSource() and - usages = strictcount(DispatchCall c | c = api.getACall()) +private predicate getRelevantUsages(string apiInfo, int usages) { + usages = + strictcount(DispatchCall c, ExternalApi api | + c = api.getACall() and + apiInfo = api.getInfo() and + not api.isUninteresting() and + api.isSource() + ) } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getInfo() as info, usages order by usages desc +from string info, int usages +where Results::restrict(info, usages) +select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/SupportedExternalTaint.ql b/csharp/ql/src/Telemetry/SupportedExternalTaint.ql index 5e8a816b3f6..29ae9571e62 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalTaint.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalTaint.ql @@ -10,12 +10,16 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { - not api.isUninteresting() and - api.hasSummary() and - usages = strictcount(DispatchCall c | c = api.getACall()) +private predicate getRelevantUsages(string apiInfo, int usages) { + usages = + strictcount(DispatchCall c, ExternalApi api | + apiInfo = api.getInfo() and + c = api.getACall() and + not api.isUninteresting() and + api.hasSummary() + ) } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getInfo() as info, usages order by usages desc +from string info, int usages +where Results::restrict(info, usages) +select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql index 69b8793abc1..864d5bfdcc0 100644 --- a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -12,13 +12,17 @@ private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSumma private import semmle.code.csharp.dataflow.internal.NegativeSummary private import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { - not api.isUninteresting() and - not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable and - usages = strictcount(DispatchCall c | c = api.getACall()) +private predicate getRelevantUsages(string apiInfo, int usages) { + usages = + strictcount(DispatchCall c, ExternalApi api | + apiInfo = api.getInfo() and + c = api.getACall() and + not api.isUninteresting() and + not api.isSupported() and + not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable + ) } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getInfo() as info, usages order by usages desc +from string info, int usages +where Results::restrict(info, usages) +select info, usages order by usages desc From 3455dd5e06b006a11ecf5b670db99e8b3d6b632b Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 4 Oct 2022 14:13:50 +0200 Subject: [PATCH 044/164] C#: Re-factor telemetry queries to avoid code duplication. --- csharp/ql/src/Telemetry/ExternalApi.qll | 20 ++++++++++++++----- .../src/Telemetry/SupportedExternalSinks.ql | 13 ++++-------- .../src/Telemetry/SupportedExternalSources.ql | 13 ++++-------- .../src/Telemetry/SupportedExternalTaint.ql | 13 ++++-------- .../src/Telemetry/UnsupportedExternalAPIs.ql | 15 +++++--------- 5 files changed, 32 insertions(+), 42 deletions(-) diff --git a/csharp/ql/src/Telemetry/ExternalApi.qll b/csharp/ql/src/Telemetry/ExternalApi.qll index 4f261aa0df8..0106ef99315 100644 --- a/csharp/ql/src/Telemetry/ExternalApi.qll +++ b/csharp/ql/src/Telemetry/ExternalApi.qll @@ -114,19 +114,28 @@ class ExternalApi extends DotNet::Callable { int resultLimit() { result = 1000 } /** - * Holds if the relevant usage count of api with `apiInfo` is `usages`. + * Holds if it is relevant to count usages of `api`. */ -signature predicate relevantUsagesSig(string apiInfo, int usages); +signature predicate relevantApi(ExternalApi api); /** * Given a predicate to count relevant API usages, this module provides a predicate * for restricting the number or returned results based on a certain limit. */ -module Results { +module Results { + private int getUsages(string apiInfo) { + result = + strictcount(DispatchCall c, ExternalApi api | + c = api.getACall() and + apiInfo = api.getInfo() and + getRelevantUsages(api) + ) + } + private int getOrder(string apiInfo) { apiInfo = rank[result](string info, int usages | - getRelevantUsages(info, usages) + usages = getUsages(info) | info order by usages desc, info ) @@ -137,6 +146,7 @@ module Results { * and if it is in the top results (guarded by resultLimit). */ predicate restrict(string apiInfo, int usages) { - getRelevantUsages(apiInfo, usages) and getOrder(apiInfo) <= resultLimit() + usages = getUsages(apiInfo) and + getOrder(apiInfo) <= resultLimit() } } diff --git a/csharp/ql/src/Telemetry/SupportedExternalSinks.ql b/csharp/ql/src/Telemetry/SupportedExternalSinks.ql index c09d438073e..4eb42c4628f 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalSinks.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalSinks.ql @@ -10,16 +10,11 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(string apiInfo, int usages) { - usages = - strictcount(DispatchCall c, ExternalApi api | - apiInfo = api.getInfo() and - c = api.getACall() and - not api.isUninteresting() and - api.isSink() - ) +private predicate relevant(ExternalApi api) { + not api.isUninteresting() and + api.isSink() } from string info, int usages -where Results::restrict(info, usages) +where Results::restrict(info, usages) select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/SupportedExternalSources.ql b/csharp/ql/src/Telemetry/SupportedExternalSources.ql index 6bd3dc1376e..0d0b38a4754 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalSources.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalSources.ql @@ -10,16 +10,11 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(string apiInfo, int usages) { - usages = - strictcount(DispatchCall c, ExternalApi api | - c = api.getACall() and - apiInfo = api.getInfo() and - not api.isUninteresting() and - api.isSource() - ) +private predicate relevant(ExternalApi api) { + not api.isUninteresting() and + api.isSource() } from string info, int usages -where Results::restrict(info, usages) +where Results::restrict(info, usages) select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/SupportedExternalTaint.ql b/csharp/ql/src/Telemetry/SupportedExternalTaint.ql index 29ae9571e62..3eccf73b58b 100644 --- a/csharp/ql/src/Telemetry/SupportedExternalTaint.ql +++ b/csharp/ql/src/Telemetry/SupportedExternalTaint.ql @@ -10,16 +10,11 @@ private import csharp private import semmle.code.csharp.dispatch.Dispatch private import ExternalApi -private predicate getRelevantUsages(string apiInfo, int usages) { - usages = - strictcount(DispatchCall c, ExternalApi api | - apiInfo = api.getInfo() and - c = api.getACall() and - not api.isUninteresting() and - api.hasSummary() - ) +private predicate relevant(ExternalApi api) { + not api.isUninteresting() and + api.hasSummary() } from string info, int usages -where Results::restrict(info, usages) +where Results::restrict(info, usages) select info, usages order by usages desc diff --git a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql index 864d5bfdcc0..4823a4e2dbc 100644 --- a/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/csharp/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -12,17 +12,12 @@ private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSumma private import semmle.code.csharp.dataflow.internal.NegativeSummary private import ExternalApi -private predicate getRelevantUsages(string apiInfo, int usages) { - usages = - strictcount(DispatchCall c, ExternalApi api | - apiInfo = api.getInfo() and - c = api.getACall() and - not api.isUninteresting() and - not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable - ) +private predicate relevant(ExternalApi api) { + not api.isUninteresting() and + not api.isSupported() and + not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable } from string info, int usages -where Results::restrict(info, usages) +where Results::restrict(info, usages) select info, usages order by usages desc From 6c6b4ce13138270904c7a0f820613ca21afa7654 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 4 Oct 2022 14:58:37 +0200 Subject: [PATCH 045/164] C#: Fix issue with TestLibraries not being excluded in the Telemetry queries and add Moq as a testlibrary. --- csharp/ql/src/Telemetry/ExternalApi.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/csharp/ql/src/Telemetry/ExternalApi.qll b/csharp/ql/src/Telemetry/ExternalApi.qll index 0106ef99315..d4cc0ae43cc 100644 --- a/csharp/ql/src/Telemetry/ExternalApi.qll +++ b/csharp/ql/src/Telemetry/ExternalApi.qll @@ -17,8 +17,10 @@ private import semmle.code.csharp.security.dataflow.flowsources.Remote class TestLibrary extends RefType { TestLibrary() { this.getNamespace() - .getName() - .matches(["NUnit.Framework%", "Xunit%", "Microsoft.VisualStudio.TestTools.UnitTesting%"]) + .getQualifiedName() + .matches([ + "NUnit.Framework%", "Xunit%", "Microsoft.VisualStudio.TestTools.UnitTesting%", "Moq%" + ]) } } From 52d2dd71c0a7641687931fd9d750c6730ab19d73 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 4 Oct 2022 15:16:21 +0200 Subject: [PATCH 046/164] Java: Make equivalent fix to the telemetry queries as made for C#. --- java/ql/src/Telemetry/ExternalApi.qll | 35 ++++++++++++------- .../src/Telemetry/SupportedExternalSinks.ql | 15 +++----- .../src/Telemetry/SupportedExternalSources.ql | 15 +++----- .../src/Telemetry/SupportedExternalTaint.ql | 15 +++----- .../src/Telemetry/UnsupportedExternalAPIs.ql | 15 +++----- 5 files changed, 43 insertions(+), 52 deletions(-) diff --git a/java/ql/src/Telemetry/ExternalApi.qll b/java/ql/src/Telemetry/ExternalApi.qll index eaf88555444..48252515987 100644 --- a/java/ql/src/Telemetry/ExternalApi.qll +++ b/java/ql/src/Telemetry/ExternalApi.qll @@ -105,29 +105,40 @@ deprecated class ExternalAPI = ExternalApi; int resultLimit() { result = 1000 } /** - * Holds if the relevant usage count of `api` is `usages`. + * Holds if it is relevant to count usages of `api`. */ -signature predicate relevantUsagesSig(ExternalApi api, int usages); +signature predicate relevantApi(ExternalApi api); /** * Given a predicate to count relevant API usages, this module provides a predicate * for restricting the number or returned results based on a certain limit. */ -module Results { - private int getOrder(ExternalApi api) { - api = - rank[result](ExternalApi a, int usages | - getRelevantUsages(a, usages) +module Results { + private int getUsages(string apiName) { + result = + strictcount(Call c, ExternalApi api | + c.getCallee().getSourceDeclaration() = api and + not c.getFile() instanceof GeneratedFile and + apiName = api.getApiName() and + getRelevantUsages(api) + ) + } + + private int getOrder(string apiInfo) { + apiInfo = + rank[result](string info, int usages | + usages = getUsages(info) | - a order by usages desc, a.getApiName() + info order by usages desc, info ) } /** - * Holds if `api` is being used `usages` times and if it is - * in the top results (guarded by resultLimit). + * Holds if there exists an API with `apiName` that is being used `usages` times + * and if it is in the top results (guarded by resultLimit). */ - predicate restrict(ExternalApi api, int usages) { - getRelevantUsages(api, usages) and getOrder(api) <= resultLimit() + predicate restrict(string apiName, int usages) { + usages = getUsages(apiName) and + getOrder(apiName) <= resultLimit() } } diff --git a/java/ql/src/Telemetry/SupportedExternalSinks.ql b/java/ql/src/Telemetry/SupportedExternalSinks.ql index 26bdc4a4ba3..7593adeed2a 100644 --- a/java/ql/src/Telemetry/SupportedExternalSinks.ql +++ b/java/ql/src/Telemetry/SupportedExternalSinks.ql @@ -9,16 +9,11 @@ import java import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { +private predicate relevant(ExternalApi api) { not api.isUninteresting() and - api.isSink() and - usages = - strictcount(Call c | - c.getCallee().getSourceDeclaration() = api and - not c.getFile() instanceof GeneratedFile - ) + api.isSink() } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getApiName() as apiname, usages order by usages desc +from string apiName, int usages +where Results::restrict(apiName, usages) +select apiName, usages order by usages desc diff --git a/java/ql/src/Telemetry/SupportedExternalSources.ql b/java/ql/src/Telemetry/SupportedExternalSources.ql index 3708e6ffbdb..89f9b37cb55 100644 --- a/java/ql/src/Telemetry/SupportedExternalSources.ql +++ b/java/ql/src/Telemetry/SupportedExternalSources.ql @@ -9,16 +9,11 @@ import java import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { +private predicate relevant(ExternalApi api) { not api.isUninteresting() and - api.isSource() and - usages = - strictcount(Call c | - c.getCallee().getSourceDeclaration() = api and - not c.getFile() instanceof GeneratedFile - ) + api.isSource() } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getApiName() as apiname, usages order by usages desc +from string apiName, int usages +where Results::restrict(apiName, usages) +select apiName, usages order by usages desc diff --git a/java/ql/src/Telemetry/SupportedExternalTaint.ql b/java/ql/src/Telemetry/SupportedExternalTaint.ql index f6e651204cf..3f995138812 100644 --- a/java/ql/src/Telemetry/SupportedExternalTaint.ql +++ b/java/ql/src/Telemetry/SupportedExternalTaint.ql @@ -9,16 +9,11 @@ import java import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { +private predicate relevant(ExternalApi api) { not api.isUninteresting() and - api.hasSummary() and - usages = - strictcount(Call c | - c.getCallee().getSourceDeclaration() = api and - not c.getFile() instanceof GeneratedFile - ) + api.hasSummary() } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getApiName() as apiname, usages order by usages desc +from string apiName, int usages +where Results::restrict(apiName, usages) +select apiName, usages order by usages desc diff --git a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql index a6666637f16..b87f4a0e052 100644 --- a/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql +++ b/java/ql/src/Telemetry/UnsupportedExternalAPIs.ql @@ -11,17 +11,12 @@ import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl import semmle.code.java.dataflow.internal.NegativeSummary import ExternalApi -private predicate getRelevantUsages(ExternalApi api, int usages) { +private predicate relevant(ExternalApi api) { not api.isUninteresting() and not api.isSupported() and - not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable and - usages = - strictcount(Call c | - c.getCallee().getSourceDeclaration() = api and - not c.getFile() instanceof GeneratedFile - ) + not api instanceof FlowSummaryImpl::Public::NegativeSummarizedCallable } -from ExternalApi api, int usages -where Results::restrict(api, usages) -select api.getApiName() as apiname, usages order by usages desc +from string apiName, int usages +where Results::restrict(apiName, usages) +select apiName, usages order by usages desc From f888c4b279c4e27fb7003d298894cd03fca1314f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 4 Oct 2022 10:40:34 -0400 Subject: [PATCH 047/164] Move files from CWE-276 to CWE-926 --- .../ContentProviderIncompletePermissions.qhelp | 0 .../{CWE-276 => CWE-926}/ContentProviderIncompletePermissions.ql | 0 .../ContentProviderIncompletePermissionsFull.xml | 0 .../ContentProviderIncompletePermissionsReadOnly.xml | 0 .../ContentProviderIncompletePermissionsReadWrite.xml | 0 .../ContentProviderIncompletePermissionsWriteOnly.xml | 0 .../incomplete_provider_permissions/AndroidManifest.xml | 0 .../ContentProviderIncompletePermissionsTest.expected | 0 .../ContentProviderIncompletePermissionsTest.ql | 0 .../incomplete_provider_permissions/Testbuild/AndroidManifest.xml | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissions.qhelp (100%) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissions.ql (100%) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissionsFull.xml (100%) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissionsReadOnly.xml (100%) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissionsReadWrite.xml (100%) rename java/ql/src/Security/CWE/{CWE-276 => CWE-926}/ContentProviderIncompletePermissionsWriteOnly.xml (100%) rename java/ql/test/query-tests/security/{CWE-276/android => CWE-926}/incomplete_provider_permissions/AndroidManifest.xml (100%) rename java/ql/test/query-tests/security/{CWE-276/android => CWE-926}/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected (100%) rename java/ql/test/query-tests/security/{CWE-276/android => CWE-926}/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql (100%) rename java/ql/test/query-tests/security/{CWE-276/android => CWE-926}/incomplete_provider_permissions/Testbuild/AndroidManifest.xml (100%) diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.qhelp rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissions.ql rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsFull.xml similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsFull.xml rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsFull.xml diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsReadOnly.xml similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadOnly.xml rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsReadOnly.xml diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsReadWrite.xml similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsReadWrite.xml rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsReadWrite.xml diff --git a/java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsWriteOnly.xml similarity index 100% rename from java/ql/src/Security/CWE/CWE-276/ContentProviderIncompletePermissionsWriteOnly.xml rename to java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissionsWriteOnly.xml diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml similarity index 100% rename from java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/AndroidManifest.xml rename to java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/AndroidManifest.xml diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected similarity index 100% rename from java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected rename to java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.expected diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql similarity index 100% rename from java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql rename to java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/ContentProviderIncompletePermissionsTest.ql diff --git a/java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml b/java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/Testbuild/AndroidManifest.xml similarity index 100% rename from java/ql/test/query-tests/security/CWE-276/android/incomplete_provider_permissions/Testbuild/AndroidManifest.xml rename to java/ql/test/query-tests/security/CWE-926/incomplete_provider_permissions/Testbuild/AndroidManifest.xml From 3c7f5420dbdc42a62a2f7ee23a197f9c4856fabb Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 4 Oct 2022 10:48:05 -0400 Subject: [PATCH 048/164] Update metadata to match CWE-926 --- .../CWE/CWE-926/ContentProviderIncompletePermissions.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql index 9e57ccfddfb..d625fa211fc 100644 --- a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql @@ -3,10 +3,10 @@ * @description Android content providers which do not configure both read and write permissions can allow permission bypass * @kind problem * @problem.severity warning - * @security-severity 7.8 + * @security-severity 8.2 * @id java/android/incomplete-provider-permissions * @tags security - * external/cwe/cwe-276 + * external/cwe/cwe-926 * @precision medium */ From d8cfdc5e267019450c736bf7e0327bdcd67ea63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 5 Oct 2022 00:04:56 +0200 Subject: [PATCH 049/164] C++: Tag with CWE-1078, CWE-670 --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 35ab00a8fdd..965894ba87d 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -4,9 +4,13 @@ * @kind problem * @id cpp/comma-before-misleading-indentation * @problem.severity warning + * @security-severity 7.8 * @precision medium * @tags maintainability * readability + * security + * external/cwe/cwe-1078 + * external/cwe/cwe-670 */ import cpp From 61a05c2b6cea797cdb10b58c971fd5ed5d6ee84a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 5 Oct 2022 15:25:11 +0200 Subject: [PATCH 050/164] Kotlin: add `lateinit` declarations to modifiers test --- .../kotlin/library-tests/modifiers/modifiers.expected | 8 ++++++++ java/ql/test/kotlin/library-tests/modifiers/modifiers.kt | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected index b6b3a649593..96f54eaadad 100644 --- a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected +++ b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected @@ -45,3 +45,11 @@ | modifiers.kt:27:12:27:49 | fn5 | Method | inline | | modifiers.kt:27:12:27:49 | fn5 | Method | public | | modifiers.kt:27:20:27:44 | f | Parameter | crossinline | +| modifiers.kt:30:1:36:1 | LateInit | Class | final | +| modifiers.kt:30:1:36:1 | LateInit | Class | public | +| modifiers.kt:30:8:36:1 | LateInit | Constructor | public | +| modifiers.kt:31:5:31:40 | test0 | Field | private | +| modifiers.kt:31:5:31:40 | test0 | Property | private | +| modifiers.kt:31:22:31:40 | getTest0$private | Method | private | +| modifiers.kt:31:22:31:40 | setTest0$private | Method | private | +| modifiers.kt:33:5:35:5 | fn | Method | public | diff --git a/java/ql/test/kotlin/library-tests/modifiers/modifiers.kt b/java/ql/test/kotlin/library-tests/modifiers/modifiers.kt index 695ab23e66c..14f66021047 100644 --- a/java/ql/test/kotlin/library-tests/modifiers/modifiers.kt +++ b/java/ql/test/kotlin/library-tests/modifiers/modifiers.kt @@ -26,3 +26,11 @@ open class X { inline fun fn4(noinline f: () -> Unit) { } inline fun fn5(crossinline f: () -> Unit) { } } + +public class LateInit { + private lateinit var test0: LateInit + + fun fn() { + lateinit var test1: LateInit + } +} \ No newline at end of file From 082544e88c598c1354cf48bebb0d210cf583e8f4 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 5 Oct 2022 15:25:45 +0200 Subject: [PATCH 051/164] Kotlin: Extract `lateinit` modifier --- .../src/main/kotlin/KotlinFileExtractor.kt | 7 +++++++ java/ql/lib/semmle/code/java/Modifier.qll | 7 +++++-- .../test/kotlin/library-tests/modifiers/modifiers.expected | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index b7aff59b599..049e6d28e48 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1141,6 +1141,10 @@ open class KotlinFileExtractor( } extractVisibility(p, id, p.visibility) + + if (p.isLateinit) { + addModifiers(id, "lateinit") + } } } } @@ -1291,6 +1295,9 @@ open class KotlinFileExtractor( if (!v.isVar) { addModifiers(varId, "final") } + if (v.isLateinit) { + addModifiers(varId, "lateinit") + } } } diff --git a/java/ql/lib/semmle/code/java/Modifier.qll b/java/ql/lib/semmle/code/java/Modifier.qll index 64c0cd6ec9d..7dbd4d90726 100644 --- a/java/ql/lib/semmle/code/java/Modifier.qll +++ b/java/ql/lib/semmle/code/java/Modifier.qll @@ -67,10 +67,10 @@ abstract class Modifiable extends Element { /** Holds if this element has an `inline` modifier. */ predicate isInline() { this.hasModifier("inline") } - /** Holds if this element has an `noinline` modifier. */ + /** Holds if this element has a `noinline` modifier. */ predicate isNoinline() { this.hasModifier("noinline") } - /** Holds if this element has an `crossinline` modifier. */ + /** Holds if this element has a `crossinline` modifier. */ predicate isCrossinline() { this.hasModifier("crossinline") } /** Holds if this element has a `suspend` modifier. */ @@ -93,4 +93,7 @@ abstract class Modifiable extends Element { /** Holds if this element has a `strictfp` modifier. */ predicate isStrictfp() { this.hasModifier("strictfp") } + + /** Holds if this element has a `lateinit` modifier. */ + predicate isLateinit() { this.hasModifier("lateinit") } } diff --git a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected index 96f54eaadad..572423554e9 100644 --- a/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected +++ b/java/ql/test/kotlin/library-tests/modifiers/modifiers.expected @@ -49,7 +49,9 @@ | modifiers.kt:30:1:36:1 | LateInit | Class | public | | modifiers.kt:30:8:36:1 | LateInit | Constructor | public | | modifiers.kt:31:5:31:40 | test0 | Field | private | +| modifiers.kt:31:5:31:40 | test0 | Property | lateinit | | modifiers.kt:31:5:31:40 | test0 | Property | private | | modifiers.kt:31:22:31:40 | getTest0$private | Method | private | | modifiers.kt:31:22:31:40 | setTest0$private | Method | private | | modifiers.kt:33:5:35:5 | fn | Method | public | +| modifiers.kt:34:9:34:36 | LateInit test1 | LocalVariableDecl | lateinit | From 46fb9865acb720edf8e956a657f7f914dc6c65fc Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 5 Oct 2022 16:08:57 +0200 Subject: [PATCH 052/164] Add `lateinit` test to print the extracted AST --- .../library-tests/lateinit/PrintAst.expected | 94 +++++++++++++++++++ .../library-tests/lateinit/PrintAst.qlref | 1 + .../library-tests/lateinit/test.expected | 8 ++ .../kotlin/library-tests/lateinit/test.kt | 16 ++++ .../kotlin/library-tests/lateinit/test.ql | 13 +++ 5 files changed, 132 insertions(+) create mode 100644 java/ql/test/kotlin/library-tests/lateinit/PrintAst.expected create mode 100644 java/ql/test/kotlin/library-tests/lateinit/PrintAst.qlref create mode 100644 java/ql/test/kotlin/library-tests/lateinit/test.expected create mode 100644 java/ql/test/kotlin/library-tests/lateinit/test.kt create mode 100644 java/ql/test/kotlin/library-tests/lateinit/test.ql diff --git a/java/ql/test/kotlin/library-tests/lateinit/PrintAst.expected b/java/ql/test/kotlin/library-tests/lateinit/PrintAst.expected new file mode 100644 index 00000000000..c2119ec6123 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/lateinit/PrintAst.expected @@ -0,0 +1,94 @@ +test.kt: +# 0| [CompilationUnit] test +# 1| 1: [Class] LateInit +# 1| 1: [Constructor] LateInit +# 1| 5: [BlockStmt] { ... } +# 1| 0: [SuperConstructorInvocationStmt] super(...) +# 1| 1: [BlockStmt] { ... } +# 2| 2: [FieldDeclaration] LateInit test0; +# 2| -1: [TypeAccess] LateInit +# 2| 3: [Method] getTest0$private +# 2| 3: [TypeAccess] LateInit +# 2| 5: [BlockStmt] { ... } +# 2| 0: [ReturnStmt] return ... +# 2| 0: [VarAccess] this.test0 +# 2| -1: [ThisAccess] this +# 2| 4: [Method] setTest0$private +# 2| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 2| 0: [Parameter] +# 2| 0: [TypeAccess] LateInit +# 2| 5: [BlockStmt] { ... } +# 2| 0: [ExprStmt] ; +# 2| 0: [AssignExpr] ...=... +# 2| 0: [VarAccess] this.test0 +# 2| -1: [ThisAccess] this +# 2| 1: [VarAccess] +# 4| 5: [Method] f +# 4| 3: [TypeAccess] Unit +# 4| 5: [BlockStmt] { ... } +# 4| 0: [ReturnStmt] return ... +# 4| 0: [MethodAccess] println(...) +# 4| -1: [TypeAccess] ConsoleKt +# 4| 0: [StringLiteral] a +# 6| 6: [Method] init +# 6| 3: [TypeAccess] LateInit +# 6| 5: [BlockStmt] { ... } +# 6| 0: [ReturnStmt] return ... +# 6| 0: [ClassInstanceExpr] new LateInit(...) +# 6| -3: [TypeAccess] LateInit +# 8| 7: [Method] fn +# 8| 3: [TypeAccess] Unit +# 8| 5: [BlockStmt] { ... } +# 9| 0: [ExprStmt] ; +# 9| 0: [MethodAccess] f(...) +# 9| -1: [MethodAccess] getTest0$private(...) +# 9| -1: [ThisAccess] this +# 10| 1: [ExprStmt] ; +# 10| 0: [WhenExpr] when ... +# 10| 0: [WhenBranch] ... -> ... +# 10| 0: [MethodAccess] isInitialized(...) +# 10| -1: [TypeAccess] LateinitKt +# 10| 0: [PropertyRefExpr] ...::... +# 10| -4: [AnonymousClass] new KMutableProperty0(...) { ... } +# 10| 1: [Constructor] +#-----| 4: (Parameters) +# 10| 0: [Parameter] +# 10| 5: [BlockStmt] { ... } +# 10| 0: [SuperConstructorInvocationStmt] super(...) +# 10| 1: [ExprStmt] ; +# 10| 0: [AssignExpr] ...=... +# 10| 0: [VarAccess] this. +# 10| -1: [ThisAccess] this +# 10| 1: [VarAccess] +# 10| 2: [FieldDeclaration] LateInit ; +# 10| -1: [TypeAccess] LateInit +# 10| 3: [Method] get +# 10| 5: [BlockStmt] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [MethodAccess] getTest0$private(...) +# 10| -1: [VarAccess] this. +# 10| -1: [ThisAccess] this +# 10| 4: [Method] invoke +# 10| 5: [BlockStmt] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [MethodAccess] get(...) +# 10| -1: [ThisAccess] this +# 10| 5: [Method] set +#-----| 4: (Parameters) +# 10| 0: [Parameter] a0 +# 10| 5: [BlockStmt] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [MethodAccess] setTest0$private(...) +# 10| -1: [VarAccess] this. +# 10| -1: [ThisAccess] this +# 10| 0: [VarAccess] a0 +# 10| -3: [TypeAccess] KMutableProperty0 +# 10| 0: [TypeAccess] LateInit +# 10| 0: [ThisAccess] this +# 10| 1: [BlockStmt] { ... } +# 13| 2: [LocalVariableDeclStmt] var ...; +# 13| 1: [LocalVariableDeclExpr] test1 +# 14| 3: [ExprStmt] ; +# 14| 0: [MethodAccess] f(...) +# 14| -1: [VarAccess] test1 diff --git a/java/ql/test/kotlin/library-tests/lateinit/PrintAst.qlref b/java/ql/test/kotlin/library-tests/lateinit/PrintAst.qlref new file mode 100644 index 00000000000..c7fd5faf239 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/lateinit/PrintAst.qlref @@ -0,0 +1 @@ +semmle/code/java/PrintAst.ql \ No newline at end of file diff --git a/java/ql/test/kotlin/library-tests/lateinit/test.expected b/java/ql/test/kotlin/library-tests/lateinit/test.expected new file mode 100644 index 00000000000..e3761785021 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/lateinit/test.expected @@ -0,0 +1,8 @@ +| test.kt:4:15:4:26 | println(...) | file:///ConsoleKt.class:0:0:0:0 | println | +| test.kt:9:9:9:13 | getTest0$private(...) | test.kt:2:22:2:40 | getTest0$private | +| test.kt:9:15:9:17 | f(...) | test.kt:4:5:4:26 | f | +| test.kt:10:13:10:23 | get(...) | test.kt:10:13:10:23 | get | +| test.kt:10:13:10:23 | getTest0$private(...) | test.kt:2:22:2:40 | getTest0$private | +| test.kt:10:13:10:23 | setTest0$private(...) | test.kt:2:22:2:40 | setTest0$private | +| test.kt:10:25:10:37 | isInitialized(...) | file:///LateinitKt.class:0:0:0:0 | isInitialized | +| test.kt:14:15:14:17 | f(...) | test.kt:4:5:4:26 | f | diff --git a/java/ql/test/kotlin/library-tests/lateinit/test.kt b/java/ql/test/kotlin/library-tests/lateinit/test.kt new file mode 100644 index 00000000000..3312f67511c --- /dev/null +++ b/java/ql/test/kotlin/library-tests/lateinit/test.kt @@ -0,0 +1,16 @@ +public class LateInit { + private lateinit var test0: LateInit + + fun f() = println("a") + + fun init() = LateInit() + + fun fn() { + test0.f() // This is preceded by a null-check and a throw in bytecode, in IR it's a simple call + if (this::test0.isInitialized) { // This is converted to a null-check in bytecode, in IR it's a call to `LateinitKt.isInitialized` + } + + lateinit var test1: LateInit + test1.f() // This is replaced by `Intrinsics.throwUninitializedPropertyAccessException` in bytecode, in IR it's a simple call + } +} diff --git a/java/ql/test/kotlin/library-tests/lateinit/test.ql b/java/ql/test/kotlin/library-tests/lateinit/test.ql new file mode 100644 index 00000000000..5f4a458da95 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/lateinit/test.ql @@ -0,0 +1,13 @@ +import java + +class MethodLocation extends Method { + override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + exists(string fullPath | super.hasLocationInfo(fullPath, sl, sc, el, ec) | + if exists(this.getFile().getRelativePath()) + then path = fullPath + else path = fullPath.regexpReplaceAll(".*/", "/") + ) + } +} + +query predicate calls(MethodAccess ma, Method m) { ma.getMethod() = m } From 0bbc7adca041199b5400d3fb871d8f8f452047eb Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 6 Oct 2022 08:45:57 +0200 Subject: [PATCH 053/164] Accept test changes --- .../ql/test/kotlin/library-tests/properties/properties.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/test/kotlin/library-tests/properties/properties.expected b/java/ql/test/kotlin/library-tests/properties/properties.expected index 7bbe706923c..01c82187a81 100644 --- a/java/ql/test/kotlin/library-tests/properties/properties.expected +++ b/java/ql/test/kotlin/library-tests/properties/properties.expected @@ -41,7 +41,7 @@ fieldDeclarations | properties.kt:28:5:29:22 | overrideGetter | properties.kt:29:13:29:22 | getOverrideGetter | properties.kt:28:5:29:22 | setOverrideGetter | properties.kt:28:5:29:22 | overrideGetter | public | | properties.kt:30:5:31:29 | overrideGetterUseField | properties.kt:31:13:31:29 | getOverrideGetterUseField | properties.kt:30:5:31:29 | setOverrideGetterUseField | properties.kt:30:5:31:29 | overrideGetterUseField | public | | properties.kt:32:5:33:29 | useField | properties.kt:33:13:33:29 | getUseField | file://:0:0:0:0 | | properties.kt:32:5:33:29 | useField | public | -| properties.kt:34:5:34:36 | lateInitVar | properties.kt:34:14:34:36 | getLateInitVar | properties.kt:34:14:34:36 | setLateInitVar | properties.kt:34:5:34:36 | lateInitVar | public | +| properties.kt:34:5:34:36 | lateInitVar | properties.kt:34:14:34:36 | getLateInitVar | properties.kt:34:14:34:36 | setLateInitVar | properties.kt:34:5:34:36 | lateInitVar | lateinit, public | | properties.kt:35:5:35:32 | privateProp | properties.kt:35:13:35:32 | getPrivateProp$private | file://:0:0:0:0 | | properties.kt:35:5:35:32 | privateProp | private | | properties.kt:36:5:36:36 | protectedProp | properties.kt:36:15:36:36 | getProtectedProp | file://:0:0:0:0 | | properties.kt:36:5:36:36 | protectedProp | protected | | properties.kt:37:5:37:30 | publicProp | properties.kt:37:12:37:30 | getPublicProp | file://:0:0:0:0 | | properties.kt:37:5:37:30 | publicProp | public | From 3fcb825e7f20e36951d03155ee40865af0e567e3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 6 Oct 2022 17:21:09 +0100 Subject: [PATCH 054/164] C++: Change a few indirectionIndex ranges from '[0 .. n - 1]' to '[1 .. n]'. This simplifies some arithmetic in a few predicates. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 6 +++--- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 17 +++++------------ .../code/cpp/ir/dataflow/internal/ModelUtil.qll | 2 +- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index d6b2d455dd2..672cb93690c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -137,7 +137,7 @@ private newtype TReturnKind = exists(IndirectReturnNode return, ReturnIndirectionInstruction returnInd | returnInd.hasIndex(argumentIndex) and return.getAddressOperand() = returnInd.getSourceAddressOperand() and - indirectionIndex = return.getIndirectionIndex() - 1 // We subtract one because the return loads the value. + indirectionIndex = return.getIndirectionIndex() ) } @@ -197,7 +197,7 @@ class ReturnIndirectionNode extends IndirectReturnNode, ReturnNode { exists(int argumentIndex, ReturnIndirectionInstruction returnInd | returnInd.hasIndex(argumentIndex) and this.getAddressOperand() = returnInd.getSourceAddressOperand() and - result = TIndirectReturnKind(argumentIndex, this.getIndirectionIndex() - 1) and + result = TIndirectReturnKind(argumentIndex, this.getIndirectionIndex()) and hasNonInitializeParameterDef(returnInd.getIRVariable()) ) or @@ -365,7 +365,7 @@ predicate jumpStep(Node n1, Node n2) { predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) { exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store | nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and - node2.getIndirectionIndex() = 0 and + node2.getIndirectionIndex() = 1 and numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(), numberOfLoads) | diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 08d5f270e5a..1393ddea1a1 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -38,13 +38,12 @@ private module Cached { TVariableNode(Variable var) or TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) { indirectionIndex = - [0 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType()) - - 1] + [1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())] } or TSsaPhiNode(Ssa::PhiNode phi) or TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) { Ssa::isModifiableByCall(operand) and - indirectionIndex = [0 .. Ssa::countIndirectionsForCppType(operand.getLanguageType()) - 1] + indirectionIndex = [1 .. Ssa::countIndirectionsForCppType(operand.getLanguageType())] } or TIndirectOperand(Operand op, int indirectionIndex) { Ssa::hasIndirectOperand(op, indirectionIndex) @@ -370,8 +369,6 @@ class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode { override Declaration getEnclosingCallable() { result = this.getFunction() } - override IRType getType() { result = fieldAddress.getIRType() } - FieldAddress getFieldAddress() { result = fieldAddress } Field getUpdatedField() { result = fieldAddress.getField() } @@ -379,10 +376,8 @@ class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode { int getIndirectionIndex() { result = indirectionIndex } override Node getPreUpdateNode() { - // + 1 because we're storing into an lvalue, and the original node should be the rvalue of - // the same address. hasOperandAndIndex(result, pragma[only_bind_into](fieldAddress).getObjectAddressOperand(), - indirectionIndex + 1) + indirectionIndex) } override Expr getDefinedExpr() { @@ -536,9 +531,7 @@ class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PostUpdate override Function getFunction() { result = this.getCallInstruction().getEnclosingFunction() } - override IRType getType() { result instanceof IRVoidType } - - override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex + 1) } + override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex) } override string toStringImpl() { // This string should be unique enough to be helpful but common enough to @@ -1075,7 +1068,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { store.getDestinationAddressOperand() = address ) or - Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex - 1) + Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll index c302c6ef878..27edf7ce02c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll @@ -41,7 +41,7 @@ Node callOutput(CallInstruction call, FunctionOutput output) { // The side effect of a call on the value pointed to by an argument or qualifier exists(int index, int indirectionIndex | result.(IndirectArgumentOutNode).getArgumentIndex() = index and - result.(IndirectArgumentOutNode).getIndirectionIndex() + 1 = indirectionIndex and + result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and result.(IndirectArgumentOutNode).getCallInstruction() = call and output.isParameterDerefOrQualifierObject(index, indirectionIndex) ) From 65a538ed419b4571d54b3bff7581d1d79754c8e3 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 6 Oct 2022 17:22:09 +0100 Subject: [PATCH 055/164] C++: Exclude a few more operands from the dataflow graph. These aren't ever used for dataflow, and it should give us a slight speedup. --- .../code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll index 36ab036c4e5..2e0a20fcfdc 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll @@ -11,7 +11,9 @@ private import DataFlowUtil * corresponding `(Indirect)OperandNode`. */ predicate ignoreOperand(Operand operand) { - operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() + operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or + operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or + operand instanceof MemoryOperand } /** From e147a6032ef2ff1886bf152ed5c2a7592afae686 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Thu, 6 Oct 2022 17:26:56 +0100 Subject: [PATCH 056/164] C++: Replace 'IRType' with 'Type' in dataflow. This means we're more compatible with the old AST library. --- .../ir/dataflow/internal/DataFlowPrivate.qll | 10 +-- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 68 +++++++++++++++---- .../dataflow/internal/ssa0/SsaInternals.qll | 4 +- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 672cb93690c..c35d85274b2 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -465,20 +465,20 @@ predicate clearsContent(Node n, Content c) { predicate expectsContent(Node n, ContentSet c) { none() } /** Gets the type of `n` used for type pruning. */ -IRType getNodeType(Node n) { +DataFlowType getNodeType(Node n) { suppressUnusedNode(n) and - result instanceof IRVoidType // stub implementation + result instanceof VoidType // stub implementation } /** Gets a string representation of a type returned by `getNodeType`. */ -string ppReprType(IRType t) { none() } // stub implementation +string ppReprType(DataFlowType t) { none() } // stub implementation /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. */ pragma[inline] -predicate compatibleTypes(IRType t1, IRType t2) { +predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() // stub implementation } @@ -502,7 +502,7 @@ class DataFlowCallable = Cpp::Declaration; class DataFlowExpr = Expr; -class DataFlowType = IRType; +class DataFlowType = Type; /** A function call relevant for data flow. */ class DataFlowCall extends CallInstruction { diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 1393ddea1a1..b1e0779468b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -112,7 +112,7 @@ class Node extends TIRDataFlowNode { Declaration getFunction() { none() } // overridden in subclasses /** Gets the type of this node. */ - IRType getType() { none() } // overridden in subclasses + DataFlowType getType() { none() } // overridden in subclasses /** Gets the instruction corresponding to this node, if any. */ Instruction asInstruction() { result = this.(InstructionNode).getInstruction() } @@ -272,7 +272,7 @@ class Node extends TIRDataFlowNode { /** * Gets an upper bound on the type of this node. */ - IRType getTypeBound() { result = this.getType() } + DataFlowType getTypeBound() { result = this.getType() } /** Gets the location of this element. */ cached @@ -321,7 +321,7 @@ class InstructionNode extends Node, TInstructionNode { override Declaration getFunction() { result = instr.getEnclosingFunction() } - override IRType getType() { result = instr.getResultIRType() } + override DataFlowType getType() { result = instr.getResultType() } final override Location getLocationImpl() { result = instr.getLocation() } @@ -347,13 +347,32 @@ class OperandNode extends Node, TOperandNode { override Declaration getFunction() { result = op.getUse().getEnclosingFunction() } - override IRType getType() { result = op.getIRType() } + override DataFlowType getType() { result = op.getType() } final override Location getLocationImpl() { result = op.getLocation() } override string toStringImpl() { result = this.getOperand().toString() } } +/** + * Returns `t`, but stripped of the `n` outermost pointers, references, etc. + * + * For example, `stripPointers(int*&, 2)` is `int` and `stripPointers(int*, 0)` is `int*`. + */ +private Type stripPointers(Type t, int n) { + result = t and n = 0 + or + result = stripPointers(t.(PointerType).getBaseType(), n - 1) + or + result = stripPointers(t.(ArrayType).getBaseType(), n - 1) + or + result = stripPointers(t.(ReferenceType).getBaseType(), n - 1) + or + result = stripPointers(t.(PointerToMemberType).getBaseType(), n - 1) + or + result = stripPointers(t.(FunctionPointerIshType).getBaseType(), n - 1) +} + /** * INTERNAL: do not use. * @@ -406,7 +425,7 @@ class SsaPhiNode extends Node, TSsaPhiNode { override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() } - override IRType getType() { result instanceof IRVoidType } + override DataFlowType getType() { result = this.getAnInput().getType() } final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() } @@ -449,8 +468,6 @@ class SideEffectOperandNode extends Node, IndirectOperand { override Function getFunction() { result = call.getEnclosingFunction() } - override IRType getType() { result instanceof IRVoidType } - Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() } } @@ -473,8 +490,6 @@ class IndirectParameterNode extends Node, IndirectInstruction { override Function getFunction() { result = this.getInstruction().getEnclosingFunction() } - override IRType getType() { result instanceof IRVoidType } - override string toStringImpl() { result = this.getParameter().toString() + " indirection" or @@ -499,8 +514,6 @@ class IndirectReturnNode extends IndirectOperand { Operand getAddressOperand() { result = operand } override Declaration getEnclosingCallable() { result = this.getFunction() } - - override IRType getType() { result instanceof IRVoidType } } /** @@ -587,6 +600,23 @@ class IndirectReturnOutNode extends Node { int getIndirectionIndex() { result = indirectionIndex } } +private PointerType getGLValueType(Type t, int indirectionIndex) { + result.getBaseType() = stripPointers(t, indirectionIndex - 1) +} + +bindingset[isGLValue] +private DataFlowType getType0(Type t, int indirectionIndex, boolean isGLValue) { + if isGLValue = true + then + result = getGLValueType(t, indirectionIndex) + or + // If the `PointerType` with the correct base type isn't in the database we cannot + // return a correct type. So instead we'll return a value that has "one indirection too little". + not exists(getGLValueType(t, indirectionIndex)) and + result = stripPointers(t, indirectionIndex - 1) + else result = stripPointers(t, indirectionIndex) +} + /** * INTERNAL: Do not use. * @@ -608,7 +638,11 @@ class IndirectOperand extends Node, TIndirectOperand { override Declaration getEnclosingCallable() { result = this.getFunction() } - override IRType getType() { result = this.getOperand().getIRType() } + override DataFlowType getType() { + exists(boolean isGLValue | if operand.isGLValue() then isGLValue = true else isGLValue = false | + result = getType0(operand.getType().getUnspecifiedType(), indirectionIndex, isGLValue) + ) + } final override Location getLocationImpl() { result = this.getOperand().getLocation() } @@ -638,7 +672,11 @@ class IndirectInstruction extends Node, TIndirectInstruction { override Declaration getEnclosingCallable() { result = this.getFunction() } - override IRType getType() { result = this.getInstruction().getResultIRType() } + override DataFlowType getType() { + exists(boolean isGLValue | if instr.isGLValue() then isGLValue = true else isGLValue = false | + result = getType0(instr.getResultType().getUnspecifiedType(), indirectionIndex, isGLValue) + ) + } final override Location getLocationImpl() { result = this.getInstruction().getLocation() } @@ -852,6 +890,8 @@ abstract class PostUpdateNode extends Node { * Gets the node before the state update. */ abstract Node getPreUpdateNode(); + + final override Type getType() { result = this.getPreUpdateNode().getType() } } /** @@ -915,7 +955,7 @@ class VariableNode extends Node, TVariableNode { result = v } - override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) } + override DataFlowType getType() { result = v.getType() } final override Location getLocationImpl() { result = v.getLocation() } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll index 3a89f1d170f..06c4a7f751c 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll @@ -36,7 +36,7 @@ private module SourceVariables { override string toString() { result = var.toString() } - override DataFlowType getType() { result = var.getIRType() } + override DataFlowType getType() { result = var.getType() } } class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable { @@ -48,7 +48,7 @@ private module SourceVariables { override string toString() { result = call.toString() } - override DataFlowType getType() { result = call.getResultIRType() } + override DataFlowType getType() { result = call.getResultType() } } private newtype TSourceVariable = From 944ca4a0da5b206fbdaf2958da0c65853dda5eb4 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 11:23:34 +0200 Subject: [PATCH 057/164] fix some more style-guide violations in the alert-messages --- .../Classes/MaybeUndefinedClassAttribute.ql | 2 +- python/ql/src/Classes/SlotsInOldStyleClass.ql | 3 +- python/ql/src/Classes/SubclassShadowing.ql | 4 +- python/ql/src/Classes/SuperInOldStyleClass.ql | 2 +- .../ql/src/Classes/UndefinedClassAttribute.ql | 2 +- python/ql/src/Exceptions/RaisingTuple.ql | 4 +- .../Exceptions/UnguardedNextInGenerator.ql | 2 +- .../Comparisons/UselessComparisonTest.ql | 2 +- .../ql/src/Functions/DeprecatedSliceMethod.ql | 2 +- .../ModificationOfParameterWithDefault.ql | 4 +- .../Functions/UseImplicitNoneReturnValue.ql | 2 +- .../ql/src/Imports/ImportShadowedByLoopVar.ql | 2 +- python/ql/src/Imports/ImportStarUsed.ql | 2 +- python/ql/src/Imports/ImportandImportFrom.ql | 2 +- python/ql/src/Numerics/Pythagorean.ql | 2 +- .../IncompleteUrlSubstringSanitization.ql | 2 +- .../ql/src/Security/CWE-022/PathInjection.ql | 4 +- python/ql/src/Security/CWE-022/TarSlip.ql | 4 +- .../src/Security/CWE-078/CommandInjection.ql | 4 +- .../ql/src/Security/CWE-079/ReflectedXss.ql | 4 +- .../ql/src/Security/CWE-089/SqlInjection.ql | 4 +- .../ql/src/Security/CWE-090/LdapInjection.ql | 5 +- .../ql/src/Security/CWE-094/CodeInjection.ql | 4 +- .../ql/src/Security/CWE-117/LogInjection.ql | 4 +- .../Security/CWE-209/StackTraceExposure.ql | 5 +- .../CWE-295/RequestWithoutValidation.ql | 6 +- .../src/Security/CWE-312/CleartextLogging.ql | 4 +- .../src/Security/CWE-312/CleartextStorage.ql | 2 +- .../src/Security/CWE-327/InsecureProtocol.ql | 2 +- .../Security/CWE-502/UnsafeDeserialization.ql | 4 +- python/ql/src/Security/CWE-601/UrlRedirect.ql | 4 +- python/ql/src/Security/CWE-611/Xxe.ql | 4 +- .../ql/src/Security/CWE-643/XpathInjection.ql | 4 +- .../src/Security/CWE-730/PolynomialReDoS.ql | 4 +- .../ql/src/Security/CWE-730/RegexInjection.ql | 5 +- python/ql/src/Security/CWE-776/XmlBomb.ql | 4 +- .../Security/CWE-798/HardcodedCredentials.ql | 3 +- .../CWE-918/FullServerSideRequestForgery.ql | 4 +- .../PartialServerSideRequestForgery.ql | 4 +- python/ql/src/Statements/DocStrings.ql | 2 +- .../ql/src/Statements/NonIteratorInForLoop.ql | 2 +- .../ql/src/Statements/SideEffectInAssert.ql | 2 +- .../src/Statements/UnusedExceptionObject.ql | 2 +- python/ql/src/Variables/Global.ql | 2 +- .../ql/src/Variables/LoopVariableCapture.ql | 2 +- python/ql/src/Variables/MultiplyDefined.ql | 4 +- python/ql/src/Variables/ShadowGlobal.ql | 2 +- .../ql/src/Variables/UndefinedPlaceHolder.ql | 2 +- .../ql/src/Variables/UnusedLocalVariable.ql | 2 +- .../experimental/Security/CWE-022/ZipSlip.ql | 5 +- .../Security/CWE-113/HeaderInjection.ql | 4 +- .../Security/CWE-287/ImproperLdapAuth.ql | 2 +- .../Security/CWE-522/LDAPInsecureAuth.ql | 3 +- .../Security/CWE-611/SimpleXmlRpcServer.ql | 2 +- .../Security/CWE-943/NoSQLInjection.ql | 2 +- .../new-style/SlotsInOldStyleClass.expected | 2 +- .../new-style/SuperInOldStyleClass.expected | 2 +- .../UnguardedNextInGenerator.expected | 4 +- .../Exceptions/raising/RaisingTuple.expected | 6 +- .../iter/NonIteratorInForLoop.expected | 4 +- .../Security/CWE-022/ZipSlip.expected | 10 +-- .../Security/CWE-113/HeaderInjection.expected | 12 +-- .../CWE-287/ImproperLdapAuth.expected | 20 ++--- .../CWE-522/LDAPInsecureAuth.expected | 12 +-- .../SimpleXmlRpcServer.expected | 2 +- .../Security/CWE-943/NoSQLInjection.expected | 24 +++--- .../django-orm/ReflectedXss.expected | 10 +-- .../SubclassShadowing.expected | 2 +- .../MaybeUndefinedClassAttribute.expected | 8 +- .../UndefinedClassAttribute.expected | 8 +- .../UselessComparisonTest.expected | 20 ++--- ...odificationOfParameterWithDefault.expected | 46 +++++------ .../general/DeprecatedSliceMethod.expected | 6 +- ...odificationOfParameterWithDefault.expected | 16 ++-- .../UseImplicitNoneReturnValue.expected | 4 +- .../ImportandImportFrom.expected | 4 +- .../general/ImportShadowedByLoopVar.expected | 2 +- .../Imports/general/ImportStarUsed.expected | 6 +- .../query-tests/Numerics/Pythagorean.expected | 6 +- ...ncompleteUrlSubstringSanitization.expected | 4 +- .../PathInjection.expected | 36 ++++----- .../Security/CWE-022-TarSlip/TarSlip.expected | 10 +-- .../CommandInjection.expected | 18 ++--- .../CommandInjection.expected | 26 +++---- .../ReflectedXss.expected | 6 +- .../SqlInjection.expected | 32 ++++---- .../LdapInjection.expected | 30 +++---- .../CodeInjection.expected | 8 +- .../LogInjection.expected | 8 +- .../StackTraceExposure.expected | 10 +-- .../RequestWithoutValidation.expected | 12 +-- .../CleartextLogging.expected | 20 ++--- .../CleartextStorage.expected | 6 +- .../CleartextStorage.expected | 8 +- .../InsecureProtocol.expected | 78 +++++++++---------- .../UnsafeDeserialization.expected | 8 +- .../CWE-601-UrlRedirect/UrlRedirect.expected | 16 ++-- .../Security/CWE-611-Xxe/Xxe.expected | 4 +- .../XpathInjection.expected | 12 +-- .../PolynomialReDoS.expected | 4 +- .../RegexInjection.expected | 6 +- .../Security/CWE-776-XmlBomb/XmlBomb.expected | 2 +- .../HardcodedCredentials.expected | 4 +- .../FullServerSideRequestForgery.expected | 42 +++++----- .../PartialServerSideRequestForgery.expected | 36 ++++----- .../Statements/DocStrings/DocStrings.expected | 8 +- .../asserts/SideEffectInAssert.expected | 6 +- .../general/NonIteratorInForLoop.expected | 2 +- .../no_effect/UnusedExceptionObject.expected | 2 +- .../capture/LoopVariableCapture.expected | 16 ++-- .../Variables/general/Global.expected | 2 +- .../Variables/general/ShadowGlobal.expected | 2 +- .../multiple/MultiplyDefined.expected | 14 ++-- .../unused/UnusedLocalVariable.expected | 10 +-- .../UnusedLocalVariable.expected | 2 +- 115 files changed, 459 insertions(+), 458 deletions(-) diff --git a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql index ef360d95ec7..9818aaece3c 100644 --- a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql +++ b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql @@ -39,5 +39,5 @@ where sa.getName() = a.getName() select a, "Attribute '" + a.getName() + - "' is not defined in the class body nor in the __init__() method, but it is defined $@", sa, + "' is not defined in the class body nor in the __init__() method, but it is defined $@.", sa, "here" diff --git a/python/ql/src/Classes/SlotsInOldStyleClass.ql b/python/ql/src/Classes/SlotsInOldStyleClass.ql index cd4f9dd5f1d..bb229edc8d3 100644 --- a/python/ql/src/Classes/SlotsInOldStyleClass.ql +++ b/python/ql/src/Classes/SlotsInOldStyleClass.ql @@ -15,4 +15,5 @@ import python from ClassObject c where not c.isNewStyle() and c.declaresAttribute("__slots__") and not c.failedInference() -select c, "Using __slots__ in an old style class just creates a class attribute called '__slots__'" +select c, + "Using '__slots__' in an old style class just creates a class attribute called '__slots__'." diff --git a/python/ql/src/Classes/SubclassShadowing.ql b/python/ql/src/Classes/SubclassShadowing.ql index 6594f5eee12..974230709bb 100644 --- a/python/ql/src/Classes/SubclassShadowing.ql +++ b/python/ql/src/Classes/SubclassShadowing.ql @@ -42,5 +42,5 @@ predicate shadowed_by_super_class( from ClassObject c, ClassObject supercls, Assign assign, FunctionObject shadowed where shadowed_by_super_class(c, supercls, assign, shadowed) select shadowed.getOrigin(), - "Method " + shadowed.getName() + " is shadowed by $@ in super class '" + supercls.getName() + "'.", - assign, "an attribute" + "Method " + shadowed.getName() + " is shadowed by an $@ in super class '" + supercls.getName() + + "'.", assign, "attribute" diff --git a/python/ql/src/Classes/SuperInOldStyleClass.ql b/python/ql/src/Classes/SuperInOldStyleClass.ql index f309c025fec..deba0889449 100644 --- a/python/ql/src/Classes/SuperInOldStyleClass.ql +++ b/python/ql/src/Classes/SuperInOldStyleClass.ql @@ -24,4 +24,4 @@ predicate uses_of_super_in_old_style_class(Call s) { from Call c where uses_of_super_in_old_style_class(c) -select c, "super() will not work in old-style classes" +select c, "'super()' will not work in old-style classes." diff --git a/python/ql/src/Classes/UndefinedClassAttribute.ql b/python/ql/src/Classes/UndefinedClassAttribute.ql index 7e5717b792d..748c4681820 100644 --- a/python/ql/src/Classes/UndefinedClassAttribute.ql +++ b/python/ql/src/Classes/UndefinedClassAttribute.ql @@ -30,4 +30,4 @@ predicate report_undefined_class_attribute(Attribute a, ClassObject c, string na from Attribute a, ClassObject c, string name where report_undefined_class_attribute(a, c, name) -select a, "Attribute '" + name + "' is not defined in either the class body or in any method" +select a, "Attribute '" + name + "' is not defined in either the class body or in any method." diff --git a/python/ql/src/Exceptions/RaisingTuple.ql b/python/ql/src/Exceptions/RaisingTuple.ql index 9116430ac18..37e406326fa 100644 --- a/python/ql/src/Exceptions/RaisingTuple.ql +++ b/python/ql/src/Exceptions/RaisingTuple.ql @@ -21,5 +21,5 @@ where major_version() = 2 /* Raising a tuple is a type error in Python 3, so is handled by the IllegalRaise query. */ select r, - "Raising $@ will result in the first element (recursively) being raised and all other elements being discarded.", - origin, "a tuple" + "Raising a $@ will result in the first element (recursively) being raised and all other elements being discarded.", + origin, "tuple" diff --git a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql index 0bd49f2c8c8..a6969218fdd 100644 --- a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql +++ b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql @@ -73,4 +73,4 @@ where // However, we do not know the minor version of the analyzed code (only of the extractor), // so we only alert on Python 2. major_version() = 2 -select call, "Call to next() in a generator" +select call, "Call to 'next()' in a generator." diff --git a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql index 8bab127ec9d..3bd5f84fc67 100644 --- a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql +++ b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql @@ -48,4 +48,4 @@ private predicate useless_test_ast(AstNode comp, AstNode previous, boolean isTru from Expr test, Expr other, boolean isTrue where useless_test_ast(test, other, isTrue) and not useless_test_ast(test.getAChildNode+(), other, _) -select test, "Test is always " + isTrue + ", because of $@", other, "this condition" +select test, "Test is always " + isTrue + ", because of $@.", other, "this condition" diff --git a/python/ql/src/Functions/DeprecatedSliceMethod.ql b/python/ql/src/Functions/DeprecatedSliceMethod.ql index 2f3e8373b0b..af596f704cd 100644 --- a/python/ql/src/Functions/DeprecatedSliceMethod.ql +++ b/python/ql/src/Functions/DeprecatedSliceMethod.ql @@ -21,4 +21,4 @@ where not f.isOverridingMethod() and slice_method_name(meth) and f.getName() = meth -select f, meth + " method has been deprecated since Python 2.0" +select f, meth + " method has been deprecated since Python 2.0." diff --git a/python/ql/src/Functions/ModificationOfParameterWithDefault.ql b/python/ql/src/Functions/ModificationOfParameterWithDefault.ql index e4a50065b41..88b346fd2a0 100644 --- a/python/ql/src/Functions/ModificationOfParameterWithDefault.ql +++ b/python/ql/src/Functions/ModificationOfParameterWithDefault.ql @@ -19,5 +19,5 @@ from ModificationOfParameterWithDefault::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This expression mutates $@.", source.getNode(), - "a default value" +select sink.getNode(), source, sink, "This expression mutates a $@.", source.getNode(), + "default value" diff --git a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql index 606f1e6da51..f45c9c42e0e 100644 --- a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql +++ b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql @@ -35,4 +35,4 @@ where forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and /* Mox return objects have an `AndReturn` method */ not useOfMoxInModule(c.getEnclosingModule()) -select c, "The result of '$@' is used even though it is always None.", func, func.getQualifiedName() +select c, "The result of $@ is used even though it is always None.", func, func.getQualifiedName() diff --git a/python/ql/src/Imports/ImportShadowedByLoopVar.ql b/python/ql/src/Imports/ImportShadowedByLoopVar.ql index 035f1640d71..5a9bd33941c 100644 --- a/python/ql/src/Imports/ImportShadowedByLoopVar.ql +++ b/python/ql/src/Imports/ImportShadowedByLoopVar.ql @@ -22,4 +22,4 @@ predicate shadowsImport(Variable l) { from Variable l, Name defn where shadowsImport(l) and defn.defines(l) and exists(For for | defn = for.getTarget()) -select defn, "Loop variable '" + l.getId() + "' shadows an import" +select defn, "Loop variable '" + l.getId() + "' shadows an import." diff --git a/python/ql/src/Imports/ImportStarUsed.ql b/python/ql/src/Imports/ImportStarUsed.ql index ad25748e771..1094a879c2a 100644 --- a/python/ql/src/Imports/ImportStarUsed.ql +++ b/python/ql/src/Imports/ImportStarUsed.ql @@ -13,4 +13,4 @@ import python from ImportStar i -select i, "Using 'from ... import *' pollutes the namespace" +select i, "Using 'from ... import *' pollutes the namespace." diff --git a/python/ql/src/Imports/ImportandImportFrom.ql b/python/ql/src/Imports/ImportandImportFrom.ql index e57cac8aed4..f77ce345113 100644 --- a/python/ql/src/Imports/ImportandImportFrom.ql +++ b/python/ql/src/Imports/ImportandImportFrom.ql @@ -22,4 +22,4 @@ predicate import_and_import_from(Import i1, Import i2, Module m) { from Stmt i1, Stmt i2, Module m where import_and_import_from(i1, i2, m) -select i1, "Module '" + m.getName() + "' is imported with both 'import' and 'import from'" +select i1, "Module '" + m.getName() + "' is imported with both 'import' and 'import from'." diff --git a/python/ql/src/Numerics/Pythagorean.ql b/python/ql/src/Numerics/Pythagorean.ql index 03056de3a61..0fa325e9ae6 100644 --- a/python/ql/src/Numerics/Pythagorean.ql +++ b/python/ql/src/Numerics/Pythagorean.ql @@ -36,4 +36,4 @@ where right.asExpr() = s.getRight() and left.getALocalSource() = square() and right.getALocalSource() = square() -select c, "Pythagorean calculation with sub-optimal numerics" +select c, "Pythagorean calculation with sub-optimal numerics." diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 7db2b972da0..02e6b72d266 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -51,4 +51,4 @@ predicate unsafe_call_to_endswith(Call sanitizer, StrConst url) { from Expr sanitizer, StrConst url where incomplete_sanitization(sanitizer, url) -select sanitizer, "'$@' may be at an arbitrary position in the sanitized URL.", url, url.getText() +select sanitizer, "$@ may be at an arbitrary position in the sanitized URL.", url, url.getText() diff --git a/python/ql/src/Security/CWE-022/PathInjection.ql b/python/ql/src/Security/CWE-022/PathInjection.ql index 3ed0ef6234b..8548c815fe4 100644 --- a/python/ql/src/Security/CWE-022/PathInjection.ql +++ b/python/ql/src/Security/CWE-022/PathInjection.ql @@ -22,5 +22,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This path depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-022/TarSlip.ql b/python/ql/src/Security/CWE-022/TarSlip.ql index 241355f1c1b..647b41756f8 100644 --- a/python/ql/src/Security/CWE-022/TarSlip.ql +++ b/python/ql/src/Security/CWE-022/TarSlip.ql @@ -18,5 +18,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This file extraction depends on $@", source.getNode(), - "a potentially untrusted source" +select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(), + "potentially untrusted source" diff --git a/python/ql/src/Security/CWE-078/CommandInjection.ql b/python/ql/src/Security/CWE-078/CommandInjection.ql index 8ac08164a8c..f8c48714e1a 100644 --- a/python/ql/src/Security/CWE-078/CommandInjection.ql +++ b/python/ql/src/Security/CWE-078/CommandInjection.ql @@ -20,5 +20,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This command line depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This command line depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-079/ReflectedXss.ql b/python/ql/src/Security/CWE-079/ReflectedXss.ql index 2b1e0b8b745..1189e35be67 100644 --- a/python/ql/src/Security/CWE-079/ReflectedXss.ql +++ b/python/ql/src/Security/CWE-079/ReflectedXss.ql @@ -19,5 +19,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.", - source.getNode(), "a user-provided value" +select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.", + source.getNode(), "user-provided value" diff --git a/python/ql/src/Security/CWE-089/SqlInjection.ql b/python/ql/src/Security/CWE-089/SqlInjection.ql index f00eae6ea42..5e910cf3edf 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.ql +++ b/python/ql/src/Security/CWE-089/SqlInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This SQL query depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-090/LdapInjection.ql b/python/ql/src/Security/CWE-090/LdapInjection.ql index 14ffbb95518..efcf52eba41 100644 --- a/python/ql/src/Security/CWE-090/LdapInjection.ql +++ b/python/ql/src/Security/CWE-090/LdapInjection.ql @@ -23,5 +23,6 @@ where or any(FilterConfiguration filterConfig).hasFlowPath(source, sink) and parameterName = "filter" -select sink.getNode(), source, sink, "$@ depends on $@.", sink.getNode(), - "LDAP query parameter (" + parameterName + ")", source.getNode(), "a user-provided value" +select sink.getNode(), source, sink, + "LDAP query parameter (" + parameterName + ") depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-094/CodeInjection.ql b/python/ql/src/Security/CWE-094/CodeInjection.ql index c4334d925f4..5e5c06b68b7 100644 --- a/python/ql/src/Security/CWE-094/CodeInjection.ql +++ b/python/ql/src/Security/CWE-094/CodeInjection.ql @@ -20,5 +20,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This code execution depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This code execution depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-117/LogInjection.ql b/python/ql/src/Security/CWE-117/LogInjection.ql index 045d8300e0c..3c380321af2 100644 --- a/python/ql/src/Security/CWE-117/LogInjection.ql +++ b/python/ql/src/Security/CWE-117/LogInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This log entry depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.ql b/python/ql/src/Security/CWE-209/StackTraceExposure.ql index 7b8cf74c597..43469aaf5a3 100644 --- a/python/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/python/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -19,6 +19,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, - "$@ flows to this location and may be exposed to an external user.", source.getNode(), - "Stack trace information" +select sink.getNode(), source, sink, "This information exposed to the user depends on $@.", + source.getNode(), "stack trace information" diff --git a/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql b/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql index 125957e59b6..e8a43838fb7 100644 --- a/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql +++ b/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql @@ -22,6 +22,6 @@ where // certificate validation, for example in `requests.get(..., verify=arg)`, `arg` would // be the `disablingNode`, and the `origin` would be the place were `arg` got its // value from. - if disablingNode = origin then ending = "." else ending = " by the value from $@." -select request, "This request may run without certificate validation because it is $@" + ending, - disablingNode, "disabled here", origin, "here" + if disablingNode = origin then ending = "." else ending = " by $@." +select request, "This request may run without certificate validation because $@" + ending, + disablingNode, "the request is disabled", origin, "this value" diff --git a/python/ql/src/Security/CWE-312/CleartextLogging.ql b/python/ql/src/Security/CWE-312/CleartextLogging.ql index 877ee081e3a..93876606c7d 100644 --- a/python/ql/src/Security/CWE-312/CleartextLogging.ql +++ b/python/ql/src/Security/CWE-312/CleartextLogging.ql @@ -22,5 +22,5 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, s where config.hasFlowPath(source, sink) and classification = source.getNode().(Source).getClassification() -select sink.getNode(), source, sink, "$@ is logged here.", source.getNode(), - "Sensitive data (" + classification + ")" +select sink.getNode(), source, sink, "This logs sensitive data returned by $@ as clear text.", + source.getNode(), "Sensitive data (" + classification + ")" diff --git a/python/ql/src/Security/CWE-312/CleartextStorage.ql b/python/ql/src/Security/CWE-312/CleartextStorage.ql index 81513fd9b1d..bd21b241242 100644 --- a/python/ql/src/Security/CWE-312/CleartextStorage.ql +++ b/python/ql/src/Security/CWE-312/CleartextStorage.ql @@ -22,5 +22,5 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, s where config.hasFlowPath(source, sink) and classification = source.getNode().(Source).getClassification() -select sink.getNode(), source, sink, "$@ is stored here.", source.getNode(), +select sink.getNode(), source, sink, "This stores $@ as clear text.", source.getNode(), "Sensitive data (" + classification + ")" diff --git a/python/ql/src/Security/CWE-327/InsecureProtocol.ql b/python/ql/src/Security/CWE-327/InsecureProtocol.ql index b4984c8c764..ec3ca3766e8 100644 --- a/python/ql/src/Security/CWE-327/InsecureProtocol.ql +++ b/python/ql/src/Security/CWE-327/InsecureProtocol.ql @@ -79,5 +79,5 @@ where connectionCreation = protocolConfiguration and specific = true select connectionCreation, - "Insecure SSL/TLS protocol version " + insecure_version + " " + verb(specific) + " by $@ ", + "Insecure SSL/TLS protocol version " + insecure_version + " " + verb(specific) + " by $@.", protocolConfiguration, configName(protocolConfiguration) diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql index 545c54890bf..0ef54275827 100644 --- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql +++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.ql @@ -18,5 +18,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Unsafe deserialization depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.ql b/python/ql/src/Security/CWE-601/UrlRedirect.ql index 98110eaf5d8..fbe3f3349ce 100644 --- a/python/ql/src/Security/CWE-601/UrlRedirect.ql +++ b/python/ql/src/Security/CWE-601/UrlRedirect.ql @@ -18,5 +18,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Untrusted URL redirection depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-611/Xxe.ql b/python/ql/src/Security/CWE-611/Xxe.ql index 9bb705efc33..b361f6ffcfb 100644 --- a/python/ql/src/Security/CWE-611/Xxe.ql +++ b/python/ql/src/Security/CWE-611/Xxe.ql @@ -19,5 +19,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "XML parsing depends on $@ without guarding against external entity expansion.", source.getNode(), - "a user-provided value" + "XML parsing depends on a $@ without guarding against external entity expansion.", + source.getNode(), "user-provided value" diff --git a/python/ql/src/Security/CWE-643/XpathInjection.ql b/python/ql/src/Security/CWE-643/XpathInjection.ql index 9056fe43a05..07df47624e7 100644 --- a/python/ql/src/Security/CWE-643/XpathInjection.ql +++ b/python/ql/src/Security/CWE-643/XpathInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "XPath expression depends on $@.", source.getNode(), - "a user-provided value" +select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-730/PolynomialReDoS.ql b/python/ql/src/Security/CWE-730/PolynomialReDoS.ql index 278b7369a38..1637686c1d8 100644 --- a/python/ql/src/Security/CWE-730/PolynomialReDoS.ql +++ b/python/ql/src/Security/CWE-730/PolynomialReDoS.ql @@ -30,6 +30,6 @@ where // regexp.isAtEndLine() // ) select sinkNode.getHighlight(), source, sink, - "This $@ that depends on $@ may run slow on strings " + regexp.getPrefixMessage() + + "This $@ that depends on a $@ may run slow on strings " + regexp.getPrefixMessage() + "with many repetitions of '" + regexp.getPumpString() + "'.", regexp, "regular expression", - source.getNode(), "a user-provided value" + source.getNode(), "user-provided value" diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql index 571cac2bdd8..bbcb18056a0 100644 --- a/python/ql/src/Security/CWE-730/RegexInjection.ql +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -24,6 +24,5 @@ from where config.hasFlowPath(source, sink) and regexExecution = sink.getNode().(Sink).getRegexExecution() -select sink.getNode(), source, sink, "$@ depends on $@ and executed by $@.", sink.getNode(), - "This regular expression", source.getNode(), "a user-provided value", regexExecution, - regexExecution.getName() +select sink.getNode(), source, sink, "This regular expression depends on a $@ and executed by $@.", + source.getNode(), "user-provided value", regexExecution, regexExecution.getName() diff --git a/python/ql/src/Security/CWE-776/XmlBomb.ql b/python/ql/src/Security/CWE-776/XmlBomb.ql index 1dde46e651c..f943aa58c44 100644 --- a/python/ql/src/Security/CWE-776/XmlBomb.ql +++ b/python/ql/src/Security/CWE-776/XmlBomb.ql @@ -19,5 +19,5 @@ import DataFlow::PathGraph from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink.getNode(), source, sink, - "XML parsing depends on $@ without guarding against uncontrolled entity expansion.", - source.getNode(), "a user-provided value" + "XML parsing depends on a $@ without guarding against uncontrolled entity expansion.", + source.getNode(), "user-provided value" diff --git a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql index 895352be75c..932a557c5ee 100644 --- a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +++ b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql @@ -129,4 +129,5 @@ from HardcodedCredentialsConfiguration config, TaintedPathSource src, TaintedPat where config.hasFlowPath(src, sink) and not any(TestScope test).contains(src.getAstNode()) -select sink.getSink(), src, sink, "Use of $@.", src.getSource(), "hardcoded credentials" +select sink.getSink(), src, sink, "This hardcoded value is $@.", sink.getNode(), + "used as credentials" diff --git a/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql b/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql index 37334fea87c..a29f9e775a1 100644 --- a/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql +++ b/python/ql/src/Security/CWE-918/FullServerSideRequestForgery.ql @@ -21,5 +21,5 @@ where request = sink.getNode().(Sink).getRequest() and fullConfig.hasFlowPath(source, sink) and fullyControlledRequest(request) -select request, source, sink, "The full URL of this request depends on $@.", source.getNode(), - "a user-provided value" +select request, source, sink, "The full URL of this request depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql b/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql index 8f8d72c7d65..3bbeaabcce6 100644 --- a/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql +++ b/python/ql/src/Security/CWE-918/PartialServerSideRequestForgery.ql @@ -21,5 +21,5 @@ where request = sink.getNode().(Sink).getRequest() and partialConfig.hasFlowPath(source, sink) and not fullyControlledRequest(request) -select request, source, sink, "Part of the URL of this request depends on $@.", source.getNode(), - "a user-provided value" +select request, source, sink, "Part of the URL of this request depends on a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/Statements/DocStrings.ql b/python/ql/src/Statements/DocStrings.ql index b20731f723b..355aff93f17 100644 --- a/python/ql/src/Statements/DocStrings.ql +++ b/python/ql/src/Statements/DocStrings.ql @@ -48,4 +48,4 @@ string scope_type(Scope s) { from Scope s where needs_docstring(s) and not exists(s.getDocString()) -select s, scope_type(s) + " " + s.getName() + " does not have a docstring" +select s, scope_type(s) + " " + s.getName() + " does not have a docstring." diff --git a/python/ql/src/Statements/NonIteratorInForLoop.ql b/python/ql/src/Statements/NonIteratorInForLoop.ql index 0df5c30a77d..51ceb41f7db 100644 --- a/python/ql/src/Statements/NonIteratorInForLoop.ql +++ b/python/ql/src/Statements/NonIteratorInForLoop.ql @@ -22,4 +22,4 @@ where not t.failedInference(_) and not v = Value::named("None") and not t.isDescriptorType() -select loop, "$@ of class '$@' may be used in for-loop.", origin, "Non-iterable", t, t.getName() +select loop, "$@ of class $@ may be used in for-loop.", origin, "Non-iterable", t, t.getName() diff --git a/python/ql/src/Statements/SideEffectInAssert.ql b/python/ql/src/Statements/SideEffectInAssert.ql index 21aff6ca646..e4797d2dad4 100644 --- a/python/ql/src/Statements/SideEffectInAssert.ql +++ b/python/ql/src/Statements/SideEffectInAssert.ql @@ -42,4 +42,4 @@ predicate probable_side_effect(Expr e) { from Assert a, Expr e where probable_side_effect(e) and a.contains(e) -select a, "This 'assert' statement contains $@ which may have side effects.", e, "an expression" +select a, "This 'assert' statement contains an $@ which may have side effects.", e, "expression" diff --git a/python/ql/src/Statements/UnusedExceptionObject.ql b/python/ql/src/Statements/UnusedExceptionObject.ql index 6c19f82d60f..2cb4c4e447a 100644 --- a/python/ql/src/Statements/UnusedExceptionObject.ql +++ b/python/ql/src/Statements/UnusedExceptionObject.ql @@ -17,4 +17,4 @@ where call.getFunc().pointsTo(ex) and ex.getASuperType() = ClassValue::exception() and exists(ExprStmt s | s.getValue() = call) -select call, "Instantiating an exception, but not raising it, has no effect" +select call, "Instantiating an exception, but not raising it, has no effect." diff --git a/python/ql/src/Variables/Global.ql b/python/ql/src/Variables/Global.ql index d1ecadb1710..b29fb564a87 100644 --- a/python/ql/src/Variables/Global.ql +++ b/python/ql/src/Variables/Global.ql @@ -13,4 +13,4 @@ import python from Global g where not g.getScope() instanceof Module -select g, "Updating global variables except at module initialization is discouraged" +select g, "Updating global variables except at module initialization is discouraged." diff --git a/python/ql/src/Variables/LoopVariableCapture.ql b/python/ql/src/Variables/LoopVariableCapture.ql index 74cd20b1d6c..e4ccd73e5e1 100644 --- a/python/ql/src/Variables/LoopVariableCapture.ql +++ b/python/ql/src/Variables/LoopVariableCapture.ql @@ -44,4 +44,4 @@ predicate escaping_capturing_looping_construct(CallableExpr capturing, AstNode l from CallableExpr capturing, AstNode loop, Variable var where escaping_capturing_looping_construct(capturing, loop, var) -select capturing, "Capture of loop variable '$@'", loop, var.getId() +select capturing, "Capture of loop variable $@.", loop, var.getId() diff --git a/python/ql/src/Variables/MultiplyDefined.ql b/python/ql/src/Variables/MultiplyDefined.ql index a8fedd25156..6b82ce7bfd9 100644 --- a/python/ql/src/Variables/MultiplyDefined.ql +++ b/python/ql/src/Variables/MultiplyDefined.ql @@ -67,5 +67,5 @@ where forall(Name el | el = asgn1.getParentNode().(Tuple).getAnElt() | multiply_defined(el, _, _)) and not uninteresting_definition(asgn1) select asgn1, - "This assignment to '" + v.getId() + - "' is unnecessary as it is redefined $@ before this value is used.", asgn2 as t, "here" + "This assignment to '" + v.getId() + "' is unnecessary as $@ before this value is used.", asgn2, + "it is redefined" diff --git a/python/ql/src/Variables/ShadowGlobal.ql b/python/ql/src/Variables/ShadowGlobal.ql index 065abf42fe4..79d74d272ae 100644 --- a/python/ql/src/Variables/ShadowGlobal.ql +++ b/python/ql/src/Variables/ShadowGlobal.ql @@ -67,4 +67,4 @@ where def.defines(g) and not assigned_pytest_fixture(g) and not g.getId() = "_" -select d, "Local variable '" + g.getId() + "' shadows a global variable defined $@.", def, "here" +select d, "Local variable '" + g.getId() + "' shadows a $@.", def, "global variable" diff --git a/python/ql/src/Variables/UndefinedPlaceHolder.ql b/python/ql/src/Variables/UndefinedPlaceHolder.ql index 29004a6123f..7f7794e60a1 100644 --- a/python/ql/src/Variables/UndefinedPlaceHolder.ql +++ b/python/ql/src/Variables/UndefinedPlaceHolder.ql @@ -43,4 +43,4 @@ where not initialized_as_local(p) and not template_attribute(p) and not_a_global(p) -select p, "This use of place-holder variable '" + p.getId() + "' may be undefined" +select p, "This use of place-holder variable '" + p.getId() + "' may be undefined." diff --git a/python/ql/src/Variables/UnusedLocalVariable.ql b/python/ql/src/Variables/UnusedLocalVariable.ql index 2202359fa0b..a009d4a51b9 100644 --- a/python/ql/src/Variables/UnusedLocalVariable.ql +++ b/python/ql/src/Variables/UnusedLocalVariable.ql @@ -43,4 +43,4 @@ where unused_local(unused, v) and // If unused is part of a tuple, count it as unused if all elements of that tuple are unused. forall(Name el | el = unused.getParentNode().(Tuple).getAnElt() | unused_local(el, _)) -select unused, "Variable " + v.getId() + " is not used" +select unused, "Variable " + v.getId() + " is not used." diff --git a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql index dd89b4d1280..fe2aca0368f 100644 --- a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql +++ b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql @@ -18,5 +18,6 @@ import DataFlow::PathGraph from ZipSlipConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "Extraction of zipfile from $@", source.getNode(), - "a potentially untrusted source" +select source.getNode(), source, sink, + "Unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(), + "file system operation" diff --git a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql index 3cb4a20d5de..6c1170a5e72 100644 --- a/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql +++ b/python/ql/src/experimental/Security/CWE-113/HeaderInjection.ql @@ -17,5 +17,5 @@ import DataFlow::PathGraph from HeaderInjectionFlowConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ HTTP header is constructed from a $@.", sink.getNode(), - "This", source.getNode(), "user-provided value" +select sink.getNode(), source, sink, "This HTTP header is constructed from a $@.", source.getNode(), + "user-provided value" diff --git a/python/ql/src/experimental/Security/CWE-287/ImproperLdapAuth.ql b/python/ql/src/experimental/Security/CWE-287/ImproperLdapAuth.ql index 177c58e2782..d4d4425aa0a 100644 --- a/python/ql/src/experimental/Security/CWE-287/ImproperLdapAuth.ql +++ b/python/ql/src/experimental/Security/CWE-287/ImproperLdapAuth.ql @@ -27,4 +27,4 @@ predicate authenticatesImproperly(LdapBind ldapBind) { from LdapBind ldapBind where authenticatesImproperly(ldapBind) -select ldapBind, "The following LDAP bind operation is executed without authentication" +select ldapBind, "The following LDAP bind operation is executed without authentication." diff --git a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql index 88715203be8..88925d56a15 100644 --- a/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql +++ b/python/ql/src/experimental/Security/CWE-522/LDAPInsecureAuth.ql @@ -16,5 +16,4 @@ import experimental.semmle.python.security.LDAPInsecureAuth from LdapInsecureAuthConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "$@ is authenticated insecurely.", sink.getNode(), - "This LDAP host" +select sink.getNode(), source, sink, "This LDAP host is authenticated insecurely." diff --git a/python/ql/src/experimental/Security/CWE-611/SimpleXmlRpcServer.ql b/python/ql/src/experimental/Security/CWE-611/SimpleXmlRpcServer.ql index e31fdc88629..edd19bfdfd9 100644 --- a/python/ql/src/experimental/Security/CWE-611/SimpleXmlRpcServer.ql +++ b/python/ql/src/experimental/Security/CWE-611/SimpleXmlRpcServer.ql @@ -16,4 +16,4 @@ private import semmle.python.ApiGraphs from DataFlow::CallCfgNode call where call = API::moduleImport("xmlrpc").getMember("server").getMember("SimpleXMLRPCServer").getACall() -select call, "SimpleXMLRPCServer is vulnerable to XML bombs" +select call, "SimpleXMLRPCServer is vulnerable to XML bombs." diff --git a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql index cd4405d301b..87e003fcc45 100644 --- a/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql +++ b/python/ql/src/experimental/Security/CWE-943/NoSQLInjection.ql @@ -15,5 +15,5 @@ import DataFlow::PathGraph from NoSqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink, source, sink, "$@ NoSQL query contains an unsanitized $@", sink, "This", source, +select sink, source, sink, "This NoSQL query contains an unsanitized $@.", source, "user-provided value" diff --git a/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.expected b/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.expected index 60c073b9dd6..ccad85bd384 100644 --- a/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.expected +++ b/python/ql/test/2/query-tests/Classes/new-style/SlotsInOldStyleClass.expected @@ -1 +1 @@ -| newstyle_test.py:4:1:4:16 | class OldStyle1 | Using __slots__ in an old style class just creates a class attribute called '__slots__' | +| newstyle_test.py:4:1:4:16 | class OldStyle1 | Using '__slots__' in an old style class just creates a class attribute called '__slots__'. | diff --git a/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.expected b/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.expected index f60a56e8efe..2ee934ed673 100644 --- a/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.expected +++ b/python/ql/test/2/query-tests/Classes/new-style/SuperInOldStyleClass.expected @@ -1 +1 @@ -| newstyle_test.py:15:9:15:15 | super() | super() will not work in old-style classes | +| newstyle_test.py:15:9:15:15 | super() | 'super()' will not work in old-style classes. | diff --git a/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.expected b/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.expected index 289b8fb5a0d..7cd772d4662 100644 --- a/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.expected +++ b/python/ql/test/2/query-tests/Exceptions/generators/UnguardedNextInGenerator.expected @@ -1,2 +1,2 @@ -| test.py:5:15:5:22 | ControlFlowNode for next() | Call to next() in a generator | -| test.py:10:20:10:27 | ControlFlowNode for next() | Call to next() in a generator | +| test.py:5:15:5:22 | ControlFlowNode for next() | Call to 'next()' in a generator. | +| test.py:10:20:10:27 | ControlFlowNode for next() | Call to 'next()' in a generator. | diff --git a/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.expected b/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.expected index 7200c147ea9..ecfd7587d53 100644 --- a/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.expected +++ b/python/ql/test/2/query-tests/Exceptions/raising/RaisingTuple.expected @@ -1,3 +1,3 @@ -| test.py:8:5:8:12 | Raise | Raising $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:7:10:7:29 | ControlFlowNode for Tuple | a tuple | -| test.py:11:5:11:32 | Raise | Raising $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:11:12:11:31 | ControlFlowNode for Tuple | a tuple | -| test.py:15:5:15:23 | Raise | Raising $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:14:10:14:19 | ControlFlowNode for Tuple | a tuple | +| test.py:8:5:8:12 | Raise | Raising a $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:7:10:7:29 | ControlFlowNode for Tuple | tuple | +| test.py:11:5:11:32 | Raise | Raising a $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:11:12:11:31 | ControlFlowNode for Tuple | tuple | +| test.py:15:5:15:23 | Raise | Raising a $@ will result in the first element (recursively) being raised and all other elements being discarded. | test.py:14:10:14:19 | ControlFlowNode for Tuple | tuple | diff --git a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected index 1f807ddf5f0..9c6647c1253 100644 --- a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected +++ b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected @@ -1,2 +1,2 @@ -| async_iterator.py:26:11:26:34 | For | $@ of class '$@' may be used in for-loop. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | Non-iterable | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter | -| statements_test.py:34:5:34:19 | For | $@ of class '$@' may be used in for-loop. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | Non-iterable | file://:0:0:0:0 | builtin-class int | int | +| async_iterator.py:26:11:26:34 | For | $@ of class $@ may be used in for-loop. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | Non-iterable | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter | +| statements_test.py:34:5:34:19 | For | $@ of class $@ may be used in for-loop. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | Non-iterable | file://:0:0:0:0 | builtin-class int | int | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected index 66594b3374e..fcf908f08e1 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected @@ -27,8 +27,8 @@ nodes | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | subpaths #select -| zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | Extraction of zipfile from $@ | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | a potentially untrusted source | -| zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | Extraction of zipfile from $@ | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | a potentially untrusted source | -| zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | Extraction of zipfile from $@ | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | a potentially untrusted source | -| zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | Extraction of zipfile from $@ | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | a potentially untrusted source | -| zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | Extraction of zipfile from $@ | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | a potentially untrusted source | +| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | file system operation | +| zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | file system operation | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected index 100beb0f4b3..f2838178c0d 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-113/HeaderInjection.expected @@ -36,9 +36,9 @@ nodes | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | semmle.label | ControlFlowNode for rfs_header | subpaths #select -| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | This | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | user-provided value | -| django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | This | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | user-provided value | -| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This | flask_bad.py:9:18:9:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value | -| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | $@ HTTP header is constructed from a $@. | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | +| django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | django_bad.py:7:40:7:49 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | django_bad.py:5:18:5:58 | ControlFlowNode for Attribute() | user-provided value | +| django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | django_bad.py:14:30:14:39 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | django_bad.py:12:18:12:58 | ControlFlowNode for Attribute() | user-provided value | +| flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | flask_bad.py:9:18:9:24 | ControlFlowNode for request | flask_bad.py:12:31:12:40 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:9:18:9:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | flask_bad.py:19:18:19:24 | ControlFlowNode for request | flask_bad.py:21:38:21:47 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:19:18:19:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | flask_bad.py:27:18:27:24 | ControlFlowNode for request | flask_bad.py:29:34:29:43 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:27:18:27:24 | ControlFlowNode for request | user-provided value | +| flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | flask_bad.py:35:18:35:24 | ControlFlowNode for request | flask_bad.py:38:24:38:33 | ControlFlowNode for rfs_header | This HTTP header is constructed from a $@. | flask_bad.py:35:18:35:24 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.expected index 766665ee1b6..224c1a33902 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-287/ImproperLdapAuth.expected @@ -1,10 +1,10 @@ -| auth_bad_2.py:19:5:19:42 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_2.py:33:5:33:44 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_2.py:47:5:47:43 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_2.py:60:5:60:52 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_2.py:73:5:73:39 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_2.py:87:5:87:48 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication | -| auth_bad_3.py:19:12:19:43 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication | -| auth_bad_3.py:33:12:33:57 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication | -| auth_bad_3.py:46:12:46:55 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication | -| auth_bad_3.py:60:12:60:42 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication | +| auth_bad_2.py:19:5:19:42 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_2.py:33:5:33:44 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_2.py:47:5:47:43 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_2.py:60:5:60:52 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_2.py:73:5:73:39 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_2.py:87:5:87:48 | ControlFlowNode for Attribute() | The following LDAP bind operation is executed without authentication. | +| auth_bad_3.py:19:12:19:43 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication. | +| auth_bad_3.py:33:12:33:57 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication. | +| auth_bad_3.py:46:12:46:55 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication. | +| auth_bad_3.py:60:12:60:42 | ControlFlowNode for Connection() | The following LDAP bind operation is executed without authentication. | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected index 24784f039e7..a2d5f215057 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-522/LDAPInsecureAuth.expected @@ -20,9 +20,9 @@ nodes | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | semmle.label | ControlFlowNode for host | subpaths #select -| ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | $@ is authenticated insecurely. | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | This LDAP host | -| ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | $@ is authenticated insecurely. | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | This LDAP host | -| ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host | -| ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host | -| ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host | -| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | $@ is authenticated insecurely. | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host | +| ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:45:41:45:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. | +| ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | ldap2_remote.py:56:41:56:60 | ControlFlowNode for BinaryExpr | This LDAP host is authenticated insecurely. | +| ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | ldap3_remote.py:101:12:101:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:102:18:102:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | +| ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | ldap3_remote.py:114:12:114:49 | ControlFlowNode for BinaryExpr | ldap3_remote.py:115:18:115:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | +| ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | ldap3_remote.py:126:12:126:31 | ControlFlowNode for BinaryExpr | ldap3_remote.py:127:18:127:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | +| ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | ldap3_remote.py:138:21:138:27 | ControlFlowNode for request | ldap3_remote.py:139:18:139:21 | ControlFlowNode for host | This LDAP host is authenticated insecurely. | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.expected b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.expected index 5f848fb56bb..30438f41083 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-611-SimpleXmlRpcServer/SimpleXmlRpcServer.expected @@ -1 +1 @@ -| xmlrpc_server.py:7:10:7:48 | ControlFlowNode for SimpleXMLRPCServer() | SimpleXMLRPCServer is vulnerable to XML bombs | +| xmlrpc_server.py:7:10:7:48 | ControlFlowNode for SimpleXMLRPCServer() | SimpleXMLRPCServer is vulnerable to XML bombs. | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected index 2922cc9f97e..7a4c8aa5967 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-943/NoSQLInjection.expected @@ -130,15 +130,15 @@ nodes | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict | subpaths #select -| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | -| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | -| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | user-provided value | -| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | $@ NoSQL query contains an unsanitized $@ | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | flask_mongoengine_bad.py:22:34:22:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:19:21:19:27 | ControlFlowNode for request | user-provided value | +| flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | flask_mongoengine_bad.py:30:39:30:59 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | +| flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | flask_pymongo_bad.py:14:31:14:51 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | flask_pymongo_bad.py:11:21:11:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | mongoengine_bad.py:22:26:22:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:18:21:18:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | mongoengine_bad.py:30:26:30:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:26:21:26:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | mongoengine_bad.py:38:26:38:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:34:21:34:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | mongoengine_bad.py:46:26:46:46 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:42:21:42:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | mongoengine_bad.py:53:34:53:44 | ControlFlowNode for json_search | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:50:21:50:27 | ControlFlowNode for request | user-provided value | +| mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | mongoengine_bad.py:61:29:61:49 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | mongoengine_bad.py:57:21:57:27 | ControlFlowNode for request | user-provided value | +| pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | pymongo_test.py:15:42:15:62 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:12:21:12:27 | ControlFlowNode for request | user-provided value | +| pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | pymongo_test.py:33:34:33:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:29:27:29:33 | ControlFlowNode for request | user-provided value | +| pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | pymongo_test.py:43:34:43:73 | ControlFlowNode for Dict | This NoSQL query contains an unsanitized $@. | pymongo_test.py:39:27:39:33 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected index bbcf58067be..dc055e4a08f 100644 --- a/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected +++ b/python/ql/test/library-tests/frameworks/django-orm/ReflectedXss.expected @@ -94,8 +94,8 @@ nodes | testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute | subpaths #select -| testapp/orm_security_tests.py:44:29:44:37 | ControlFlowNode for resp_text | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:44:29:44:37 | ControlFlowNode for resp_text | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | a user-provided value | -| testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | a user-provided value | -| testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | a user-provided value | -| testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | a user-provided value | -| testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to $@. | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | a user-provided value | +| testapp/orm_security_tests.py:44:29:44:37 | ControlFlowNode for resp_text | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:44:29:44:37 | ControlFlowNode for resp_text | Cross-site scripting vulnerability due to a $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | user-provided value | +| testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:48:25:48:57 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | user-provided value | +| testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | testapp/orm_security_tests.py:55:25:55:55 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | testapp/orm_security_tests.py:19:12:19:18 | ControlFlowNode for request | user-provided value | +| testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | testapp/orm_security_tests.py:102:25:102:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to a $@. | testapp/orm_security_tests.py:95:37:95:43 | ControlFlowNode for request | user-provided value | +| testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | testapp/orm_security_tests.py:121:25:121:36 | ControlFlowNode for Attribute | Cross-site scripting vulnerability due to a $@. | testapp/orm_security_tests.py:114:33:114:39 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Classes/subclass-shadowing/SubclassShadowing.expected b/python/ql/test/query-tests/Classes/subclass-shadowing/SubclassShadowing.expected index ae922ef5264..caad71a9a31 100644 --- a/python/ql/test/query-tests/Classes/subclass-shadowing/SubclassShadowing.expected +++ b/python/ql/test/query-tests/Classes/subclass-shadowing/SubclassShadowing.expected @@ -1 +1 @@ -| subclass_shadowing.py:10:5:10:21 | FunctionExpr | Method shadow is shadowed by $@ in super class 'Base'. | subclass_shadowing.py:6:9:6:23 | AssignStmt | an attribute | +| subclass_shadowing.py:10:5:10:21 | FunctionExpr | Method shadow is shadowed by an $@ in super class 'Base'. | subclass_shadowing.py:6:9:6:23 | AssignStmt | attribute | diff --git a/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.expected b/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.expected index 1aebf13f2bc..6ea6b538a23 100644 --- a/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.expected +++ b/python/ql/test/query-tests/Classes/undefined-attribute/MaybeUndefinedClassAttribute.expected @@ -1,4 +1,4 @@ -| undefined_attribute.py:27:16:27:29 | Attribute | Attribute 'may_exist' is not defined in the class body nor in the __init__() method, but it is defined $@ | undefined_attribute.py:11:9:11:22 | Attribute | here | -| undefined_attribute.py:184:16:184:32 | Attribute | Attribute 'return_queue' is not defined in the class body nor in the __init__() method, but it is defined $@ | undefined_attribute.py:181:13:181:29 | Attribute | here | -| undefined_attribute.py:257:16:257:31 | Attribute | Attribute 'glance_host' is not defined in the class body nor in the __init__() method, but it is defined $@ | undefined_attribute.py:262:13:262:28 | Attribute | here | -| undefined_attribute.py:258:16:258:31 | Attribute | Attribute 'glance_port' is not defined in the class body nor in the __init__() method, but it is defined $@ | undefined_attribute.py:263:10:263:25 | Attribute | here | +| undefined_attribute.py:27:16:27:29 | Attribute | Attribute 'may_exist' is not defined in the class body nor in the __init__() method, but it is defined $@. | undefined_attribute.py:11:9:11:22 | Attribute | here | +| undefined_attribute.py:184:16:184:32 | Attribute | Attribute 'return_queue' is not defined in the class body nor in the __init__() method, but it is defined $@. | undefined_attribute.py:181:13:181:29 | Attribute | here | +| undefined_attribute.py:257:16:257:31 | Attribute | Attribute 'glance_host' is not defined in the class body nor in the __init__() method, but it is defined $@. | undefined_attribute.py:262:13:262:28 | Attribute | here | +| undefined_attribute.py:258:16:258:31 | Attribute | Attribute 'glance_port' is not defined in the class body nor in the __init__() method, but it is defined $@. | undefined_attribute.py:263:10:263:25 | Attribute | here | diff --git a/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.expected b/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.expected index deb82710cf5..3f62e1c256c 100644 --- a/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.expected +++ b/python/ql/test/query-tests/Classes/undefined-attribute/UndefinedClassAttribute.expected @@ -1,4 +1,4 @@ -| undefined_attribute.py:24:16:24:30 | Attribute | Attribute 'not_exists' is not defined in either the class body or in any method | -| undefined_attribute.py:109:16:109:21 | Attribute | Attribute 'y' is not defined in either the class body or in any method | -| undefined_attribute.py:250:16:250:31 | Attribute | Attribute 'glance_host' is not defined in either the class body or in any method | -| undefined_attribute.py:251:16:251:31 | Attribute | Attribute 'glance_port' is not defined in either the class body or in any method | +| undefined_attribute.py:24:16:24:30 | Attribute | Attribute 'not_exists' is not defined in either the class body or in any method. | +| undefined_attribute.py:109:16:109:21 | Attribute | Attribute 'y' is not defined in either the class body or in any method. | +| undefined_attribute.py:250:16:250:31 | Attribute | Attribute 'glance_host' is not defined in either the class body or in any method. | +| undefined_attribute.py:251:16:251:31 | Attribute | Attribute 'glance_port' is not defined in either the class body or in any method. | diff --git a/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.expected b/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.expected index f2f9a79a657..a0b6ebbfef6 100644 --- a/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.expected +++ b/python/ql/test/query-tests/Expressions/comparisons/UselessComparisonTest.expected @@ -1,10 +1,10 @@ -| test.py:6:8:6:13 | Compare | Test is always true, because of $@ | test.py:4:8:4:12 | Compare | this condition | -| test.py:8:8:8:13 | Compare | Test is always true, because of $@ | test.py:4:17:4:21 | Compare | this condition | -| test.py:13:16:13:22 | Compare | Test is always false, because of $@ | test.py:11:12:11:17 | Compare | this condition | -| test.py:15:14:15:18 | Compare | Test is always true, because of $@ | test.py:11:12:11:17 | Compare | this condition | -| test.py:27:8:27:13 | Compare | Test is always true, because of $@ | test.py:25:8:25:12 | Compare | this condition | -| test.py:30:12:30:18 | Compare | Test is always false, because of $@ | test.py:25:17:25:23 | Compare | this condition | -| test.py:49:8:49:12 | Compare | Test is always false, because of $@ | test.py:47:8:47:50 | Compare | this condition | -| test.py:73:14:73:26 | Compare | Test is always true, because of $@ | test.py:71:8:71:19 | Compare | this condition | -| test.py:79:14:79:46 | Compare | Test is always true, because of $@ | test.py:77:8:77:19 | Compare | this condition | -| test.py:85:10:85:42 | Compare | Test is always true, because of $@ | test.py:83:8:83:19 | Compare | this condition | +| test.py:6:8:6:13 | Compare | Test is always true, because of $@. | test.py:4:8:4:12 | Compare | this condition | +| test.py:8:8:8:13 | Compare | Test is always true, because of $@. | test.py:4:17:4:21 | Compare | this condition | +| test.py:13:16:13:22 | Compare | Test is always false, because of $@. | test.py:11:12:11:17 | Compare | this condition | +| test.py:15:14:15:18 | Compare | Test is always true, because of $@. | test.py:11:12:11:17 | Compare | this condition | +| test.py:27:8:27:13 | Compare | Test is always true, because of $@. | test.py:25:8:25:12 | Compare | this condition | +| test.py:30:12:30:18 | Compare | Test is always false, because of $@. | test.py:25:17:25:23 | Compare | this condition | +| test.py:49:8:49:12 | Compare | Test is always false, because of $@. | test.py:47:8:47:50 | Compare | this condition | +| test.py:73:14:73:26 | Compare | Test is always true, because of $@. | test.py:71:8:71:19 | Compare | this condition | +| test.py:79:14:79:46 | Compare | Test is always true, because of $@. | test.py:77:8:77:19 | Compare | this condition | +| test.py:85:10:85:42 | Compare | Test is always true, because of $@. | test.py:83:8:83:19 | Compare | this condition | diff --git a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.expected b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.expected index 71f4137f1ef..527a30c9b3f 100644 --- a/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.expected +++ b/python/ql/test/query-tests/Functions/ModificationOfParameterWithDefault/ModificationOfParameterWithDefault.expected @@ -83,26 +83,26 @@ nodes | test.py:147:9:147:9 | ControlFlowNode for l | semmle.label | ControlFlowNode for l | subpaths #select -| test.py:3:5:3:5 | ControlFlowNode for l | test.py:2:12:2:12 | ControlFlowNode for l | test.py:3:5:3:5 | ControlFlowNode for l | This expression mutates $@. | test.py:2:12:2:12 | ControlFlowNode for l | a default value | -| test.py:8:5:8:5 | ControlFlowNode for l | test.py:7:11:7:11 | ControlFlowNode for l | test.py:8:5:8:5 | ControlFlowNode for l | This expression mutates $@. | test.py:7:11:7:11 | ControlFlowNode for l | a default value | -| test.py:13:9:13:9 | ControlFlowNode for l | test.py:12:14:12:14 | ControlFlowNode for l | test.py:13:9:13:9 | ControlFlowNode for l | This expression mutates $@. | test.py:12:14:12:14 | ControlFlowNode for l | a default value | -| test.py:18:5:18:5 | ControlFlowNode for l | test.py:17:15:17:15 | ControlFlowNode for l | test.py:18:5:18:5 | ControlFlowNode for l | This expression mutates $@. | test.py:17:15:17:15 | ControlFlowNode for l | a default value | -| test.py:23:5:23:5 | ControlFlowNode for l | test.py:22:15:22:15 | ControlFlowNode for l | test.py:23:5:23:5 | ControlFlowNode for l | This expression mutates $@. | test.py:22:15:22:15 | ControlFlowNode for l | a default value | -| test.py:28:5:28:5 | ControlFlowNode for l | test.py:27:12:27:12 | ControlFlowNode for l | test.py:28:5:28:5 | ControlFlowNode for l | This expression mutates $@. | test.py:27:12:27:12 | ControlFlowNode for l | a default value | -| test.py:39:5:39:5 | ControlFlowNode for l | test.py:43:14:43:14 | ControlFlowNode for l | test.py:39:5:39:5 | ControlFlowNode for l | This expression mutates $@. | test.py:43:14:43:14 | ControlFlowNode for l | a default value | -| test.py:49:5:49:5 | ControlFlowNode for l | test.py:48:14:48:14 | ControlFlowNode for l | test.py:49:5:49:5 | ControlFlowNode for l | This expression mutates $@. | test.py:48:14:48:14 | ControlFlowNode for l | a default value | -| test.py:54:5:54:5 | ControlFlowNode for d | test.py:53:10:53:10 | ControlFlowNode for d | test.py:54:5:54:5 | ControlFlowNode for d | This expression mutates $@. | test.py:53:10:53:10 | ControlFlowNode for d | a default value | -| test.py:59:5:59:5 | ControlFlowNode for d | test.py:58:19:58:19 | ControlFlowNode for d | test.py:59:5:59:5 | ControlFlowNode for d | This expression mutates $@. | test.py:58:19:58:19 | ControlFlowNode for d | a default value | -| test.py:64:5:64:5 | ControlFlowNode for d | test.py:63:28:63:28 | ControlFlowNode for d | test.py:64:5:64:5 | ControlFlowNode for d | This expression mutates $@. | test.py:63:28:63:28 | ControlFlowNode for d | a default value | -| test.py:68:5:68:5 | ControlFlowNode for d | test.py:72:19:72:19 | ControlFlowNode for d | test.py:68:5:68:5 | ControlFlowNode for d | This expression mutates $@. | test.py:72:19:72:19 | ControlFlowNode for d | a default value | -| test.py:78:5:78:5 | ControlFlowNode for d | test.py:77:17:77:17 | ControlFlowNode for d | test.py:78:5:78:5 | ControlFlowNode for d | This expression mutates $@. | test.py:77:17:77:17 | ControlFlowNode for d | a default value | -| test.py:83:5:83:5 | ControlFlowNode for d | test.py:82:26:82:26 | ControlFlowNode for d | test.py:83:5:83:5 | ControlFlowNode for d | This expression mutates $@. | test.py:82:26:82:26 | ControlFlowNode for d | a default value | -| test.py:88:5:88:5 | ControlFlowNode for d | test.py:87:35:87:35 | ControlFlowNode for d | test.py:88:5:88:5 | ControlFlowNode for d | This expression mutates $@. | test.py:87:35:87:35 | ControlFlowNode for d | a default value | -| test.py:92:5:92:5 | ControlFlowNode for d | test.py:96:26:96:26 | ControlFlowNode for d | test.py:92:5:92:5 | ControlFlowNode for d | This expression mutates $@. | test.py:96:26:96:26 | ControlFlowNode for d | a default value | -| test.py:109:9:109:9 | ControlFlowNode for d | test.py:108:14:108:14 | ControlFlowNode for d | test.py:109:9:109:9 | ControlFlowNode for d | This expression mutates $@. | test.py:108:14:108:14 | ControlFlowNode for d | a default value | -| test.py:115:5:115:5 | ControlFlowNode for d | test.py:113:20:113:20 | ControlFlowNode for d | test.py:115:5:115:5 | ControlFlowNode for d | This expression mutates $@. | test.py:113:20:113:20 | ControlFlowNode for d | a default value | -| test.py:121:5:121:5 | ControlFlowNode for d | test.py:119:29:119:29 | ControlFlowNode for d | test.py:121:5:121:5 | ControlFlowNode for d | This expression mutates $@. | test.py:119:29:119:29 | ControlFlowNode for d | a default value | -| test.py:128:9:128:9 | ControlFlowNode for l | test.py:124:15:124:15 | ControlFlowNode for l | test.py:128:9:128:9 | ControlFlowNode for l | This expression mutates $@. | test.py:124:15:124:15 | ControlFlowNode for l | a default value | -| test.py:135:9:135:9 | ControlFlowNode for l | test.py:131:23:131:23 | ControlFlowNode for l | test.py:135:9:135:9 | ControlFlowNode for l | This expression mutates $@. | test.py:131:23:131:23 | ControlFlowNode for l | a default value | -| test.py:140:9:140:9 | ControlFlowNode for l | test.py:138:15:138:15 | ControlFlowNode for l | test.py:140:9:140:9 | ControlFlowNode for l | This expression mutates $@. | test.py:138:15:138:15 | ControlFlowNode for l | a default value | -| test.py:147:9:147:9 | ControlFlowNode for l | test.py:145:23:145:23 | ControlFlowNode for l | test.py:147:9:147:9 | ControlFlowNode for l | This expression mutates $@. | test.py:145:23:145:23 | ControlFlowNode for l | a default value | +| test.py:3:5:3:5 | ControlFlowNode for l | test.py:2:12:2:12 | ControlFlowNode for l | test.py:3:5:3:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:2:12:2:12 | ControlFlowNode for l | default value | +| test.py:8:5:8:5 | ControlFlowNode for l | test.py:7:11:7:11 | ControlFlowNode for l | test.py:8:5:8:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:7:11:7:11 | ControlFlowNode for l | default value | +| test.py:13:9:13:9 | ControlFlowNode for l | test.py:12:14:12:14 | ControlFlowNode for l | test.py:13:9:13:9 | ControlFlowNode for l | This expression mutates a $@. | test.py:12:14:12:14 | ControlFlowNode for l | default value | +| test.py:18:5:18:5 | ControlFlowNode for l | test.py:17:15:17:15 | ControlFlowNode for l | test.py:18:5:18:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:17:15:17:15 | ControlFlowNode for l | default value | +| test.py:23:5:23:5 | ControlFlowNode for l | test.py:22:15:22:15 | ControlFlowNode for l | test.py:23:5:23:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:22:15:22:15 | ControlFlowNode for l | default value | +| test.py:28:5:28:5 | ControlFlowNode for l | test.py:27:12:27:12 | ControlFlowNode for l | test.py:28:5:28:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:27:12:27:12 | ControlFlowNode for l | default value | +| test.py:39:5:39:5 | ControlFlowNode for l | test.py:43:14:43:14 | ControlFlowNode for l | test.py:39:5:39:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:43:14:43:14 | ControlFlowNode for l | default value | +| test.py:49:5:49:5 | ControlFlowNode for l | test.py:48:14:48:14 | ControlFlowNode for l | test.py:49:5:49:5 | ControlFlowNode for l | This expression mutates a $@. | test.py:48:14:48:14 | ControlFlowNode for l | default value | +| test.py:54:5:54:5 | ControlFlowNode for d | test.py:53:10:53:10 | ControlFlowNode for d | test.py:54:5:54:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:53:10:53:10 | ControlFlowNode for d | default value | +| test.py:59:5:59:5 | ControlFlowNode for d | test.py:58:19:58:19 | ControlFlowNode for d | test.py:59:5:59:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:58:19:58:19 | ControlFlowNode for d | default value | +| test.py:64:5:64:5 | ControlFlowNode for d | test.py:63:28:63:28 | ControlFlowNode for d | test.py:64:5:64:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:63:28:63:28 | ControlFlowNode for d | default value | +| test.py:68:5:68:5 | ControlFlowNode for d | test.py:72:19:72:19 | ControlFlowNode for d | test.py:68:5:68:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:72:19:72:19 | ControlFlowNode for d | default value | +| test.py:78:5:78:5 | ControlFlowNode for d | test.py:77:17:77:17 | ControlFlowNode for d | test.py:78:5:78:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:77:17:77:17 | ControlFlowNode for d | default value | +| test.py:83:5:83:5 | ControlFlowNode for d | test.py:82:26:82:26 | ControlFlowNode for d | test.py:83:5:83:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:82:26:82:26 | ControlFlowNode for d | default value | +| test.py:88:5:88:5 | ControlFlowNode for d | test.py:87:35:87:35 | ControlFlowNode for d | test.py:88:5:88:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:87:35:87:35 | ControlFlowNode for d | default value | +| test.py:92:5:92:5 | ControlFlowNode for d | test.py:96:26:96:26 | ControlFlowNode for d | test.py:92:5:92:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:96:26:96:26 | ControlFlowNode for d | default value | +| test.py:109:9:109:9 | ControlFlowNode for d | test.py:108:14:108:14 | ControlFlowNode for d | test.py:109:9:109:9 | ControlFlowNode for d | This expression mutates a $@. | test.py:108:14:108:14 | ControlFlowNode for d | default value | +| test.py:115:5:115:5 | ControlFlowNode for d | test.py:113:20:113:20 | ControlFlowNode for d | test.py:115:5:115:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:113:20:113:20 | ControlFlowNode for d | default value | +| test.py:121:5:121:5 | ControlFlowNode for d | test.py:119:29:119:29 | ControlFlowNode for d | test.py:121:5:121:5 | ControlFlowNode for d | This expression mutates a $@. | test.py:119:29:119:29 | ControlFlowNode for d | default value | +| test.py:128:9:128:9 | ControlFlowNode for l | test.py:124:15:124:15 | ControlFlowNode for l | test.py:128:9:128:9 | ControlFlowNode for l | This expression mutates a $@. | test.py:124:15:124:15 | ControlFlowNode for l | default value | +| test.py:135:9:135:9 | ControlFlowNode for l | test.py:131:23:131:23 | ControlFlowNode for l | test.py:135:9:135:9 | ControlFlowNode for l | This expression mutates a $@. | test.py:131:23:131:23 | ControlFlowNode for l | default value | +| test.py:140:9:140:9 | ControlFlowNode for l | test.py:138:15:138:15 | ControlFlowNode for l | test.py:140:9:140:9 | ControlFlowNode for l | This expression mutates a $@. | test.py:138:15:138:15 | ControlFlowNode for l | default value | +| test.py:147:9:147:9 | ControlFlowNode for l | test.py:145:23:145:23 | ControlFlowNode for l | test.py:147:9:147:9 | ControlFlowNode for l | This expression mutates a $@. | test.py:145:23:145:23 | ControlFlowNode for l | default value | diff --git a/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.expected b/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.expected index c40120862c3..d2fa86f6f27 100644 --- a/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.expected +++ b/python/ql/test/query-tests/Functions/general/DeprecatedSliceMethod.expected @@ -1,3 +1,3 @@ -| functions_test.py:99:5:99:40 | Function DeprecatedSliceMethods.__getslice__ | __getslice__ method has been deprecated since Python 2.0 | -| functions_test.py:102:5:102:47 | Function DeprecatedSliceMethods.__setslice__ | __setslice__ method has been deprecated since Python 2.0 | -| functions_test.py:105:5:105:40 | Function DeprecatedSliceMethods.__delslice__ | __delslice__ method has been deprecated since Python 2.0 | +| functions_test.py:99:5:99:40 | Function DeprecatedSliceMethods.__getslice__ | __getslice__ method has been deprecated since Python 2.0. | +| functions_test.py:102:5:102:47 | Function DeprecatedSliceMethods.__setslice__ | __setslice__ method has been deprecated since Python 2.0. | +| functions_test.py:105:5:105:40 | Function DeprecatedSliceMethods.__delslice__ | __delslice__ method has been deprecated since Python 2.0. | diff --git a/python/ql/test/query-tests/Functions/general/ModificationOfParameterWithDefault.expected b/python/ql/test/query-tests/Functions/general/ModificationOfParameterWithDefault.expected index a2eff0d757f..02111ef0e5e 100644 --- a/python/ql/test/query-tests/Functions/general/ModificationOfParameterWithDefault.expected +++ b/python/ql/test/query-tests/Functions/general/ModificationOfParameterWithDefault.expected @@ -34,11 +34,11 @@ nodes | functions_test.py:196:28:196:28 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | subpaths #select -| functions_test.py:40:5:40:5 | ControlFlowNode for x | functions_test.py:39:9:39:9 | ControlFlowNode for x | functions_test.py:40:5:40:5 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:39:9:39:9 | ControlFlowNode for x | a default value | -| functions_test.py:134:5:134:5 | ControlFlowNode for x | functions_test.py:133:15:133:15 | ControlFlowNode for x | functions_test.py:134:5:134:5 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:133:15:133:15 | ControlFlowNode for x | a default value | -| functions_test.py:152:5:152:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:152:5:152:5 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:157:27:157:27 | ControlFlowNode for y | a default value | -| functions_test.py:155:5:155:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:155:5:155:5 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:157:27:157:27 | ControlFlowNode for y | a default value | -| functions_test.py:183:9:183:9 | ControlFlowNode for x | functions_test.py:192:18:192:18 | ControlFlowNode for x | functions_test.py:183:9:183:9 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:192:18:192:18 | ControlFlowNode for x | a default value | -| functions_test.py:183:9:183:9 | ControlFlowNode for x | functions_test.py:195:18:195:18 | ControlFlowNode for x | functions_test.py:183:9:183:9 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:195:18:195:18 | ControlFlowNode for x | a default value | -| functions_test.py:185:9:185:9 | ControlFlowNode for x | functions_test.py:192:18:192:18 | ControlFlowNode for x | functions_test.py:185:9:185:9 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:192:18:192:18 | ControlFlowNode for x | a default value | -| functions_test.py:185:9:185:9 | ControlFlowNode for x | functions_test.py:195:18:195:18 | ControlFlowNode for x | functions_test.py:185:9:185:9 | ControlFlowNode for x | This expression mutates $@. | functions_test.py:195:18:195:18 | ControlFlowNode for x | a default value | +| functions_test.py:40:5:40:5 | ControlFlowNode for x | functions_test.py:39:9:39:9 | ControlFlowNode for x | functions_test.py:40:5:40:5 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:39:9:39:9 | ControlFlowNode for x | default value | +| functions_test.py:134:5:134:5 | ControlFlowNode for x | functions_test.py:133:15:133:15 | ControlFlowNode for x | functions_test.py:134:5:134:5 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:133:15:133:15 | ControlFlowNode for x | default value | +| functions_test.py:152:5:152:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:152:5:152:5 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:157:27:157:27 | ControlFlowNode for y | default value | +| functions_test.py:155:5:155:5 | ControlFlowNode for x | functions_test.py:157:27:157:27 | ControlFlowNode for y | functions_test.py:155:5:155:5 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:157:27:157:27 | ControlFlowNode for y | default value | +| functions_test.py:183:9:183:9 | ControlFlowNode for x | functions_test.py:192:18:192:18 | ControlFlowNode for x | functions_test.py:183:9:183:9 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:192:18:192:18 | ControlFlowNode for x | default value | +| functions_test.py:183:9:183:9 | ControlFlowNode for x | functions_test.py:195:18:195:18 | ControlFlowNode for x | functions_test.py:183:9:183:9 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:195:18:195:18 | ControlFlowNode for x | default value | +| functions_test.py:185:9:185:9 | ControlFlowNode for x | functions_test.py:192:18:192:18 | ControlFlowNode for x | functions_test.py:185:9:185:9 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:192:18:192:18 | ControlFlowNode for x | default value | +| functions_test.py:185:9:185:9 | ControlFlowNode for x | functions_test.py:195:18:195:18 | ControlFlowNode for x | functions_test.py:185:9:185:9 | ControlFlowNode for x | This expression mutates a $@. | functions_test.py:195:18:195:18 | ControlFlowNode for x | default value | diff --git a/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.expected b/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.expected index 54a74971d37..ca99ca1ae9c 100644 --- a/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.expected +++ b/python/ql/test/query-tests/Functions/return_values/UseImplicitNoneReturnValue.expected @@ -1,2 +1,2 @@ -| functions_test.py:77:9:77:20 | do_nothing() | The result of '$@' is used even though it is always None. | functions_test.py:83:1:83:17 | Function do_nothing | do_nothing | -| functions_test.py:234:16:234:27 | do_nothing() | The result of '$@' is used even though it is always None. | functions_test.py:83:1:83:17 | Function do_nothing | do_nothing | +| functions_test.py:77:9:77:20 | do_nothing() | The result of $@ is used even though it is always None. | functions_test.py:83:1:83:17 | Function do_nothing | do_nothing | +| functions_test.py:234:16:234:27 | do_nothing() | The result of $@ is used even though it is always None. | functions_test.py:83:1:83:17 | Function do_nothing | do_nothing | diff --git a/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.expected b/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.expected index 620a54a4973..a9e372efb21 100644 --- a/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.expected +++ b/python/ql/test/query-tests/Imports/PyCheckerTests/ImportandImportFrom.expected @@ -1,2 +1,2 @@ -| imports_test.py:4:1:4:19 | Import | Module 'test_module2' is imported with both 'import' and 'import from' | -| pkg_notok/__init__.py:4:1:4:16 | Import | Module 'pkg_notok' is imported with both 'import' and 'import from' | +| imports_test.py:4:1:4:19 | Import | Module 'test_module2' is imported with both 'import' and 'import from'. | +| pkg_notok/__init__.py:4:1:4:16 | Import | Module 'pkg_notok' is imported with both 'import' and 'import from'. | diff --git a/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.expected b/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.expected index 562cc12c51e..bc72acb5a01 100644 --- a/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.expected +++ b/python/ql/test/query-tests/Imports/general/ImportShadowedByLoopVar.expected @@ -1 +1 @@ -| imports_test.py:16:5:16:10 | module | Loop variable 'module' shadows an import | +| imports_test.py:16:5:16:10 | module | Loop variable 'module' shadows an import. | diff --git a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected index d29bc2b9b5f..6257baddfb8 100644 --- a/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected +++ b/python/ql/test/query-tests/Imports/general/ImportStarUsed.expected @@ -1,3 +1,3 @@ -| imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace | -| imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace | -| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace | +| imports_test.py:21:1:21:20 | from module import * | Using 'from ... import *' pollutes the namespace. | +| imports_test.py:22:1:22:32 | from module_without_all import * | Using 'from ... import *' pollutes the namespace. | +| imports_test.py:65:1:65:40 | from module_that_does_not_exist import * | Using 'from ... import *' pollutes the namespace. | diff --git a/python/ql/test/query-tests/Numerics/Pythagorean.expected b/python/ql/test/query-tests/Numerics/Pythagorean.expected index 2f5ef6ff562..a289983af53 100644 --- a/python/ql/test/query-tests/Numerics/Pythagorean.expected +++ b/python/ql/test/query-tests/Numerics/Pythagorean.expected @@ -1,3 +1,3 @@ -| pythagorean_test.py:6:12:6:28 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics | -| pythagorean_test.py:9:12:9:26 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics | -| pythagorean_test.py:14:12:14:24 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics | +| pythagorean_test.py:6:12:6:28 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics. | +| pythagorean_test.py:9:12:9:26 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics. | +| pythagorean_test.py:14:12:14:24 | ControlFlowNode for sqrt() | Pythagorean calculation with sub-optimal numerics. | diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected index 4b2ba67ecda..5eb9f16605c 100644 --- a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected +++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected @@ -1,2 +1,2 @@ -| urltest.py:9:8:9:30 | Compare | '$@' may be at an arbitrary position in the sanitized URL. | urltest.py:9:8:9:20 | Str | example.com | -| urltest.py:15:8:15:37 | Attribute() | '$@' may be at an arbitrary position in the sanitized URL. | urltest.py:15:24:15:36 | Str | example.com | +| urltest.py:9:8:9:30 | Compare | $@ may be at an arbitrary position in the sanitized URL. | urltest.py:9:8:9:20 | Str | example.com | +| urltest.py:15:8:15:37 | Attribute() | $@ may be at an arbitrary position in the sanitized URL. | urltest.py:15:24:15:36 | Str | example.com | diff --git a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected index 49c173f6fe9..a206bf683cf 100644 --- a/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022-PathInjection/PathInjection.expected @@ -122,21 +122,21 @@ subpaths | test.py:25:19:25:19 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:25:9:25:20 | ControlFlowNode for normalize() | | test.py:48:23:48:23 | ControlFlowNode for x | test.py:12:15:12:15 | ControlFlowNode for x | test.py:13:12:13:30 | ControlFlowNode for Attribute() | test.py:48:13:48:24 | ControlFlowNode for normalize() | #select -| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | a user-provided value | -| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:19:16:19:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:27:16:27:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:46:16:46:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on $@. | path_injection.py:63:16:63:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on $@. | path_injection.py:84:16:84:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | a user-provided value | -| path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | a user-provided value | -| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:107:16:107:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:118:16:118:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on $@. | path_injection.py:129:16:129:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on $@. | path_injection.py:138:16:138:22 | ControlFlowNode for request | a user-provided value | -| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on $@. | path_injection.py:149:16:149:22 | ControlFlowNode for request | a user-provided value | -| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | -| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on $@. | test.py:9:12:9:18 | ControlFlowNode for request | a user-provided value | +| flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | flask_path_injection.py:21:32:21:38 | ControlFlowNode for dirname | This path depends on a $@. | flask_path_injection.py:19:15:19:21 | ControlFlowNode for request | user-provided value | +| path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | path_injection.py:12:16:12:22 | ControlFlowNode for request | path_injection.py:13:14:13:47 | ControlFlowNode for Attribute() | This path depends on a $@. | path_injection.py:12:16:12:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:21:14:21:18 | ControlFlowNode for npath | path_injection.py:19:16:19:22 | ControlFlowNode for request | path_injection.py:21:14:21:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:19:16:19:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:31:14:31:18 | ControlFlowNode for npath | path_injection.py:27:16:27:22 | ControlFlowNode for request | path_injection.py:31:14:31:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:27:16:27:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:48:14:48:18 | ControlFlowNode for npath | path_injection.py:46:16:46:22 | ControlFlowNode for request | path_injection.py:48:14:48:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:46:16:46:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:65:14:65:18 | ControlFlowNode for npath | path_injection.py:63:16:63:22 | ControlFlowNode for request | path_injection.py:65:14:65:18 | ControlFlowNode for npath | This path depends on a $@. | path_injection.py:63:16:63:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | path_injection.py:84:16:84:22 | ControlFlowNode for request | path_injection.py:87:18:87:37 | ControlFlowNode for possibly_unsafe_path | This path depends on a $@. | path_injection.py:84:16:84:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:94:14:94:17 | ControlFlowNode for path | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | path_injection.py:94:14:94:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:91:20:91:25 | ControlFlowNode for foo_id | user-provided value | +| path_injection.py:102:14:102:17 | ControlFlowNode for path | path_injection.py:98:20:98:22 | ControlFlowNode for foo | path_injection.py:102:14:102:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:98:20:98:22 | ControlFlowNode for foo | user-provided value | +| path_injection.py:113:14:113:17 | ControlFlowNode for path | path_injection.py:107:16:107:22 | ControlFlowNode for request | path_injection.py:113:14:113:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:107:16:107:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:124:14:124:17 | ControlFlowNode for path | path_injection.py:118:16:118:22 | ControlFlowNode for request | path_injection.py:124:14:124:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:118:16:118:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | path_injection.py:129:16:129:22 | ControlFlowNode for request | path_injection.py:132:14:132:22 | ControlFlowNode for sanitized | This path depends on a $@. | path_injection.py:129:16:129:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:142:14:142:17 | ControlFlowNode for path | path_injection.py:138:16:138:22 | ControlFlowNode for request | path_injection.py:142:14:142:17 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:138:16:138:22 | ControlFlowNode for request | user-provided value | +| path_injection.py:152:18:152:21 | ControlFlowNode for path | path_injection.py:149:16:149:22 | ControlFlowNode for request | path_injection.py:152:18:152:21 | ControlFlowNode for path | This path depends on a $@. | path_injection.py:149:16:149:22 | ControlFlowNode for request | user-provided value | +| test.py:19:10:19:10 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:19:10:19:10 | ControlFlowNode for x | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | +| test.py:26:10:26:10 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:26:10:26:10 | ControlFlowNode for y | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | +| test.py:33:14:33:14 | ControlFlowNode for x | test.py:9:12:9:18 | ControlFlowNode for request | test.py:33:14:33:14 | ControlFlowNode for x | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | +| test.py:49:14:49:14 | ControlFlowNode for y | test.py:9:12:9:18 | ControlFlowNode for request | test.py:49:14:49:14 | ControlFlowNode for y | This path depends on a $@. | test.py:9:12:9:18 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected index 15d62252945..d10399cc7ca 100644 --- a/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected +++ b/python/ql/test/query-tests/Security/CWE-022-TarSlip/TarSlip.expected @@ -23,8 +23,8 @@ nodes | tarslip.py:61:21:61:25 | ControlFlowNode for entry | semmle.label | ControlFlowNode for entry | subpaths #select -| tarslip.py:15:1:15:3 | ControlFlowNode for tar | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | tarslip.py:15:1:15:3 | ControlFlowNode for tar | This file extraction depends on $@ | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | a potentially untrusted source | -| tarslip.py:20:17:20:21 | ControlFlowNode for entry | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | tarslip.py:20:17:20:21 | ControlFlowNode for entry | This file extraction depends on $@ | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | a potentially untrusted source | -| tarslip.py:39:17:39:21 | ControlFlowNode for entry | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | tarslip.py:39:17:39:21 | ControlFlowNode for entry | This file extraction depends on $@ | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | a potentially untrusted source | -| tarslip.py:43:24:43:26 | ControlFlowNode for tar | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | tarslip.py:43:24:43:26 | ControlFlowNode for tar | This file extraction depends on $@ | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | a potentially untrusted source | -| tarslip.py:61:21:61:25 | ControlFlowNode for entry | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | tarslip.py:61:21:61:25 | ControlFlowNode for entry | This file extraction depends on $@ | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | a potentially untrusted source | +| tarslip.py:15:1:15:3 | ControlFlowNode for tar | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | tarslip.py:15:1:15:3 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:14:7:14:39 | ControlFlowNode for Attribute() | potentially untrusted source | +| tarslip.py:20:17:20:21 | ControlFlowNode for entry | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | tarslip.py:20:17:20:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:18:7:18:39 | ControlFlowNode for Attribute() | potentially untrusted source | +| tarslip.py:39:17:39:21 | ControlFlowNode for entry | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | tarslip.py:39:17:39:21 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:35:7:35:39 | ControlFlowNode for Attribute() | potentially untrusted source | +| tarslip.py:43:24:43:26 | ControlFlowNode for tar | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | tarslip.py:43:24:43:26 | ControlFlowNode for tar | This file extraction depends on a $@. | tarslip.py:42:7:42:39 | ControlFlowNode for Attribute() | potentially untrusted source | +| tarslip.py:61:21:61:25 | ControlFlowNode for entry | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | tarslip.py:61:21:61:25 | ControlFlowNode for entry | This file extraction depends on a $@. | tarslip.py:58:7:58:39 | ControlFlowNode for Attribute() | potentially untrusted source | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected index 8d26b3f6d5c..8930b1a067c 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection-py2/CommandInjection.expected @@ -23,12 +23,12 @@ nodes | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | +| command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:19:15:19:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:15:20:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:21:15:21:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:23:20:23:32 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:25:19:25:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:26:19:26:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:27:19:27:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:28:19:28:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:29:19:29:31 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected index cce39a976db..3f072d83d2a 100644 --- a/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078-CommandInjection/CommandInjection.expected @@ -52,16 +52,16 @@ nodes | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on $@. | command_injection.py:25:11:25:17 | ControlFlowNode for request | a user-provided value | -| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:31:13:31:19 | ControlFlowNode for request | a user-provided value | -| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | a user-provided value | -| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:71:12:71:18 | ControlFlowNode for request | a user-provided value | -| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on $@. | command_injection.py:78:12:78:18 | ControlFlowNode for request | a user-provided value | +| command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | command_injection.py:11:13:11:19 | ControlFlowNode for request | command_injection.py:13:15:13:27 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:11:13:11:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | command_injection.py:18:13:18:19 | ControlFlowNode for request | command_injection.py:20:22:20:34 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:18:13:18:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:26:23:26:25 | ControlFlowNode for cmd | command_injection.py:25:11:25:17 | ControlFlowNode for request | command_injection.py:26:23:26:25 | ControlFlowNode for cmd | This command line depends on a $@. | command_injection.py:25:11:25:17 | ControlFlowNode for request | user-provided value | +| command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | command_injection.py:31:13:31:19 | ControlFlowNode for request | command_injection.py:33:14:33:26 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:31:13:31:19 | ControlFlowNode for request | user-provided value | +| command_injection.py:41:15:41:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:41:15:41:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:42:15:42:21 | ControlFlowNode for command | command_injection.py:38:15:38:21 | ControlFlowNode for request | command_injection.py:42:15:42:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:38:15:38:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:55:15:55:21 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:55:15:55:21 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:56:14:56:20 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:56:14:56:20 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:57:21:57:27 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:57:21:57:27 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:58:27:58:33 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:58:27:58:33 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:59:20:59:26 | ControlFlowNode for command | command_injection.py:54:15:54:21 | ControlFlowNode for request | command_injection.py:59:20:59:26 | ControlFlowNode for command | This command line depends on a $@. | command_injection.py:54:15:54:21 | ControlFlowNode for request | user-provided value | +| command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | command_injection.py:71:12:71:18 | ControlFlowNode for request | command_injection.py:73:19:73:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:71:12:71:18 | ControlFlowNode for request | user-provided value | +| command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | command_injection.py:78:12:78:18 | ControlFlowNode for request | command_injection.py:80:19:80:30 | ControlFlowNode for BinaryExpr | This command line depends on a $@. | command_injection.py:78:12:78:18 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected index 39c2bb3778f..00f98fbaa6c 100644 --- a/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected +++ b/python/ql/test/query-tests/Security/CWE-079-ReflectedXss/ReflectedXss.expected @@ -17,6 +17,6 @@ nodes | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() | subpaths #select -| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to $@. | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | a user-provided value | -| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | a user-provided value | -| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to $@. | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | a user-provided value | +| reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | reflected_xss.py:10:26:10:53 | ControlFlowNode for BinaryExpr | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:9:18:9:24 | ControlFlowNode for request | user-provided value | +| reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | reflected_xss.py:22:26:22:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:21:23:21:29 | ControlFlowNode for request | user-provided value | +| reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | reflected_xss.py:28:26:28:41 | ControlFlowNode for Attribute() | Cross-site scripting vulnerability due to a $@. | reflected_xss.py:27:23:27:29 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected index ed4c3e3d313..46379fcbbc4 100644 --- a/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-089-SqlInjection/SqlInjection.expected @@ -36,19 +36,19 @@ nodes | sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | semmle.label | ControlFlowNode for username | subpaths #select -| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | a user-provided value | -| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | a user-provided value | -| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | a user-provided value | -| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | This SQL query depends on $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | -| sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | This SQL query depends on $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | a user-provided value | +| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value | +| sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:24:38:24:95 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value | +| sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:25:26:25:83 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value | +| sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:26:28:26:85 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:27:28:27:87 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:31:50:31:72 | ControlFlowNode for Attribute() | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:41:26:41:33 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:42:31:42:38 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:43:30:43:37 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:44:35:44:42 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:45:41:45:48 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:46:46:46:53 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:47:47:47:54 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:48:52:48:59 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:50:18:50:25 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | +| sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | sqlalchemy_textclause.py:51:24:51:31 | ControlFlowNode for username | This SQL query depends on a $@. | sqlalchemy_textclause.py:23:15:23:22 | ControlFlowNode for username | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected index 7dcddaaae83..186e1b02181 100644 --- a/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-090-LdapInjection/LdapInjection.expected @@ -82,18 +82,18 @@ nodes | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | semmle.label | ControlFlowNode for search_filter | subpaths #select -| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | $@ depends on $@. | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | $@ depends on $@. | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | $@ depends on $@. | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | a user-provided value | -| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | $@ depends on $@. | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | a user-provided value | +| ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:17:21:18 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | ldap3_bad.py:21:21:21:33 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:14:21:14:27 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:9:38:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | +| ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | ldap3_bad.py:38:13:38:25 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap3_bad.py:31:21:31:27 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:9:21:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:13:17:13:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | ldap_bad.py:21:33:21:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:14:21:14:27 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:9:37:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:30:17:30:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | ldap_bad.py:37:33:37:45 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:31:21:31:27 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:9:55:10 | ControlFlowNode for dn | LDAP query parameter (DN) depends on a $@. | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:47:17:47:23 | ControlFlowNode for request | user-provided value | +| ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | ldap_bad.py:55:43:55:55 | ControlFlowNode for search_filter | LDAP query parameter (filter) depends on a $@. | ldap_bad.py:48:21:48:27 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected index 97f5bc54118..6b543c3aa18 100644 --- a/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-094-CodeInjection/CodeInjection.expected @@ -16,7 +16,7 @@ nodes | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | semmle.label | ControlFlowNode for obj_name | subpaths #select -| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | a user-provided value | -| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | a user-provided value | +| code_injection.py:7:10:7:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:7:10:7:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | +| code_injection.py:8:10:8:13 | ControlFlowNode for code | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:8:10:8:13 | ControlFlowNode for code | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | +| code_injection.py:10:10:10:12 | ControlFlowNode for cmd | code_injection.py:6:12:6:18 | ControlFlowNode for request | code_injection.py:10:10:10:12 | ControlFlowNode for cmd | This code execution depends on a $@. | code_injection.py:6:12:6:18 | ControlFlowNode for request | user-provided value | +| code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | code_injection.py:18:16:18:22 | ControlFlowNode for request | code_injection.py:21:20:21:27 | ControlFlowNode for obj_name | This code execution depends on a $@. | code_injection.py:18:16:18:22 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected index 9641f49e3e2..e9faa8b46f9 100644 --- a/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-117-LogInjection/LogInjection.expected @@ -22,7 +22,7 @@ nodes | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | semmle.label | ControlFlowNode for BinaryExpr | subpaths #select -| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | a user-provided value | -| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | a user-provided value | -| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | a user-provided value | -| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | This log entry depends on $@. | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | a user-provided value | +| LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | LogInjectionBad.py:18:21:18:40 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:17:12:17:18 | ControlFlowNode for request | user-provided value | +| LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | LogInjectionBad.py:24:18:24:37 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:23:12:23:18 | ControlFlowNode for request | user-provided value | +| LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | LogInjectionBad.py:30:25:30:44 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:29:12:29:18 | ControlFlowNode for request | user-provided value | +| LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | LogInjectionBad.py:37:19:37:38 | ControlFlowNode for BinaryExpr | This log entry depends on a $@. | LogInjectionBad.py:35:12:35:18 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected index 07b208caaac..b37e8f605d2 100644 --- a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected +++ b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected @@ -22,8 +22,8 @@ nodes subpaths | test.py:50:29:50:31 | ControlFlowNode for err | test.py:52:18:52:20 | ControlFlowNode for msg | test.py:53:12:53:27 | ControlFlowNode for BinaryExpr | test.py:50:16:50:32 | ControlFlowNode for format_error() | #select -| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | $@ flows to this location and may be exposed to an external user. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | Stack trace information | -| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | $@ flows to this location and may be exposed to an external user. | test.py:23:25:23:25 | SSA variable e | Stack trace information | -| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | $@ flows to this location and may be exposed to an external user. | test.py:31:25:31:25 | SSA variable e | Stack trace information | -| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | $@ flows to this location and may be exposed to an external user. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | Stack trace information | -| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | $@ flows to this location and may be exposed to an external user. | test.py:65:25:65:25 | SSA variable e | Stack trace information | +| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | This information exposed to the user depends on $@. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | stack trace information | +| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | This information exposed to the user depends on $@. | test.py:23:25:23:25 | SSA variable e | stack trace information | +| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | This information exposed to the user depends on $@. | test.py:31:25:31:25 | SSA variable e | stack trace information | +| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | This information exposed to the user depends on $@. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | stack trace information | +| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | This information exposed to the user depends on $@. | test.py:65:25:65:25 | SSA variable e | stack trace information | diff --git a/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected b/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected index f81eda034dc..326fdfa9a06 100644 --- a/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected +++ b/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected @@ -1,6 +1,6 @@ -| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | This request may run without certificate validation because it is $@. | make_request.py:5:43:5:47 | ControlFlowNode for False | disabled here | make_request.py:5:43:5:47 | ControlFlowNode for False | here | -| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | This request may run without certificate validation because it is $@. | make_request.py:7:44:7:48 | ControlFlowNode for False | disabled here | make_request.py:7:44:7:48 | ControlFlowNode for False | here | -| make_request.py:12:1:12:39 | ControlFlowNode for put() | This request may run without certificate validation because it is $@. | make_request.py:12:34:12:38 | ControlFlowNode for False | disabled here | make_request.py:12:34:12:38 | ControlFlowNode for False | here | -| make_request.py:28:5:28:46 | ControlFlowNode for patch() | This request may run without certificate validation because it is $@ by the value from $@. | make_request.py:28:40:28:45 | ControlFlowNode for verify | disabled here | make_request.py:30:6:30:10 | ControlFlowNode for False | here | -| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | This request may run without certificate validation because it is $@. | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | disabled here | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | here | -| make_request.py:41:1:41:26 | ControlFlowNode for Attribute() | This request may run without certificate validation because it is $@. | make_request.py:41:21:41:25 | ControlFlowNode for False | disabled here | make_request.py:41:21:41:25 | ControlFlowNode for False | here | +| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:5:43:5:47 | ControlFlowNode for False | the request is disabled | make_request.py:5:43:5:47 | ControlFlowNode for False | this value | +| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:7:44:7:48 | ControlFlowNode for False | the request is disabled | make_request.py:7:44:7:48 | ControlFlowNode for False | this value | +| make_request.py:12:1:12:39 | ControlFlowNode for put() | This request may run without certificate validation because $@. | make_request.py:12:34:12:38 | ControlFlowNode for False | the request is disabled | make_request.py:12:34:12:38 | ControlFlowNode for False | this value | +| make_request.py:28:5:28:46 | ControlFlowNode for patch() | This request may run without certificate validation because $@ by $@. | make_request.py:28:40:28:45 | ControlFlowNode for verify | the request is disabled | make_request.py:30:6:30:10 | ControlFlowNode for False | this value | +| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | the request is disabled | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | this value | +| make_request.py:41:1:41:26 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:41:21:41:25 | ControlFlowNode for False | the request is disabled | make_request.py:41:21:41:25 | ControlFlowNode for False | this value | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected index f5fb2ac8dfb..e41dba2c9a7 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected @@ -22,13 +22,13 @@ nodes | test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | subpaths #select -| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:22:58:22:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | $@ is logged here. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | $@ is logged here. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) | +| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:22:58:22:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | This logs sensitive data returned by $@ as clear text. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) | +| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | This logs sensitive data returned by $@ as clear text. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected index ea3b3cb4c2a..53fc6ece659 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected @@ -9,6 +9,6 @@ nodes | test.py:15:26:15:29 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert | subpaths #select -| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | $@ is stored here. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected index 518935eb677..66a0a5f7932 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected @@ -15,7 +15,7 @@ nodes | test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines | subpaths #select -| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) | -| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) | -| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | This stores $@ as clear text. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) | +| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | This stores $@ as clear text. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) | +| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | This stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | diff --git a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected index 359a8d28ba1..c08e19e5f1c 100644 --- a/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected +++ b/python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected @@ -1,39 +1,39 @@ -| InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | call to SSLContext | -| InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:15:1:15:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@ | InsecureProtocol.py:15:1:15:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@ | InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | call to SSL.Context | -| InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | -| InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@ | InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | call to SSLContext | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | -| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:19:14:19:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:15:15:15:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:28:14:28:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:24:15:24:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:33:15:33:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:117:5:117:11 | ControlFlowNode for context | context modification | -| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:135:5:135:11 | ControlFlowNode for context | context modification | -| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | -| ssl_fluent.py:97:14:97:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:95:5:95:11 | ControlFlowNode for context | context modification | -| ssl_fluent.py:146:14:146:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:143:5:143:11 | ControlFlowNode for context | context modification | -| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@ | ssl_fluent.py:162:5:162:11 | ControlFlowNode for context | context modification | -| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@ | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | -| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@ | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | +| InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:6:1:6:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@. | InsecureProtocol.py:7:1:7:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@. | InsecureProtocol.py:8:1:8:47 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:10:1:10:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv3 specified by $@. | InsecureProtocol.py:11:1:11:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version TLSv1 specified by $@. | InsecureProtocol.py:12:1:12:39 | ControlFlowNode for SSLContext() | call to SSLContext | +| InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:14:1:14:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:15:1:15:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv3 specified by $@. | InsecureProtocol.py:15:1:15:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version TLSv1 specified by $@. | InsecureProtocol.py:16:1:16:29 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:19:1:19:19 | ControlFlowNode for Attribute() | call to SSL.Context | +| InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:23:1:23:43 | ControlFlowNode for Attribute() | call to ssl.wrap_socket | +| InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | Insecure SSL/TLS protocol version SSLv2 specified by $@. | InsecureProtocol.py:24:1:24:35 | ControlFlowNode for SSLContext() | call to SSLContext | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:8:27:8:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | pyOpenSSL_fluent.py:6:15:6:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv2 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| pyOpenSSL_fluent.py:18:27:18:33 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | pyOpenSSL_fluent.py:15:15:15:44 | ControlFlowNode for Attribute() | call to SSL.Context | +| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:9:14:9:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:6:15:6:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:19:14:19:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:15:15:15:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:28:14:28:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:24:15:24:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:37:14:37:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:33:15:33:53 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:57:14:57:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:54:15:54:49 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:101:15:101:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:117:5:117:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:71:14:71:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:135:5:135:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:77:14:77:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:62:12:62:43 | ControlFlowNode for Attribute() | call to ssl.SSLContext | +| ssl_fluent.py:97:14:97:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:95:5:95:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:146:14:146:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:143:5:143:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:162:5:162:11 | ControlFlowNode for context | context modification | +| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | +| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context | diff --git a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected index 9cab4ce7d16..2a456dbcc70 100644 --- a/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected +++ b/python/ql/test/query-tests/Security/CWE-502-UnsafeDeserialization/UnsafeDeserialization.expected @@ -13,7 +13,7 @@ nodes | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | semmle.label | ControlFlowNode for payload | subpaths #select -| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | -| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | a user-provided value | +| unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:15:18:15:24 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | +| unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:16:15:16:21 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | +| unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:18:19:18:25 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | +| unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | unsafe_deserialization.py:21:16:21:22 | ControlFlowNode for payload | Unsafe deserialization depends on a $@. | unsafe_deserialization.py:14:15:14:21 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected index 750e61d048d..dddd8fc4b0b 100644 --- a/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601-UrlRedirect/UrlRedirect.expected @@ -42,11 +42,11 @@ nodes | test.py:83:21:83:26 | ControlFlowNode for unsafe | semmle.label | ControlFlowNode for unsafe | subpaths #select -| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on $@. | test.py:7:14:7:20 | ControlFlowNode for request | a user-provided value | -| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:23 | ControlFlowNode for request | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:30:17:30:23 | ControlFlowNode for request | a user-provided value | -| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:23 | ControlFlowNode for request | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:37:17:37:23 | ControlFlowNode for request | a user-provided value | -| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:23 | ControlFlowNode for request | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on $@. | test.py:44:17:44:23 | ControlFlowNode for request | a user-provided value | -| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:23 | ControlFlowNode for request | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:60:17:60:23 | ControlFlowNode for request | a user-provided value | -| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:23 | ControlFlowNode for request | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:67:17:67:23 | ControlFlowNode for request | a user-provided value | -| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:23 | ControlFlowNode for request | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:74:17:74:23 | ControlFlowNode for request | a user-provided value | -| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:81:17:81:23 | ControlFlowNode for request | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on $@. | test.py:81:17:81:23 | ControlFlowNode for request | a user-provided value | +| test.py:8:21:8:26 | ControlFlowNode for target | test.py:7:14:7:20 | ControlFlowNode for request | test.py:8:21:8:26 | ControlFlowNode for target | Untrusted URL redirection depends on a $@. | test.py:7:14:7:20 | ControlFlowNode for request | user-provided value | +| test.py:32:21:32:24 | ControlFlowNode for safe | test.py:30:17:30:23 | ControlFlowNode for request | test.py:32:21:32:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:30:17:30:23 | ControlFlowNode for request | user-provided value | +| test.py:39:21:39:24 | ControlFlowNode for safe | test.py:37:17:37:23 | ControlFlowNode for request | test.py:39:21:39:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:37:17:37:23 | ControlFlowNode for request | user-provided value | +| test.py:46:21:46:24 | ControlFlowNode for safe | test.py:44:17:44:23 | ControlFlowNode for request | test.py:46:21:46:24 | ControlFlowNode for safe | Untrusted URL redirection depends on a $@. | test.py:44:17:44:23 | ControlFlowNode for request | user-provided value | +| test.py:62:21:62:26 | ControlFlowNode for unsafe | test.py:60:17:60:23 | ControlFlowNode for request | test.py:62:21:62:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:60:17:60:23 | ControlFlowNode for request | user-provided value | +| test.py:69:21:69:26 | ControlFlowNode for unsafe | test.py:67:17:67:23 | ControlFlowNode for request | test.py:69:21:69:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:67:17:67:23 | ControlFlowNode for request | user-provided value | +| test.py:76:21:76:26 | ControlFlowNode for unsafe | test.py:74:17:74:23 | ControlFlowNode for request | test.py:76:21:76:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:74:17:74:23 | ControlFlowNode for request | user-provided value | +| test.py:83:21:83:26 | ControlFlowNode for unsafe | test.py:81:17:81:23 | ControlFlowNode for request | test.py:83:21:83:26 | ControlFlowNode for unsafe | Untrusted URL redirection depends on a $@. | test.py:81:17:81:23 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected index 402ee97db09..7cddfb74205 100644 --- a/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected +++ b/python/ql/test/query-tests/Security/CWE-611-Xxe/Xxe.expected @@ -16,5 +16,5 @@ nodes | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:8:19:8:25 | ControlFlowNode for request | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:8:19:8:25 | ControlFlowNode for request | a user-provided value | -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against external entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | a user-provided value | +| test.py:9:34:9:44 | ControlFlowNode for xml_content | test.py:8:19:8:25 | ControlFlowNode for request | test.py:9:34:9:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:8:19:8:25 | ControlFlowNode for request | user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against external entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected index d0068a4b872..1a08fb7530a 100644 --- a/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-643-XPathInjection/XpathInjection.expected @@ -34,9 +34,9 @@ nodes | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | semmle.label | ControlFlowNode for xpathQuery | subpaths #select -| xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | XPath expression depends on $@. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | a user-provided value | -| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on $@. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | a user-provided value | +| xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | xpathBad.py:9:7:9:13 | ControlFlowNode for request | xpathBad.py:13:20:13:43 | ControlFlowNode for BinaryExpr | XPath expression depends on a $@. | xpathBad.py:9:7:9:13 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | xpathFlow.py:14:20:14:29 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:11:18:11:24 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | xpathFlow.py:23:29:23:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:20:18:20:24 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | xpathFlow.py:32:29:32:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:30:18:30:24 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | xpathFlow.py:41:31:41:40 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:39:18:39:24 | ControlFlowNode for request | user-provided value | +| xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | xpathFlow.py:49:29:49:38 | ControlFlowNode for xpathQuery | XPath expression depends on a $@. | xpathFlow.py:47:18:47:24 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected index 7f5cf5926c0..5e081c1d093 100644 --- a/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected +++ b/python/ql/test/query-tests/Security/CWE-730-PolynomialReDoS/PolynomialReDoS.expected @@ -9,5 +9,5 @@ nodes | test.py:9:32:9:35 | ControlFlowNode for text | semmle.label | ControlFlowNode for text | subpaths #select -| test.py:8:30:8:33 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | a user-provided value | -| test.py:9:32:9:35 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on $@ may run slow on strings with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | a user-provided value | +| test.py:8:30:8:33 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:8:30:8:33 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | test.py:8:21:8:23 | \\s+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | user-provided value | +| test.py:9:32:9:35 | ControlFlowNode for text | test.py:7:12:7:18 | ControlFlowNode for request | test.py:9:32:9:35 | ControlFlowNode for text | This $@ that depends on a $@ may run slow on strings with many repetitions of '99'. | test.py:9:27:9:29 | \\d+ | regular expression | test.py:7:12:7:18 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected index 317815142fe..3a6843346d2 100644 --- a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected @@ -23,6 +23,6 @@ nodes | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern | subpaths #select -| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:13:22:13:28 | ControlFlowNode for request | a user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:24:22:24:28 | ControlFlowNode for request | a user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | $@ depends on $@ and executed by $@. | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression | re_bad.py:36:22:36:28 | ControlFlowNode for request | a user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | diff --git a/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected index 79ebe0bfef7..492120581fd 100644 --- a/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected +++ b/python/ql/test/query-tests/Security/CWE-776-XmlBomb/XmlBomb.expected @@ -9,4 +9,4 @@ nodes | test.py:30:34:30:44 | ControlFlowNode for xml_content | semmle.label | ControlFlowNode for xml_content | subpaths #select -| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on $@ without guarding against uncontrolled entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | a user-provided value | +| test.py:30:34:30:44 | ControlFlowNode for xml_content | test.py:19:19:19:25 | ControlFlowNode for request | test.py:30:34:30:44 | ControlFlowNode for xml_content | XML parsing depends on a $@ without guarding against uncontrolled entity expansion. | test.py:19:19:19:25 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected index d912d5a7b84..7c433013f44 100644 --- a/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected +++ b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected @@ -4,5 +4,5 @@ edges | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | #select -| test.py:14:18:14:25 | USERNAME | test.py:5:12:5:24 | hard coded value | test.py:14:18:14:25 | hard coded value | Use of $@. | test.py:5:12:5:24 | Str | hardcoded credentials | -| test.py:15:18:15:25 | PASSWORD | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | Use of $@. | test.py:6:12:6:25 | Str | hardcoded credentials | +| test.py:14:18:14:25 | USERNAME | test.py:5:12:5:24 | hard coded value | test.py:14:18:14:25 | hard coded value | This hardcoded value is $@. | test.py:14:18:14:25 | USERNAME | used as credentials | +| test.py:15:18:15:25 | PASSWORD | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | This hardcoded value is $@. | test.py:15:18:15:25 | PASSWORD | used as credentials | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected index cc55c8317e1..6a08b56d7c4 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected @@ -243,24 +243,24 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | a user-provided value | +| full_partial_test.py:10:5:10:28 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:10:18:10:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:13:5:13:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:13:18:13:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:19:5:19:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:19:18:19:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:23:5:23:21 | ControlFlowNode for Attribute() | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | full_partial_test.py:23:18:23:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:7:18:7:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:42:5:42:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:42:18:42:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:45:5:45:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:45:18:45:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:48:5:48:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:48:18:48:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:51:5:51:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:51:18:51:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:54:5:54:21 | ControlFlowNode for Attribute() | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | full_partial_test.py:54:18:54:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:37:18:37:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:62:5:62:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:62:18:62:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:65:5:65:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:65:18:65:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:76:5:76:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:76:18:76:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:79:5:79:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:79:18:79:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:82:5:82:21 | ControlFlowNode for Attribute() | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | full_partial_test.py:82:18:82:20 | ControlFlowNode for url | The full URL of this request depends on a $@. | full_partial_test.py:71:18:71:24 | ControlFlowNode for request | user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:13:27:13:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:14:5:14:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:14:25:14:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:19:5:19:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:19:25:19:35 | ControlFlowNode for unsafe_path | The full URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | +| test_requests.py:8:5:8:28 | ControlFlowNode for Attribute() | test_requests.py:6:18:6:24 | ControlFlowNode for request | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | The full URL of this request depends on a $@. | test_requests.py:6:18:6:24 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected index 6206a070a88..bfca61c3a3a 100644 --- a/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected +++ b/python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected @@ -243,21 +243,21 @@ nodes | test_requests.py:8:18:8:27 | ControlFlowNode for user_input | semmle.label | ControlFlowNode for user_input | subpaths #select -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | a user-provided value | -| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on $@. | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | a user-provided value | -| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | a user-provided value | +| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:57:18:57:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:68:5:68:21 | ControlFlowNode for Attribute() | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | full_partial_test.py:68:18:68:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:58:17:58:23 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:89:5:89:21 | ControlFlowNode for Attribute() | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | full_partial_test.py:89:18:89:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:86:18:86:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:95:5:95:21 | ControlFlowNode for Attribute() | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | full_partial_test.py:95:18:95:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:92:18:92:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:101:5:101:21 | ControlFlowNode for Attribute() | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | full_partial_test.py:101:18:101:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:98:18:98:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:107:5:107:21 | ControlFlowNode for Attribute() | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | full_partial_test.py:107:18:107:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:104:18:104:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:116:5:116:21 | ControlFlowNode for Attribute() | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | full_partial_test.py:116:18:116:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:110:18:110:24 | ControlFlowNode for request | user-provided value | +| full_partial_test.py:122:5:122:21 | ControlFlowNode for Attribute() | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | full_partial_test.py:122:18:122:20 | ControlFlowNode for url | Part of the URL of this request depends on a $@. | full_partial_test.py:119:18:119:24 | ControlFlowNode for request | user-provided value | +| test_http_client.py:22:5:22:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:18:27:18:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:26:5:26:31 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:25:27:25:37 | ControlFlowNode for unsafe_host | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:29:5:29:36 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:29:25:29:35 | ControlFlowNode for unsafe_path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:33:5:33:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:33:25:33:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | user-provided value | +| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:9:19:9:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:9:19:9:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:10:19:10:25 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:10:19:10:25 | ControlFlowNode for request | user-provided value | +| test_http_client.py:37:5:37:29 | ControlFlowNode for Attribute() | test_http_client.py:11:18:11:24 | ControlFlowNode for request | test_http_client.py:37:25:37:28 | ControlFlowNode for path | Part of the URL of this request depends on a $@. | test_http_client.py:11:18:11:24 | ControlFlowNode for request | user-provided value | diff --git a/python/ql/test/query-tests/Statements/DocStrings/DocStrings.expected b/python/ql/test/query-tests/Statements/DocStrings/DocStrings.expected index 29cebbf4f9d..2f76425fa78 100644 --- a/python/ql/test/query-tests/Statements/DocStrings/DocStrings.expected +++ b/python/ql/test/query-tests/Statements/DocStrings/DocStrings.expected @@ -1,4 +1,4 @@ -| DocStrings.py:0:0:0:0 | Module DocStrings | Module DocStrings does not have a docstring | -| DocStrings.py:40:1:40:13 | Class Not_OK | Class Not_OK does not have a docstring | -| DocStrings.py:48:5:48:26 | Function meth_not_ok | Function meth_not_ok does not have a docstring | -| DocStrings.py:53:1:53:17 | Function not_ok | Function not_ok does not have a docstring | +| DocStrings.py:0:0:0:0 | Module DocStrings | Module DocStrings does not have a docstring. | +| DocStrings.py:40:1:40:13 | Class Not_OK | Class Not_OK does not have a docstring. | +| DocStrings.py:48:5:48:26 | Function meth_not_ok | Function meth_not_ok does not have a docstring. | +| DocStrings.py:53:1:53:17 | Function not_ok | Function not_ok does not have a docstring. | diff --git a/python/ql/test/query-tests/Statements/asserts/SideEffectInAssert.expected b/python/ql/test/query-tests/Statements/asserts/SideEffectInAssert.expected index f03252810d8..b39426cb2b7 100644 --- a/python/ql/test/query-tests/Statements/asserts/SideEffectInAssert.expected +++ b/python/ql/test/query-tests/Statements/asserts/SideEffectInAssert.expected @@ -1,3 +1,3 @@ -| assert.py:5:5:5:20 | Assert | This 'assert' statement contains $@ which may have side effects. | assert.py:5:13:5:19 | Yield | an expression | -| assert.py:8:5:8:22 | Assert | This 'assert' statement contains $@ which may have side effects. | assert.py:8:12:8:22 | Attribute() | an expression | -| side_effect.py:5:1:5:43 | Assert | This 'assert' statement contains $@ which may have side effects. | side_effect.py:5:8:5:38 | Attribute() | an expression | +| assert.py:5:5:5:20 | Assert | This 'assert' statement contains an $@ which may have side effects. | assert.py:5:13:5:19 | Yield | expression | +| assert.py:8:5:8:22 | Assert | This 'assert' statement contains an $@ which may have side effects. | assert.py:8:12:8:22 | Attribute() | expression | +| side_effect.py:5:1:5:43 | Assert | This 'assert' statement contains an $@ which may have side effects. | side_effect.py:5:8:5:38 | Attribute() | expression | diff --git a/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected b/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected index 38d063a8c0e..aea64f8bb13 100644 --- a/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected +++ b/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected @@ -1 +1 @@ -| test.py:50:1:50:23 | For | $@ of class '$@' may be used in for-loop. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | Non-iterable | test.py:45:1:45:26 | class NonIterator | NonIterator | +| test.py:50:1:50:23 | For | $@ of class $@ may be used in for-loop. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | Non-iterable | test.py:45:1:45:26 | class NonIterator | NonIterator | diff --git a/python/ql/test/query-tests/Statements/no_effect/UnusedExceptionObject.expected b/python/ql/test/query-tests/Statements/no_effect/UnusedExceptionObject.expected index 217832385ad..4ab8cecb8f8 100644 --- a/python/ql/test/query-tests/Statements/no_effect/UnusedExceptionObject.expected +++ b/python/ql/test/query-tests/Statements/no_effect/UnusedExceptionObject.expected @@ -1 +1 @@ -| test.py:127:9:127:26 | ValueError() | Instantiating an exception, but not raising it, has no effect | +| test.py:127:9:127:26 | ValueError() | Instantiating an exception, but not raising it, has no effect. | diff --git a/python/ql/test/query-tests/Variables/capture/LoopVariableCapture.expected b/python/ql/test/query-tests/Variables/capture/LoopVariableCapture.expected index cc9ae7029d6..8fd40c120a6 100644 --- a/python/ql/test/query-tests/Variables/capture/LoopVariableCapture.expected +++ b/python/ql/test/query-tests/Variables/capture/LoopVariableCapture.expected @@ -1,8 +1,8 @@ -| test.py:5:9:5:20 | FunctionExpr | Capture of loop variable '$@' | test.py:4:5:4:23 | For | x | -| test.py:10:6:10:14 | Lambda | Capture of loop variable '$@' | test.py:10:5:10:36 | ListComp | i | -| test.py:42:6:42:14 | Lambda | Capture of loop variable '$@' | test.py:42:5:42:56 | ListComp | i | -| test.py:43:6:43:14 | Lambda | Capture of loop variable '$@' | test.py:43:5:43:56 | ListComp | j | -| test.py:45:6:45:14 | Lambda | Capture of loop variable '$@' | test.py:45:5:45:36 | SetComp | i | -| test.py:49:8:49:16 | Lambda | Capture of loop variable '$@' | test.py:49:5:49:38 | DictComp | i | -| test.py:57:6:57:14 | Lambda | Capture of loop variable '$@' | test.py:57:6:57:35 | GeneratorExp | i | -| test.py:62:10:62:18 | Lambda | Capture of loop variable '$@' | test.py:62:10:62:39 | GeneratorExp | i | +| test.py:5:9:5:20 | FunctionExpr | Capture of loop variable $@. | test.py:4:5:4:23 | For | x | +| test.py:10:6:10:14 | Lambda | Capture of loop variable $@. | test.py:10:5:10:36 | ListComp | i | +| test.py:42:6:42:14 | Lambda | Capture of loop variable $@. | test.py:42:5:42:56 | ListComp | i | +| test.py:43:6:43:14 | Lambda | Capture of loop variable $@. | test.py:43:5:43:56 | ListComp | j | +| test.py:45:6:45:14 | Lambda | Capture of loop variable $@. | test.py:45:5:45:36 | SetComp | i | +| test.py:49:8:49:16 | Lambda | Capture of loop variable $@. | test.py:49:5:49:38 | DictComp | i | +| test.py:57:6:57:14 | Lambda | Capture of loop variable $@. | test.py:57:6:57:35 | GeneratorExp | i | +| test.py:62:10:62:18 | Lambda | Capture of loop variable $@. | test.py:62:10:62:39 | GeneratorExp | i | diff --git a/python/ql/test/query-tests/Variables/general/Global.expected b/python/ql/test/query-tests/Variables/general/Global.expected index 073dea682ed..4308dca8db8 100644 --- a/python/ql/test/query-tests/Variables/general/Global.expected +++ b/python/ql/test/query-tests/Variables/general/Global.expected @@ -1 +1 @@ -| variables_test.py:64:5:64:14 | Global | Updating global variables except at module initialization is discouraged | +| variables_test.py:64:5:64:14 | Global | Updating global variables except at module initialization is discouraged. | diff --git a/python/ql/test/query-tests/Variables/general/ShadowGlobal.expected b/python/ql/test/query-tests/Variables/general/ShadowGlobal.expected index ae59529932f..3080eb75c5d 100644 --- a/python/ql/test/query-tests/Variables/general/ShadowGlobal.expected +++ b/python/ql/test/query-tests/Variables/general/ShadowGlobal.expected @@ -1 +1 @@ -| variables_test.py:14:5:14:7 | sh1 | Local variable 'sh1' shadows a global variable defined $@. | variables_test.py:6:5:6:7 | sh1 | here | +| variables_test.py:14:5:14:7 | sh1 | Local variable 'sh1' shadows a $@. | variables_test.py:6:5:6:7 | sh1 | global variable | diff --git a/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected b/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected index 68d01f762f6..013baae72fd 100644 --- a/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected +++ b/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected @@ -1,7 +1,7 @@ -| uselesscode_test.py:4:5:4:8 | mult | This assignment to 'mult' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:15:5:15:8 | mult | here | -| uselesscode_test.py:5:5:5:5 | x | This assignment to 'x' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:7:5:7:5 | x | here | -| uselesscode_test.py:28:7:28:10 | Mult | This assignment to 'Mult' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:37:7:37:10 | Mult | here | -| uselesscode_test.py:52:9:52:11 | bad | This assignment to 'bad' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:53:9:53:11 | bad | here | -| uselesscode_test.py:67:9:67:11 | bad | This assignment to 'bad' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:71:9:71:11 | bad | here | -| uselesscode_test.py:117:5:117:5 | x | This assignment to 'x' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:118:5:118:5 | x | here | -| uselesscode_test.py:117:8:117:8 | y | This assignment to 'y' is unnecessary as it is redefined $@ before this value is used. | uselesscode_test.py:118:8:118:8 | y | here | +| uselesscode_test.py:4:5:4:8 | mult | This assignment to 'mult' is unnecessary as $@ before this value is used. | uselesscode_test.py:15:5:15:8 | mult | it is redefined | +| uselesscode_test.py:5:5:5:5 | x | This assignment to 'x' is unnecessary as $@ before this value is used. | uselesscode_test.py:7:5:7:5 | x | it is redefined | +| uselesscode_test.py:28:7:28:10 | Mult | This assignment to 'Mult' is unnecessary as $@ before this value is used. | uselesscode_test.py:37:7:37:10 | Mult | it is redefined | +| uselesscode_test.py:52:9:52:11 | bad | This assignment to 'bad' is unnecessary as $@ before this value is used. | uselesscode_test.py:53:9:53:11 | bad | it is redefined | +| uselesscode_test.py:67:9:67:11 | bad | This assignment to 'bad' is unnecessary as $@ before this value is used. | uselesscode_test.py:71:9:71:11 | bad | it is redefined | +| uselesscode_test.py:117:5:117:5 | x | This assignment to 'x' is unnecessary as $@ before this value is used. | uselesscode_test.py:118:5:118:5 | x | it is redefined | +| uselesscode_test.py:117:8:117:8 | y | This assignment to 'y' is unnecessary as $@ before this value is used. | uselesscode_test.py:118:8:118:8 | y | it is redefined | diff --git a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected index e0c2505bdda..06ae6a34602 100644 --- a/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected +++ b/python/ql/test/query-tests/Variables/unused/UnusedLocalVariable.expected @@ -1,5 +1,5 @@ -| variables_test.py:29:5:29:5 | x | Variable x is not used | -| variables_test.py:89:5:89:5 | a | Variable a is not used | -| variables_test.py:89:7:89:7 | b | Variable b is not used | -| variables_test.py:89:9:89:9 | c | Variable c is not used | -| variables_test.py:95:5:95:7 | var | Variable var is not used | +| variables_test.py:29:5:29:5 | x | Variable x is not used. | +| variables_test.py:89:5:89:5 | a | Variable a is not used. | +| variables_test.py:89:7:89:7 | b | Variable b is not used. | +| variables_test.py:89:9:89:9 | c | Variable c is not used. | +| variables_test.py:95:5:95:7 | var | Variable var is not used. | diff --git a/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected b/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected index 9abbf310179..4293a0ed355 100644 --- a/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected +++ b/python/ql/test/query-tests/Variables/unused_local_nonlocal/UnusedLocalVariable.expected @@ -1 +1 @@ -| variables_test.py:32:9:32:12 | test | Variable test is not used | +| variables_test.py:32:9:32:12 | test | Variable test is not used. | From 10a014f18c2933443c7375ca6581b1422b387726 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 13:46:48 +0200 Subject: [PATCH 058/164] add change-note --- python/ql/src/change-notes/2022-10-07-alert-messages.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 python/ql/src/change-notes/2022-10-07-alert-messages.md diff --git a/python/ql/src/change-notes/2022-10-07-alert-messages.md b/python/ql/src/change-notes/2022-10-07-alert-messages.md new file mode 100644 index 00000000000..de46b7752eb --- /dev/null +++ b/python/ql/src/change-notes/2022-10-07-alert-messages.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages. \ No newline at end of file From 6fdfd40880190a3164007e65dcc2ddd685cf3676 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Fri, 7 Oct 2022 22:31:00 +0200 Subject: [PATCH 059/164] changes to address reviews --- .../IncompleteUrlSubstringSanitization.ql | 3 ++- .../Security/CWE-209/StackTraceExposure.ql | 5 +++-- .../CWE-295/RequestWithoutValidation.ql | 2 +- .../src/Security/CWE-312/CleartextLogging.ql | 4 ++-- .../src/Security/CWE-312/CleartextStorage.ql | 4 ++-- .../ql/src/Security/CWE-730/RegexInjection.ql | 5 +++-- .../Security/CWE-798/HardcodedCredentials.ql | 2 +- .../ql/src/Statements/NonIteratorInForLoop.ql | 3 ++- python/ql/src/Variables/MultiplyDefined.ql | 4 ++-- .../experimental/Security/CWE-022/ZipSlip.ql | 2 +- .../iter/NonIteratorInForLoop.expected | 4 ++-- .../Security/CWE-022/ZipSlip.expected | 10 +++++----- ...ncompleteUrlSubstringSanitization.expected | 4 ++-- .../StackTraceExposure.expected | 10 +++++----- .../RequestWithoutValidation.expected | 12 +++++------ .../CleartextLogging.expected | 20 +++++++++---------- .../CleartextStorage.expected | 6 +++--- .../CleartextStorage.expected | 8 ++++---- .../RegexInjection.expected | 6 +++--- .../HardcodedCredentials.expected | 4 ++-- .../general/NonIteratorInForLoop.expected | 2 +- .../multiple/MultiplyDefined.expected | 14 ++++++------- 22 files changed, 69 insertions(+), 65 deletions(-) diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql index 02e6b72d266..6bf97d50bf5 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.ql @@ -51,4 +51,5 @@ predicate unsafe_call_to_endswith(Call sanitizer, StrConst url) { from Expr sanitizer, StrConst url where incomplete_sanitization(sanitizer, url) -select sanitizer, "$@ may be at an arbitrary position in the sanitized URL.", url, url.getText() +select sanitizer, "The string $@ may be at an arbitrary position in the sanitized URL.", url, + url.getText() diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.ql b/python/ql/src/Security/CWE-209/StackTraceExposure.ql index 43469aaf5a3..e817edc6b09 100644 --- a/python/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/python/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -19,5 +19,6 @@ import DataFlow::PathGraph from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) -select sink.getNode(), source, sink, "This information exposed to the user depends on $@.", - source.getNode(), "stack trace information" +select sink.getNode(), source, sink, + "$@ flows to this location and may be exposed to an external user.", source.getNode(), + "stack trace information" diff --git a/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql b/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql index e8a43838fb7..b402c4d2a3f 100644 --- a/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql +++ b/python/ql/src/Security/CWE-295/RequestWithoutValidation.ql @@ -24,4 +24,4 @@ where // value from. if disablingNode = origin then ending = "." else ending = " by $@." select request, "This request may run without certificate validation because $@" + ending, - disablingNode, "the request is disabled", origin, "this value" + disablingNode, "it is disabled", origin, "this value" diff --git a/python/ql/src/Security/CWE-312/CleartextLogging.ql b/python/ql/src/Security/CWE-312/CleartextLogging.ql index 93876606c7d..0c2591eaec4 100644 --- a/python/ql/src/Security/CWE-312/CleartextLogging.ql +++ b/python/ql/src/Security/CWE-312/CleartextLogging.ql @@ -22,5 +22,5 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, s where config.hasFlowPath(source, sink) and classification = source.getNode().(Source).getClassification() -select sink.getNode(), source, sink, "This logs sensitive data returned by $@ as clear text.", - source.getNode(), "Sensitive data (" + classification + ")" +select sink.getNode(), source, sink, "This expression logs $@ as clear text.", source.getNode(), + "sensitive data (" + classification + ")" diff --git a/python/ql/src/Security/CWE-312/CleartextStorage.ql b/python/ql/src/Security/CWE-312/CleartextStorage.ql index bd21b241242..9a8d5de3331 100644 --- a/python/ql/src/Security/CWE-312/CleartextStorage.ql +++ b/python/ql/src/Security/CWE-312/CleartextStorage.ql @@ -22,5 +22,5 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, s where config.hasFlowPath(source, sink) and classification = source.getNode().(Source).getClassification() -select sink.getNode(), source, sink, "This stores $@ as clear text.", source.getNode(), - "Sensitive data (" + classification + ")" +select sink.getNode(), source, sink, "This expression stores $@ as clear text.", source.getNode(), + "sensitive data (" + classification + ")" diff --git a/python/ql/src/Security/CWE-730/RegexInjection.ql b/python/ql/src/Security/CWE-730/RegexInjection.ql index bbcb18056a0..5075c7a675d 100644 --- a/python/ql/src/Security/CWE-730/RegexInjection.ql +++ b/python/ql/src/Security/CWE-730/RegexInjection.ql @@ -24,5 +24,6 @@ from where config.hasFlowPath(source, sink) and regexExecution = sink.getNode().(Sink).getRegexExecution() -select sink.getNode(), source, sink, "This regular expression depends on a $@ and executed by $@.", - source.getNode(), "user-provided value", regexExecution, regexExecution.getName() +select sink.getNode(), source, sink, + "This regular expression depends on a $@ and is executed by $@.", source.getNode(), + "user-provided value", regexExecution, regexExecution.getName() diff --git a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql index 932a557c5ee..c84ee29526f 100644 --- a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +++ b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql @@ -129,5 +129,5 @@ from HardcodedCredentialsConfiguration config, TaintedPathSource src, TaintedPat where config.hasFlowPath(src, sink) and not any(TestScope test).contains(src.getAstNode()) -select sink.getSink(), src, sink, "This hardcoded value is $@.", sink.getNode(), +select src.getSource(), src, sink, "This hardcoded value is $@.", sink.getNode(), "used as credentials" diff --git a/python/ql/src/Statements/NonIteratorInForLoop.ql b/python/ql/src/Statements/NonIteratorInForLoop.ql index 51ceb41f7db..91ad69f8d44 100644 --- a/python/ql/src/Statements/NonIteratorInForLoop.ql +++ b/python/ql/src/Statements/NonIteratorInForLoop.ql @@ -22,4 +22,5 @@ where not t.failedInference(_) and not v = Value::named("None") and not t.isDescriptorType() -select loop, "$@ of class $@ may be used in for-loop.", origin, "Non-iterable", t, t.getName() +select loop, "This for-loop may attempt to iterate over a $@ of class $@.", origin, + "non-iterable instance", t, t.getName() diff --git a/python/ql/src/Variables/MultiplyDefined.ql b/python/ql/src/Variables/MultiplyDefined.ql index 6b82ce7bfd9..a045dd6e8fa 100644 --- a/python/ql/src/Variables/MultiplyDefined.ql +++ b/python/ql/src/Variables/MultiplyDefined.ql @@ -67,5 +67,5 @@ where forall(Name el | el = asgn1.getParentNode().(Tuple).getAnElt() | multiply_defined(el, _, _)) and not uninteresting_definition(asgn1) select asgn1, - "This assignment to '" + v.getId() + "' is unnecessary as $@ before this value is used.", asgn2, - "it is redefined" + "This assignment to '" + v.getId() + "' is unnecessary as it is $@ before this value is used.", + asgn2, "redefined" diff --git a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql index fe2aca0368f..a914b938b96 100644 --- a/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql +++ b/python/ql/src/experimental/Security/CWE-022/ZipSlip.ql @@ -19,5 +19,5 @@ import DataFlow::PathGraph from ZipSlipConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select source.getNode(), source, sink, - "Unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(), + "This unsanitized archive entry, which may contain '..', is used in a $@.", sink.getNode(), "file system operation" diff --git a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected index 9c6647c1253..c59db3b2b65 100644 --- a/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected +++ b/python/ql/test/3/query-tests/Statements/iter/NonIteratorInForLoop.expected @@ -1,2 +1,2 @@ -| async_iterator.py:26:11:26:34 | For | $@ of class $@ may be used in for-loop. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | Non-iterable | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter | -| statements_test.py:34:5:34:19 | For | $@ of class $@ may be used in for-loop. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | Non-iterable | file://:0:0:0:0 | builtin-class int | int | +| async_iterator.py:26:11:26:34 | For | This for-loop may attempt to iterate over a $@ of class $@. | async_iterator.py:26:20:26:33 | ControlFlowNode for MissingAiter() | non-iterable instance | async_iterator.py:13:1:13:19 | class MissingAiter | MissingAiter | +| statements_test.py:34:5:34:19 | For | This for-loop may attempt to iterate over a $@ of class $@. | statements_test.py:34:18:34:18 | ControlFlowNode for IntegerLiteral | non-iterable instance | file://:0:0:0:0 | builtin-class int | int | diff --git a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected b/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected index fcf908f08e1..580163a52e9 100644 --- a/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected +++ b/python/ql/test/experimental/query-tests/Security/CWE-022/ZipSlip.expected @@ -27,8 +27,8 @@ nodes | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | semmle.label | ControlFlowNode for x | subpaths #select -| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | file system operation | -| zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | file system operation | -| zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | file system operation | -| zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | file system operation | -| zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | Unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | file system operation | +| zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:8:10:8:31 | ControlFlowNode for Attribute() | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:11:25:11:29 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:14:10:14:28 | ControlFlowNode for Attribute() | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:17:26:17:30 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:20:10:20:27 | ControlFlowNode for Attribute() | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:23:29:23:33 | ControlFlowNode for entry | file system operation | +| zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:27:10:27:22 | ControlFlowNode for Attribute() | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:30:25:30:25 | ControlFlowNode for x | file system operation | +| zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:34:16:34:28 | ControlFlowNode for Attribute() | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | This unsanitized archive entry, which may contain '..', is used in a $@. | zipslip_bad.py:37:32:37:32 | ControlFlowNode for x | file system operation | diff --git a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected index 5eb9f16605c..3a70e1df2c2 100644 --- a/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected +++ b/python/ql/test/query-tests/Security/CWE-020-IncompleteUrlSubstringSanitization/IncompleteUrlSubstringSanitization.expected @@ -1,2 +1,2 @@ -| urltest.py:9:8:9:30 | Compare | $@ may be at an arbitrary position in the sanitized URL. | urltest.py:9:8:9:20 | Str | example.com | -| urltest.py:15:8:15:37 | Attribute() | $@ may be at an arbitrary position in the sanitized URL. | urltest.py:15:24:15:36 | Str | example.com | +| urltest.py:9:8:9:30 | Compare | The string $@ may be at an arbitrary position in the sanitized URL. | urltest.py:9:8:9:20 | Str | example.com | +| urltest.py:15:8:15:37 | Attribute() | The string $@ may be at an arbitrary position in the sanitized URL. | urltest.py:15:24:15:36 | Str | example.com | diff --git a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected index b37e8f605d2..eb0e1efe6e0 100644 --- a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected +++ b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected @@ -22,8 +22,8 @@ nodes subpaths | test.py:50:29:50:31 | ControlFlowNode for err | test.py:52:18:52:20 | ControlFlowNode for msg | test.py:53:12:53:27 | ControlFlowNode for BinaryExpr | test.py:50:16:50:32 | ControlFlowNode for format_error() | #select -| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | This information exposed to the user depends on $@. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | stack trace information | -| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | This information exposed to the user depends on $@. | test.py:23:25:23:25 | SSA variable e | stack trace information | -| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | This information exposed to the user depends on $@. | test.py:31:25:31:25 | SSA variable e | stack trace information | -| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | This information exposed to the user depends on $@. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | stack trace information | -| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | This information exposed to the user depends on $@. | test.py:65:25:65:25 | SSA variable e | stack trace information | +| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | $@ flows to this location and may be exposed to an external user. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | stack trace information | +| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | $@ flows to this location and may be exposed to an external user. | test.py:23:25:23:25 | SSA variable e | stack trace information | +| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | $@ flows to this location and may be exposed to an external user. | test.py:31:25:31:25 | SSA variable e | stack trace information | +| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | $@ flows to this location and may be exposed to an external user. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | stack trace information | +| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | $@ flows to this location and may be exposed to an external user. | test.py:65:25:65:25 | SSA variable e | stack trace information | diff --git a/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected b/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected index 326fdfa9a06..c4c3ad6801f 100644 --- a/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected +++ b/python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/RequestWithoutValidation.expected @@ -1,6 +1,6 @@ -| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:5:43:5:47 | ControlFlowNode for False | the request is disabled | make_request.py:5:43:5:47 | ControlFlowNode for False | this value | -| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:7:44:7:48 | ControlFlowNode for False | the request is disabled | make_request.py:7:44:7:48 | ControlFlowNode for False | this value | -| make_request.py:12:1:12:39 | ControlFlowNode for put() | This request may run without certificate validation because $@. | make_request.py:12:34:12:38 | ControlFlowNode for False | the request is disabled | make_request.py:12:34:12:38 | ControlFlowNode for False | this value | -| make_request.py:28:5:28:46 | ControlFlowNode for patch() | This request may run without certificate validation because $@ by $@. | make_request.py:28:40:28:45 | ControlFlowNode for verify | the request is disabled | make_request.py:30:6:30:10 | ControlFlowNode for False | this value | -| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | the request is disabled | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | this value | -| make_request.py:41:1:41:26 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:41:21:41:25 | ControlFlowNode for False | the request is disabled | make_request.py:41:21:41:25 | ControlFlowNode for False | this value | +| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:5:43:5:47 | ControlFlowNode for False | it is disabled | make_request.py:5:43:5:47 | ControlFlowNode for False | this value | +| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:7:44:7:48 | ControlFlowNode for False | it is disabled | make_request.py:7:44:7:48 | ControlFlowNode for False | this value | +| make_request.py:12:1:12:39 | ControlFlowNode for put() | This request may run without certificate validation because $@. | make_request.py:12:34:12:38 | ControlFlowNode for False | it is disabled | make_request.py:12:34:12:38 | ControlFlowNode for False | this value | +| make_request.py:28:5:28:46 | ControlFlowNode for patch() | This request may run without certificate validation because $@ by $@. | make_request.py:28:40:28:45 | ControlFlowNode for verify | it is disabled | make_request.py:30:6:30:10 | ControlFlowNode for False | this value | +| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | it is disabled | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | this value | +| make_request.py:41:1:41:26 | ControlFlowNode for Attribute() | This request may run without certificate validation because $@. | make_request.py:41:21:41:25 | ControlFlowNode for False | it is disabled | make_request.py:41:21:41:25 | ControlFlowNode for False | this value | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected index e41dba2c9a7..e9b5ac67585 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected @@ -22,13 +22,13 @@ nodes | test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript | subpaths #select -| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:22:58:22:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | This logs sensitive data returned by $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | This logs sensitive data returned by $@ as clear text. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | This logs sensitive data returned by $@ as clear text. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) | -| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | This logs sensitive data returned by $@ as clear text. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) | +| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:22:58:22:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:22:58:22:65 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:23:58:23:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:27:40:27:47 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:30:58:30:65 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password | This expression logs $@ as clear text. | test.py:19:16:19:29 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | test.py:34:30:34:39 | ControlFlowNode for get_cert() | This expression logs $@ as clear text. | test.py:34:30:34:39 | ControlFlowNode for get_cert() | sensitive data (certificate) | +| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:37:11:37:24 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:39:22:39:35 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | This expression logs $@ as clear text. | test.py:40:22:40:35 | ControlFlowNode for get_password() | sensitive data (password) | +| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | This expression logs $@ as clear text. | test.py:67:21:67:37 | ControlFlowNode for Attribute | sensitive data (password) | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected index 53fc6ece659..f2b0894ec0a 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage-py3/CleartextStorage.expected @@ -9,6 +9,6 @@ nodes | test.py:15:26:15:29 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert | subpaths #select -| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| test.py:12:21:12:24 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:12:21:12:24 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) | +| test.py:13:22:13:41 | ControlFlowNode for Attribute() | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:13:22:13:41 | ControlFlowNode for Attribute() | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) | +| test.py:15:26:15:29 | ControlFlowNode for cert | test.py:9:12:9:21 | ControlFlowNode for get_cert() | test.py:15:26:15:29 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:9:12:9:21 | ControlFlowNode for get_cert() | sensitive data (certificate) | diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected index 66a0a5f7932..158afa2acc8 100644 --- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected +++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected @@ -15,7 +15,7 @@ nodes | test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines | subpaths #select -| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | This stores $@ as clear text. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) | -| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | This stores $@ as clear text. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) | -| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | This stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | -| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | This stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) | +| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | This expression stores $@ as clear text. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | sensitive data (password) | +| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | This expression stores $@ as clear text. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | sensitive data (password) | +| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | This expression stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | sensitive data (certificate) | +| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | This expression stores $@ as clear text. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | sensitive data (certificate) | diff --git a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected index 3a6843346d2..965df0d664f 100644 --- a/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-730-RegexInjection/RegexInjection.expected @@ -23,6 +23,6 @@ nodes | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | semmle.label | ControlFlowNode for unsafe_pattern | subpaths #select -| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | -| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and executed by $@. | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | re_bad.py:13:22:13:28 | ControlFlowNode for request | re_bad.py:14:15:14:28 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:13:22:13:28 | ControlFlowNode for request | user-provided value | re_bad.py:14:5:14:33 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | re_bad.py:24:22:24:28 | ControlFlowNode for request | re_bad.py:25:35:25:48 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:24:22:24:28 | ControlFlowNode for request | user-provided value | re_bad.py:26:5:26:31 | ControlFlowNode for Attribute() | re.search | +| re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | re_bad.py:36:22:36:28 | ControlFlowNode for request | re_bad.py:37:16:37:29 | ControlFlowNode for unsafe_pattern | This regular expression depends on a $@ and is executed by $@. | re_bad.py:36:22:36:28 | ControlFlowNode for request | user-provided value | re_bad.py:37:5:37:41 | ControlFlowNode for Attribute() | re.search | diff --git a/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected index 7c433013f44..efea6e2f054 100644 --- a/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected +++ b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/HardcodedCredentials.expected @@ -4,5 +4,5 @@ edges | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | #select -| test.py:14:18:14:25 | USERNAME | test.py:5:12:5:24 | hard coded value | test.py:14:18:14:25 | hard coded value | This hardcoded value is $@. | test.py:14:18:14:25 | USERNAME | used as credentials | -| test.py:15:18:15:25 | PASSWORD | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | This hardcoded value is $@. | test.py:15:18:15:25 | PASSWORD | used as credentials | +| test.py:5:12:5:24 | Str | test.py:5:12:5:24 | hard coded value | test.py:14:18:14:25 | hard coded value | This hardcoded value is $@. | test.py:14:18:14:25 | USERNAME | used as credentials | +| test.py:6:12:6:25 | Str | test.py:6:12:6:25 | hard coded value | test.py:15:18:15:25 | hard coded value | This hardcoded value is $@. | test.py:15:18:15:25 | PASSWORD | used as credentials | diff --git a/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected b/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected index aea64f8bb13..4c79685061f 100644 --- a/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected +++ b/python/ql/test/query-tests/Statements/general/NonIteratorInForLoop.expected @@ -1 +1 @@ -| test.py:50:1:50:23 | For | $@ of class $@ may be used in for-loop. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | Non-iterable | test.py:45:1:45:26 | class NonIterator | NonIterator | +| test.py:50:1:50:23 | For | This for-loop may attempt to iterate over a $@ of class $@. | test.py:50:10:50:22 | ControlFlowNode for NonIterator() | non-iterable instance | test.py:45:1:45:26 | class NonIterator | NonIterator | diff --git a/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected b/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected index 013baae72fd..9c45f0ab896 100644 --- a/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected +++ b/python/ql/test/query-tests/Variables/multiple/MultiplyDefined.expected @@ -1,7 +1,7 @@ -| uselesscode_test.py:4:5:4:8 | mult | This assignment to 'mult' is unnecessary as $@ before this value is used. | uselesscode_test.py:15:5:15:8 | mult | it is redefined | -| uselesscode_test.py:5:5:5:5 | x | This assignment to 'x' is unnecessary as $@ before this value is used. | uselesscode_test.py:7:5:7:5 | x | it is redefined | -| uselesscode_test.py:28:7:28:10 | Mult | This assignment to 'Mult' is unnecessary as $@ before this value is used. | uselesscode_test.py:37:7:37:10 | Mult | it is redefined | -| uselesscode_test.py:52:9:52:11 | bad | This assignment to 'bad' is unnecessary as $@ before this value is used. | uselesscode_test.py:53:9:53:11 | bad | it is redefined | -| uselesscode_test.py:67:9:67:11 | bad | This assignment to 'bad' is unnecessary as $@ before this value is used. | uselesscode_test.py:71:9:71:11 | bad | it is redefined | -| uselesscode_test.py:117:5:117:5 | x | This assignment to 'x' is unnecessary as $@ before this value is used. | uselesscode_test.py:118:5:118:5 | x | it is redefined | -| uselesscode_test.py:117:8:117:8 | y | This assignment to 'y' is unnecessary as $@ before this value is used. | uselesscode_test.py:118:8:118:8 | y | it is redefined | +| uselesscode_test.py:4:5:4:8 | mult | This assignment to 'mult' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:15:5:15:8 | mult | redefined | +| uselesscode_test.py:5:5:5:5 | x | This assignment to 'x' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:7:5:7:5 | x | redefined | +| uselesscode_test.py:28:7:28:10 | Mult | This assignment to 'Mult' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:37:7:37:10 | Mult | redefined | +| uselesscode_test.py:52:9:52:11 | bad | This assignment to 'bad' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:53:9:53:11 | bad | redefined | +| uselesscode_test.py:67:9:67:11 | bad | This assignment to 'bad' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:71:9:71:11 | bad | redefined | +| uselesscode_test.py:117:5:117:5 | x | This assignment to 'x' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:118:5:118:5 | x | redefined | +| uselesscode_test.py:117:8:117:8 | y | This assignment to 'y' is unnecessary as it is $@ before this value is used. | uselesscode_test.py:118:8:118:8 | y | redefined | From c4baf0b8fa995692d300370d43ea27dbae3b8b55 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Sun, 9 Oct 2022 22:16:23 +0100 Subject: [PATCH 060/164] Ruby: add space for test case --- .../security/cwe-094/CodeInjection.expected | 50 +++++++++---------- .../security/cwe-094/CodeInjection.rb | 15 ++++-- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected index fdf5b95aacc..08926b9e121 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected @@ -1,29 +1,29 @@ edges -| CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:3:12:3:24 | ...[...] : | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:6:10:6:13 | code | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:18:20:18:23 | code | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:21:21:21:24 | code | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:27:15:27:18 | code | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:30:19:30:22 | code | -| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:36:24:36:27 | code : | -| CodeInjection.rb:36:24:36:27 | code : | CodeInjection.rb:36:10:36:28 | call to escape | +| CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:5:12:5:24 | ...[...] : | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:8:10:8:13 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:20:20:20:23 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:23:21:23:24 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:29:15:29:18 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:32:19:32:22 | code | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:38:24:38:27 | code : | +| CodeInjection.rb:38:24:38:27 | code : | CodeInjection.rb:38:10:38:28 | call to escape | nodes -| CodeInjection.rb:3:12:3:17 | call to params : | semmle.label | call to params : | -| CodeInjection.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : | -| CodeInjection.rb:6:10:6:13 | code | semmle.label | code | -| CodeInjection.rb:9:10:9:15 | call to params | semmle.label | call to params | -| CodeInjection.rb:18:20:18:23 | code | semmle.label | code | -| CodeInjection.rb:21:21:21:24 | code | semmle.label | code | -| CodeInjection.rb:27:15:27:18 | code | semmle.label | code | -| CodeInjection.rb:30:19:30:22 | code | semmle.label | code | -| CodeInjection.rb:36:10:36:28 | call to escape | semmle.label | call to escape | -| CodeInjection.rb:36:24:36:27 | code : | semmle.label | code : | +| CodeInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | +| CodeInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : | +| CodeInjection.rb:8:10:8:13 | code | semmle.label | code | +| CodeInjection.rb:11:10:11:15 | call to params | semmle.label | call to params | +| CodeInjection.rb:20:20:20:23 | code | semmle.label | code | +| CodeInjection.rb:23:21:23:24 | code | semmle.label | code | +| CodeInjection.rb:29:15:29:18 | code | semmle.label | code | +| CodeInjection.rb:32:19:32:22 | code | semmle.label | code | +| CodeInjection.rb:38:10:38:28 | call to escape | semmle.label | call to escape | +| CodeInjection.rb:38:24:38:27 | code : | semmle.label | code : | subpaths #select -| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | -| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:9:10:9:15 | call to params | user-provided value | -| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | -| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | -| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | -| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | -| CodeInjection.rb:36:10:36:28 | call to escape | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:36:10:36:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value | +| CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:11:10:11:15 | call to params | user-provided value | +| CodeInjection.rb:20:20:20:23 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:20:20:20:23 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:23:21:23:24 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:23:21:23:24 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:29:15:29:18 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:29:15:29:18 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:32:19:32:22 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:32:19:32:22 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:38:10:38:28 | call to escape | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:38:10:38:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb index 5f58eebd92b..17233b711d0 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb @@ -1,3 +1,5 @@ +require 'active_job' + class UsersController < ActionController::Base def create code = params[:code] @@ -22,18 +24,21 @@ class UsersController < ActionController::Base # GOOD Bar.class_eval(code) - + # BAD const_get(code) - + # BAD Foo.const_get(code) - + # GOOD Bar.const_get(code) # BAD eval(Regexp.escape(code)) + + + end def update @@ -62,8 +67,8 @@ class Bar def self.class_eval(x) true end - + def self.const_get(x) true end -end \ No newline at end of file +end From 4a39e4aac0ea0179a8a28b7c7470933c0ffb6881 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Sun, 9 Oct 2022 22:26:29 +0100 Subject: [PATCH 061/164] Ruby: Add new test case for rb/code-injection --- ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb index 17233b711d0..8a1d52fa176 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb @@ -37,8 +37,8 @@ class UsersController < ActionController::Base # BAD eval(Regexp.escape(code)) - - + # BAD + ActiveJob::Serializers.deserialize(code) end def update From ee77404006955d780f52fd3e7362cdbc8b553c81 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Sun, 9 Oct 2022 22:28:22 +0100 Subject: [PATCH 062/164] Ruby: Add ActiveJob::Serializers.deserialize as a code execution sink --- ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 + .../lib/codeql/ruby/frameworks/ActiveJob.qll | 30 +++++++++++++++++++ .../security/cwe-094/CodeInjection.expected | 3 ++ 3 files changed, 34 insertions(+) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index 868489ad26b..75e7cf55177 100644 --- a/ruby/ql/lib/codeql/ruby/Frameworks.qll +++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll @@ -5,6 +5,7 @@ private import codeql.ruby.frameworks.Core private import codeql.ruby.frameworks.ActionCable private import codeql.ruby.frameworks.ActionController +private import codeql.ruby.frameworks.ActiveJob private import codeql.ruby.frameworks.ActiveRecord private import codeql.ruby.frameworks.ActiveResource private import codeql.ruby.frameworks.ActiveStorage diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll new file mode 100644 index 00000000000..aad917ccb2e --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll @@ -0,0 +1,30 @@ +/** + * Modeling for `ActiveJob`, a framweork for declaring and enqueueing jobs that + * ships with Rails. + * https://rubygems.org/gems/activejob + */ + +private import codeql.ruby.ApiGraphs +private import codeql.ruby.Concepts +private import codeql.ruby.DataFlow + +/** Modeling for `ActiveJob`. */ +module ActiveJob { + /** + * `ActiveJob::Serializers` + */ + module Serializers { + /** + * A call to `ActiveJob::Serializers.deserialize`, which interprets part of + * its argument as a Ruby constant. + */ + class DeserializeCall extends DataFlow::CallNode, CodeExecution::Range { + DeserializeCall() { + this = + API::getTopLevelMember("ActiveJob").getMember("Serializers").getAMethodCall("deserialize") + } + + override DataFlow::Node getCode() { result = this.getArgument(0) } + } + } +} diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected index 08926b9e121..f70ce6ca67e 100644 --- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected +++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected @@ -6,6 +6,7 @@ edges | CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:29:15:29:18 | code | | CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:32:19:32:22 | code | | CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:38:24:38:27 | code : | +| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:41:40:41:43 | code | | CodeInjection.rb:38:24:38:27 | code : | CodeInjection.rb:38:10:38:28 | call to escape | nodes | CodeInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : | @@ -18,6 +19,7 @@ nodes | CodeInjection.rb:32:19:32:22 | code | semmle.label | code | | CodeInjection.rb:38:10:38:28 | call to escape | semmle.label | call to escape | | CodeInjection.rb:38:24:38:27 | code : | semmle.label | code : | +| CodeInjection.rb:41:40:41:43 | code | semmle.label | code | subpaths #select | CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | @@ -27,3 +29,4 @@ subpaths | CodeInjection.rb:29:15:29:18 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:29:15:29:18 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | | CodeInjection.rb:32:19:32:22 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:32:19:32:22 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | | CodeInjection.rb:38:10:38:28 | call to escape | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:38:10:38:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | +| CodeInjection.rb:41:40:41:43 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:41:40:41:43 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value | From d0bdbe65ef8aecf96bde5aba33c32a18b2b02494 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Sun, 9 Oct 2022 22:47:52 +0100 Subject: [PATCH 063/164] Ruby: ActiveJob::Serializers.deserialize changenote --- .../2022-10-09-activejob-serializers-deserialize.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2022-10-09-activejob-serializers-deserialize.md diff --git a/ruby/ql/lib/change-notes/2022-10-09-activejob-serializers-deserialize.md b/ruby/ql/lib/change-notes/2022-10-09-activejob-serializers-deserialize.md new file mode 100644 index 00000000000..4d0be19e67f --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-10-09-activejob-serializers-deserialize.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* `ActiveJob::Serializers.deserialize` is considered to be a code execution sink. From d61f0559a0f98196010eb18648850b3e5787e4e4 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Fri, 7 Oct 2022 15:26:21 +0100 Subject: [PATCH 064/164] Ruby: add ActionMailer#params as a RemoteFlowSource --- ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 + .../codeql/ruby/frameworks/ActionMailer.qll | 48 +++++++++++++++++++ .../frameworks/ActionController.expected | 2 + .../frameworks/action_mailer/mailer.rb | 5 ++ .../action_mailer/params-flow.expected | 9 ++++ .../frameworks/action_mailer/params-flow.ql | 18 +++++++ 6 files changed, 83 insertions(+) create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailer/mailer.rb create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.expected create mode 100644 ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.ql diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll index 868489ad26b..31f7b664afa 100644 --- a/ruby/ql/lib/codeql/ruby/Frameworks.qll +++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll @@ -5,6 +5,7 @@ private import codeql.ruby.frameworks.Core private import codeql.ruby.frameworks.ActionCable private import codeql.ruby.frameworks.ActionController +private import codeql.ruby.frameworks.ActionMailer private import codeql.ruby.frameworks.ActiveRecord private import codeql.ruby.frameworks.ActiveResource private import codeql.ruby.frameworks.ActiveStorage diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll new file mode 100644 index 00000000000..13be621683b --- /dev/null +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll @@ -0,0 +1,48 @@ +/** + * Provides modeling for the `ActionMailer` library. + */ + +private import codeql.ruby.AST +private import codeql.ruby.ApiGraphs +private import codeql.ruby.frameworks.internal.Rails + +/** + * A `ClassDeclaration` for a class that extends `ActionMailer::Base`. + * For example, + * + * ```rb + * class FooMailer < ActionMailer::Base + * ... + * end + * ``` + */ +class ActionMailerMailerClass extends ClassDeclaration { + ActionMailerMailerClass() { + this.getSuperclassExpr() = + [ + API::getTopLevelMember("ActionMailer").getMember("Base"), + // In Rails applications `ApplicationMailer` typically extends + // `ActionMailer::Base`, but we treat it separately in case the + // `ApplicationMailer` definition is not in the database. + API::getTopLevelMember("ApplicationMailer") + ].getASubclass().getAValueReachableFromSource().asExpr().getExpr() + } +} + +/** A method call with a `self` receiver from within a mailer class */ +private class ActionMailerContextCall extends MethodCall { + private ActionMailerMailerClass mailerClass; + + ActionMailerContextCall() { + this.getReceiver() instanceof SelfVariableAccess and + this.getEnclosingModule() = mailerClass + } + + /** Gets the mailer class containing this method. */ + ActionMailerMailerClass getMailerClass() { result = mailerClass } +} + +/** A call to `params` from within a mailer. */ +class ActionMailerParamsCall extends ActionMailerContextCall, ParamsCallImpl { + ActionMailerParamsCall() { this.getMethodName() = "params" } +} diff --git a/ruby/ql/test/library-tests/frameworks/ActionController.expected b/ruby/ql/test/library-tests/frameworks/ActionController.expected index f5a5f703abf..f67d31eca03 100644 --- a/ruby/ql/test/library-tests/frameworks/ActionController.expected +++ b/ruby/ql/test/library-tests/frameworks/ActionController.expected @@ -115,6 +115,7 @@ paramsCalls | action_controller/params_flow.rb:144:10:144:15 | call to params | | action_controller/params_flow.rb:145:32:145:37 | call to params | | action_controller/params_flow.rb:148:22:148:27 | call to params | +| action_mailer/mailer.rb:3:10:3:15 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | @@ -189,6 +190,7 @@ paramsSources | action_controller/params_flow.rb:144:10:144:15 | call to params | | action_controller/params_flow.rb:145:32:145:37 | call to params | | action_controller/params_flow.rb:148:22:148:27 | call to params | +| action_mailer/mailer.rb:3:10:3:15 | call to params | | active_record/ActiveRecord.rb:28:30:28:35 | call to params | | active_record/ActiveRecord.rb:29:29:29:34 | call to params | | active_record/ActiveRecord.rb:30:31:30:36 | call to params | diff --git a/ruby/ql/test/library-tests/frameworks/action_mailer/mailer.rb b/ruby/ql/test/library-tests/frameworks/action_mailer/mailer.rb new file mode 100644 index 00000000000..09243fbb7fe --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailer/mailer.rb @@ -0,0 +1,5 @@ +class MyMailer < ActionMailer::Base + def foo + sink params[:foo] # $hasTaintFlow + end +end diff --git a/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.expected b/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.expected new file mode 100644 index 00000000000..a4a7be5b17a --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.expected @@ -0,0 +1,9 @@ +failures +edges +| mailer.rb:3:10:3:15 | call to params : | mailer.rb:3:10:3:21 | ...[...] | +nodes +| mailer.rb:3:10:3:15 | call to params : | semmle.label | call to params : | +| mailer.rb:3:10:3:21 | ...[...] | semmle.label | ...[...] | +subpaths +#select +| mailer.rb:3:10:3:21 | ...[...] | mailer.rb:3:10:3:15 | call to params : | mailer.rb:3:10:3:21 | ...[...] | $@ | mailer.rb:3:10:3:15 | call to params : | call to params : | diff --git a/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.ql b/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.ql new file mode 100644 index 00000000000..412ba5534b8 --- /dev/null +++ b/ruby/ql/test/library-tests/frameworks/action_mailer/params-flow.ql @@ -0,0 +1,18 @@ +/** + * @kind path-problem + */ + +import ruby +import TestUtilities.InlineFlowTest +import PathGraph +import codeql.ruby.frameworks.Rails + +class ParamsTaintFlowConf extends DefaultTaintFlowConf { + override predicate isSource(DataFlow::Node n) { + n.asExpr().getExpr() instanceof Rails::ParamsCall + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, ParamsTaintFlowConf conf +where conf.hasFlowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() From e38cfd5f7db853a46da9bfd2e42c2cda402100d5 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Mon, 10 Oct 2022 10:25:19 +0100 Subject: [PATCH 065/164] Ruby: add changenote for ActionMailer params --- ruby/ql/lib/change-notes/2022-10-07-actionmailer-params.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2022-10-07-actionmailer-params.md diff --git a/ruby/ql/lib/change-notes/2022-10-07-actionmailer-params.md b/ruby/ql/lib/change-notes/2022-10-07-actionmailer-params.md new file mode 100644 index 00000000000..0bac2da675d --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-10-07-actionmailer-params.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Calls to `params` in `ActionMailer` classes are now treated as sources of remote user input. From 584ccf1992b548751276fe93299ee9f7e179b016 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 10 Oct 2022 13:49:26 +0200 Subject: [PATCH 066/164] Python: clean up `Mysql.qll` --- .../ql/lib/semmle/python/frameworks/Mysql.qll | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/Mysql.qll b/python/ql/lib/semmle/python/frameworks/Mysql.qll index b61037ff62a..5f5d9bb35d5 100644 --- a/python/ql/lib/semmle/python/frameworks/Mysql.qll +++ b/python/ql/lib/semmle/python/frameworks/Mysql.qll @@ -21,17 +21,11 @@ private import semmle.python.frameworks.PEP249 * - https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html */ private module Mysql { - // --------------------------------------------------------------------------- - // mysql - // --------------------------------------------------------------------------- - /** Provides models for the `mysql` module. */ - module MysqlMod { - /** - * The mysql.connector module - * See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html - */ - class MysqlConnector extends PEP249::PEP249ModuleApiNode { - MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") } - } + /** + * The mysql.connector module + * See https://dev.mysql.com/doc/connector-python/en/connector-python-example-connecting.html + */ + class MysqlConnector extends PEP249::PEP249ModuleApiNode { + MysqlConnector() { this = API::moduleImport("mysql").getMember("connector") } } } From b1d33a404cd0a949b8f08c0feac0577d78d453f4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 10 Oct 2022 13:55:10 +0200 Subject: [PATCH 067/164] Python: Sort `Frameworks.qll` --- python/ql/lib/semmle/python/Frameworks.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/Frameworks.qll b/python/ql/lib/semmle/python/Frameworks.qll index 6cf4044157b..ce4ad603272 100644 --- a/python/ql/lib/semmle/python/Frameworks.qll +++ b/python/ql/lib/semmle/python/Frameworks.qll @@ -51,6 +51,6 @@ private import semmle.python.frameworks.Tornado private import semmle.python.frameworks.Twisted private import semmle.python.frameworks.Ujson private import semmle.python.frameworks.Urllib3 +private import semmle.python.frameworks.Xmltodict private import semmle.python.frameworks.Yaml private import semmle.python.frameworks.Yarl -private import semmle.python.frameworks.Xmltodict From 4ee71ae4a10b9bd221a3a21f8efc54a004117c7c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 10 Oct 2022 13:58:21 +0200 Subject: [PATCH 068/164] Python: Add support for `pymssql` package I also forgot to mention `PyMySQL` in frameworks.rst --- docs/codeql/support/reusables/frameworks.rst | 2 ++ python/ql/lib/semmle/python/Frameworks.qll | 1 + .../lib/semmle/python/frameworks/Pymssql.qll | 25 +++++++++++++++++++ .../2022-10-10-pymssql-modeling.md | 4 +++ .../frameworks/pymssql/ConceptsTest.expected | 0 .../frameworks/pymssql/ConceptsTest.ql | 2 ++ .../frameworks/pymssql/pep249.py | 6 +++++ 7 files changed, 40 insertions(+) create mode 100644 python/ql/lib/semmle/python/frameworks/Pymssql.qll create mode 100644 python/ql/src/change-notes/2022-10-10-pymssql-modeling.md create mode 100644 python/ql/test/library-tests/frameworks/pymssql/ConceptsTest.expected create mode 100644 python/ql/test/library-tests/frameworks/pymssql/ConceptsTest.ql create mode 100644 python/ql/test/library-tests/frameworks/pymssql/pep249.py diff --git a/docs/codeql/support/reusables/frameworks.rst b/docs/codeql/support/reusables/frameworks.rst index fc5410648cf..a67341ffe77 100644 --- a/docs/codeql/support/reusables/frameworks.rst +++ b/docs/codeql/support/reusables/frameworks.rst @@ -226,6 +226,8 @@ and the CodeQL library pack ``codeql/python-all`` (`changelog Date: Mon, 10 Oct 2022 14:10:52 +0200 Subject: [PATCH 069/164] Python: Update QLDocs on `PEP249Impl.qll` --- .../python/frameworks/internal/PEP249Impl.qll | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll index 5feaa7f61da..358f4ec1356 100644 --- a/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll @@ -146,7 +146,7 @@ module PEP249 { * Note: while `execute` method on a connection is not part of PEP249, if it is used, we * recognize it as an alias for constructing a cursor and calling `execute` on it. * - * See https://www.python.org/dev/peps/pep-0249/#id15. + * See https://peps.python.org/pep-0249/#execute. */ private DataFlow::TypeTrackingNode execute(DataFlow::TypeTracker t) { t.startInAttr("execute") and @@ -161,11 +161,18 @@ module PEP249 { * Note: while `execute` method on a connection is not part of PEP249, if it is used, we * recognize it as an alias for constructing a cursor and calling `execute` on it. * - * See https://www.python.org/dev/peps/pep-0249/#id15. + * See https://peps.python.org/pep-0249/#execute. */ DataFlow::Node execute() { execute(DataFlow::TypeTracker::end()).flowsTo(result) } - /** A call to the `execute` method on a cursor (or on a connection). */ + /** + * A call to the `execute` method on a cursor or a connection. + * + * See https://peps.python.org/pep-0249/#execute + * + * Note: While `execute` method on a connection is not part of PEP249, if it is used, we + * recognize it as an alias for constructing a cursor and calling `execute` on it. + */ private class ExecuteCall extends SqlExecution::Range, DataFlow::CallCfgNode { ExecuteCall() { this.getFunction() = execute() } From dba42d6bb8b06666813081bb8fa0fee0027ae795 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 10 Oct 2022 14:14:29 +0200 Subject: [PATCH 070/164] Python: Model `executemany` on PEP-249 DB APIs Note: I kept the modeling using the old approach with type-trackers instead of `DataFlow::MethodCallNode`. I would like a meta query for DCA to show sinks before doing this, so I can be absolutely sure we don't loose out on any important sinks on this... so will postpone this work to a small one-off task (added to my todo list). --- .../python/frameworks/internal/PEP249Impl.qll | 23 +++++++++++++++++++ .../2022-10-10-pep249-executemany-modeling.md | 4 ++++ .../frameworks/pymssql/pep249.py | 2 +- .../frameworks/pymysql/pep249.py | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md diff --git a/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll b/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll index 358f4ec1356..bf63bbb3731 100644 --- a/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll +++ b/python/ql/lib/semmle/python/frameworks/internal/PEP249Impl.qll @@ -178,4 +178,27 @@ module PEP249 { override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } } + + private DataFlow::TypeTrackingNode executemany(DataFlow::TypeTracker t) { + t.startInAttr("executemany") and + result in [Cursor::instance(), Connection::instance()] + or + exists(DataFlow::TypeTracker t2 | result = executemany(t2).track(t2, t)) + } + + private DataFlow::Node executemany() { executemany(DataFlow::TypeTracker::end()).flowsTo(result) } + + /** + * A call to the `executemany` method on a cursor or a connection. + * + * See https://peps.python.org/pep-0249/#executemany + * + * Note: While `executemany` method on a connection is not part of PEP249, if it is used, we + * recognize it as an alias for constructing a cursor and calling `executemany` on it. + */ + private class ExecutemanyCall extends SqlExecution::Range, DataFlow::CallCfgNode { + ExecutemanyCall() { this.getFunction() = executemany() } + + override DataFlow::Node getSql() { result in [this.getArg(0), this.getArgByName("sql")] } + } } diff --git a/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md b/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md new file mode 100644 index 00000000000..556520df64f --- /dev/null +++ b/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added model of `executemany` calls on PEP-249 compliant Database APIs, resulting in additional sinks for `py/sql-injection`. diff --git a/python/ql/test/library-tests/frameworks/pymssql/pep249.py b/python/ql/test/library-tests/frameworks/pymssql/pep249.py index bfbc9b6bc3b..2ecd00ad464 100644 --- a/python/ql/test/library-tests/frameworks/pymssql/pep249.py +++ b/python/ql/test/library-tests/frameworks/pymssql/pep249.py @@ -3,4 +3,4 @@ connection = pymssql.connect(host="localhost", user="user", password="passwd") cursor = connection.cursor() cursor.execute("some sql", (42,)) # $ getSql="some sql" -cursor.executemany("some sql", [(42,)]) # $ MISSING: getSql="some sql" +cursor.executemany("some sql", [(42,)]) # $ getSql="some sql" diff --git a/python/ql/test/library-tests/frameworks/pymysql/pep249.py b/python/ql/test/library-tests/frameworks/pymysql/pep249.py index 363e55f1fc3..1f9352875c5 100644 --- a/python/ql/test/library-tests/frameworks/pymysql/pep249.py +++ b/python/ql/test/library-tests/frameworks/pymysql/pep249.py @@ -3,3 +3,4 @@ connection = pymysql.connect(host="localhost", user="user", password="passwd") cursor = connection.cursor() cursor.execute("some sql", (42,)) # $ getSql="some sql" +cursor.executemany("some sql", [(42,)]) # $ getSql="some sql" From 15aab711c7d951fd58829ccddd56fed76abd3d64 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 10 Oct 2022 18:01:38 +0200 Subject: [PATCH 071/164] Kotlin: Add test showing missing java modifier --- .../kotlin/java_modifiers/libsrc/extlib/A.java | 6 ++++++ .../posix-only/kotlin/java_modifiers/test.expected | 2 ++ .../posix-only/kotlin/java_modifiers/test.kt | 6 ++++++ .../posix-only/kotlin/java_modifiers/test.py | 10 ++++++++++ .../posix-only/kotlin/java_modifiers/test.ql | 6 ++++++ 5 files changed, 30 insertions(+) create mode 100644 java/ql/integration-tests/posix-only/kotlin/java_modifiers/libsrc/extlib/A.java create mode 100644 java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected create mode 100644 java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.kt create mode 100644 java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.py create mode 100644 java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.ql diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/libsrc/extlib/A.java b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/libsrc/extlib/A.java new file mode 100644 index 00000000000..aa577f6526b --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/libsrc/extlib/A.java @@ -0,0 +1,6 @@ +package extlib; + +public class A { + protected void m() {} +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected new file mode 100644 index 00000000000..789fc118fd4 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected @@ -0,0 +1,2 @@ +| extlib.jar/extlib/A.class:0:0:0:0 | m | | +| test.kt:4:12:4:22 | m | override, protected | diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.kt b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.kt new file mode 100644 index 00000000000..49f233036b4 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.kt @@ -0,0 +1,6 @@ +import extlib.A; + +class B : A() { + override fun m() { } +} + diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.py b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.py new file mode 100644 index 00000000000..31c641d7013 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.py @@ -0,0 +1,10 @@ +from create_database_utils import * +import glob + +# Compile Java untraced. Note the Java source is hidden under `javasrc` so the Kotlin compiler +# will certainly reference the jar, not the source or class file for extlib.Lib + +os.mkdir('build') +runSuccessfully(["javac"] + glob.glob("libsrc/extlib/*.java") + ["-d", "build"]) +runSuccessfully(["jar", "cf", "extlib.jar", "-C", "build", "extlib"]) +run_codeql_database_create(["kotlinc test.kt -cp extlib.jar"], lang="java") diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.ql b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.ql new file mode 100644 index 00000000000..3c4cf8ac898 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.ql @@ -0,0 +1,6 @@ +import java + +query predicate mods(Method m, string modifiers) { + m.getName() = "m" and + modifiers = concat(string s | m.hasModifier(s) | s, ", ") +} From f2e2e3bc1d73f672687ddd2e75885b5e31830b95 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Mon, 10 Oct 2022 18:02:18 +0200 Subject: [PATCH 072/164] Kotlin: extract `protected` modifier from java class files --- java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt | 2 +- .../posix-only/kotlin/java_modifiers/test.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 307bb163180..ff3175b3305 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -231,7 +231,7 @@ open class KotlinFileExtractor( // default java visibility (top level) } JavaVisibilities.ProtectedAndPackage -> { - // default java visibility (member level) + addModifiers(id, "protected") } else -> logger.errorElement("Unexpected delegated visibility: $v", elementForLocation) } diff --git a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected index 789fc118fd4..459a8d9209d 100644 --- a/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected +++ b/java/ql/integration-tests/posix-only/kotlin/java_modifiers/test.expected @@ -1,2 +1,2 @@ -| extlib.jar/extlib/A.class:0:0:0:0 | m | | +| extlib.jar/extlib/A.class:0:0:0:0 | m | protected | | test.kt:4:12:4:22 | m | override, protected | From b94b78115e1dde39cdbcf8867ce21e0b830c2a65 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Mon, 10 Oct 2022 14:52:17 -0400 Subject: [PATCH 073/164] Style fix. Co-authored-by: Felicity Chapman --- .../CWE/CWE-926/ContentProviderIncompletePermissions.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql index d625fa211fc..a8c6cb99131 100644 --- a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql +++ b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.ql @@ -1,6 +1,6 @@ /** * @name Missing read or write permission in a content provider - * @description Android content providers which do not configure both read and write permissions can allow permission bypass + * @description Android content providers which do not configure both read and write permissions can allow permission bypass. * @kind problem * @problem.severity warning * @security-severity 8.2 From b6270ebe52ca668b40056b67afb38f112f0c5c42 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Mon, 10 Oct 2022 14:57:14 -0400 Subject: [PATCH 074/164] Apply suggestions from documentation review Co-authored-by: Felicity Chapman --- .../CWE/CWE-926/ContentProviderIncompletePermissions.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp index c615a7c13ca..eeb9024dea6 100644 --- a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp +++ b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp @@ -16,7 +16,7 @@ -

    To prevent permission bypass, provider elements should either +

    To prevent permission bypass, you should create provider elements that either specify both the android:readPermission and android:writePermission attributes, or specify the android:permission attribute. @@ -26,13 +26,13 @@

    In the following two (bad) examples, the provider is configured with only - read or write permissions.

    + read or write permissions. This allows a malicious application to bypass the permission check by requesting access to the unrestricted operation.

    -

    In the following (good) examples, the provider is configured with full permissions.

    +

    In the following (good) examples, the provider is configured with full permissions, protecting it from a permissions bypass.

    From 6c2eee3eb84003d4a5a5e46c83bc29bebf48b98b Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 10 Oct 2022 20:58:02 +0200 Subject: [PATCH 075/164] Ruby: Restrict regexp taint flow to `String` summaries --- .../ruby/dataflow/internal/DataFlowPrivate.qll | 3 +++ ruby/ql/lib/codeql/ruby/frameworks/core/String.qll | 14 +++++++++++++- .../ruby/regexp/internal/RegExpConfiguration.qll | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll index 41c2e6485fe..f49ddcdacd6 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll @@ -735,6 +735,9 @@ class SummaryNode extends NodeImpl, TSummaryNode { SummaryNode() { this = TSummaryNode(c, state) } + /** Gets the summarized callable that this node belongs to. */ + FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() { result = c } + override CfgScope getCfgScope() { none() } override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/core/String.qll b/ruby/ql/lib/codeql/ruby/frameworks/core/String.qll index 2b63531077a..e09ce6f3c42 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/core/String.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/core/String.qll @@ -3,7 +3,7 @@ private import codeql.ruby.AST private import codeql.ruby.ApiGraphs private import codeql.ruby.DataFlow -private import codeql.ruby.dataflow.FlowSummary +private import codeql.ruby.dataflow.FlowSummary as FlowSummary private import codeql.ruby.dataflow.internal.DataFlowDispatch private import codeql.ruby.controlflow.CfgNodes private import codeql.ruby.Regexp as RE @@ -107,6 +107,18 @@ module String { preservesValue = false } + /** A `String` callable with a flow summary. */ + abstract class SummarizedCallable extends FlowSummary::SummarizedCallable { + bindingset[this] + SummarizedCallable() { any() } + } + + abstract private class SimpleSummarizedCallable extends SummarizedCallable, + FlowSummary::SimpleSummarizedCallable { + bindingset[this] + SimpleSummarizedCallable() { any() } + } + private class NewSummary extends SummarizedCallable { NewSummary() { this = "String.new" } diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll index 5e1578eefef..310844fbbd9 100644 --- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll +++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll @@ -5,6 +5,10 @@ private import codeql.ruby.controlflow.CfgNodes private import codeql.ruby.dataflow.internal.tainttrackingforregexp.TaintTrackingImpl private import codeql.ruby.typetracking.TypeTracker private import codeql.ruby.ApiGraphs +private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate +private import codeql.ruby.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl +private import codeql.ruby.dataflow.FlowSummary as FlowSummary +private import codeql.ruby.frameworks.core.String class RegExpConfiguration extends Configuration { RegExpConfiguration() { this = "RegExpConfiguration" } @@ -30,6 +34,11 @@ class RegExpConfiguration extends Configuration { node = mce.getArgument(0) and mce.getReceiver() = trackRegexpType() ) + or + // only include taint flow through `String` summaries + FlowSummaryImpl::Private::Steps::summaryLocalStep(_, node, false) and + not node.(DataFlowPrivate::SummaryNode).getSummarizedCallable() instanceof + String::SummarizedCallable } } From 21caa4b03f6aae7da6c1659ef0047a2733603e32 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:38:31 -0400 Subject: [PATCH 076/164] spelling: across Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../ql/src/Likely Bugs/ThreadUnsafeICryptoTransformLambda.qhelp | 2 +- .../security/CWE-297/UnsafeHostnameVerification.java | 2 +- .../library-tests/CallGraph/code/runtime_decision.py | 2 +- .../frameworks/modeling-example/NaiveModel.expected | 2 +- .../frameworks/modeling-example/ProperModel.expected | 2 +- .../ql/test/library-tests/frameworks/modeling-example/test.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/csharp/ql/src/Likely Bugs/ThreadUnsafeICryptoTransformLambda.qhelp b/csharp/ql/src/Likely Bugs/ThreadUnsafeICryptoTransformLambda.qhelp index 1ccdceb7412..325a4531afe 100644 --- a/csharp/ql/src/Likely Bugs/ThreadUnsafeICryptoTransformLambda.qhelp +++ b/csharp/ql/src/Likely Bugs/ThreadUnsafeICryptoTransformLambda.qhelp @@ -6,7 +6,7 @@ -

    Create new instances of the object that implements or has a field of type System.Security.Cryptography.ICryptoTransform to avoid sharing it accross multiple threads.

    +

    Create new instances of the object that implements or has a field of type System.Security.Cryptography.ICryptoTransform to avoid sharing it across multiple threads.

    diff --git a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java index c893e0b8eef..8343f50ace1 100644 --- a/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java +++ b/java/ql/test/query-tests/security/CWE-297/UnsafeHostnameVerification.java @@ -46,7 +46,7 @@ public class UnsafeHostnameVerification { private void functionThatActuallyDisablesVerification() { HttpsURLConnection.setDefaultHostnameVerifier((name, s) -> true); // GOOD [but detected as BAD], because we only // check guards inside a function - // and not accross function calls. This is considerer GOOD because the call to + // and not across function calls. This is considerer GOOD because the call to // `functionThatActuallyDisablesVerification` is guarded by a feature flag in // `testGuardedByFlagAccrossCalls`. // Although this is not ideal as another function could directly call diff --git a/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py index 7be3f83fe68..fd2f7773ced 100644 --- a/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py +++ b/python/ql/test/experimental/library-tests/CallGraph/code/runtime_decision.py @@ -1,7 +1,7 @@ import sys import random -# hmm, annoying that you have to keep names unique accross files :| +# hmm, annoying that you have to keep names unique across files :| # since I like to use foo and bar ALL the time :D # name:rd_foo diff --git a/python/ql/test/library-tests/frameworks/modeling-example/NaiveModel.expected b/python/ql/test/library-tests/frameworks/modeling-example/NaiveModel.expected index 4f88ba7b4e1..3c432f49458 100644 --- a/python/ql/test/library-tests/frameworks/modeling-example/NaiveModel.expected +++ b/python/ql/test/library-tests/frameworks/modeling-example/NaiveModel.expected @@ -30,7 +30,7 @@ subpaths #select | test.py:22:10:22:24 | ControlFlowNode for Attribute() | test.py:21:11:21:18 | ControlFlowNode for source() | test.py:22:10:22:24 | ControlFlowNode for Attribute() | test flow (naive): test_simple | | test.py:33:10:33:12 | ControlFlowNode for val | test.py:29:11:29:18 | ControlFlowNode for source() | test.py:33:10:33:12 | ControlFlowNode for val | test flow (naive): test_alias | -| test.py:41:10:41:12 | ControlFlowNode for val | test.py:45:11:45:18 | ControlFlowNode for source() | test.py:41:10:41:12 | ControlFlowNode for val | test flow (naive): test_accross_functions | +| test.py:41:10:41:12 | ControlFlowNode for val | test.py:45:11:45:18 | ControlFlowNode for source() | test.py:41:10:41:12 | ControlFlowNode for val | test flow (naive): test_across_functions | | test.py:54:10:54:12 | ControlFlowNode for val | test.py:70:11:70:18 | ControlFlowNode for source() | test.py:54:10:54:12 | ControlFlowNode for val | test flow (naive): test_deeply_nested | | test.py:79:10:79:12 | ControlFlowNode for val | test.py:83:11:83:18 | ControlFlowNode for source() | test.py:79:10:79:12 | ControlFlowNode for val | test flow (naive): test_pass_bound_method | | test.py:91:10:91:12 | ControlFlowNode for val | test.py:107:11:107:18 | ControlFlowNode for source() | test.py:91:10:91:12 | ControlFlowNode for val | test flow (naive): test_deeply_nested_bound_method | diff --git a/python/ql/test/library-tests/frameworks/modeling-example/ProperModel.expected b/python/ql/test/library-tests/frameworks/modeling-example/ProperModel.expected index 9fee0cc2941..e3f2a30c96a 100644 --- a/python/ql/test/library-tests/frameworks/modeling-example/ProperModel.expected +++ b/python/ql/test/library-tests/frameworks/modeling-example/ProperModel.expected @@ -70,7 +70,7 @@ subpaths #select | test.py:22:10:22:24 | ControlFlowNode for Attribute() | test.py:21:11:21:18 | ControlFlowNode for source() | test.py:22:10:22:24 | ControlFlowNode for Attribute() | test flow (proper): test_simple | | test.py:33:10:33:12 | ControlFlowNode for val | test.py:29:11:29:18 | ControlFlowNode for source() | test.py:33:10:33:12 | ControlFlowNode for val | test flow (proper): test_alias | -| test.py:41:10:41:12 | ControlFlowNode for val | test.py:45:11:45:18 | ControlFlowNode for source() | test.py:41:10:41:12 | ControlFlowNode for val | test flow (proper): test_accross_functions | +| test.py:41:10:41:12 | ControlFlowNode for val | test.py:45:11:45:18 | ControlFlowNode for source() | test.py:41:10:41:12 | ControlFlowNode for val | test flow (proper): test_across_functions | | test.py:54:10:54:12 | ControlFlowNode for val | test.py:70:11:70:18 | ControlFlowNode for source() | test.py:54:10:54:12 | ControlFlowNode for val | test flow (proper): test_deeply_nested | | test.py:79:10:79:12 | ControlFlowNode for val | test.py:83:11:83:18 | ControlFlowNode for source() | test.py:79:10:79:12 | ControlFlowNode for val | test flow (proper): test_pass_bound_method | | test.py:91:10:91:12 | ControlFlowNode for val | test.py:107:11:107:18 | ControlFlowNode for source() | test.py:91:10:91:12 | ControlFlowNode for val | test flow (proper): test_deeply_nested_bound_method | diff --git a/python/ql/test/library-tests/frameworks/modeling-example/test.py b/python/ql/test/library-tests/frameworks/modeling-example/test.py index 6fe7bb3fcad..50b82df7068 100644 --- a/python/ql/test/library-tests/frameworks/modeling-example/test.py +++ b/python/ql/test/library-tests/frameworks/modeling-example/test.py @@ -41,7 +41,7 @@ def sink_func(arg): sink(val) -def test_accross_functions(): +def test_across_functions(): src = source() sink_func(src) From b1052992fe3be705c27521a02ccc284442ee3d2c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 05:44:25 -0400 Subject: [PATCH 077/164] spelling: against Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- go/ql/src/experimental/CWE-369/DivideByZero.qhelp | 2 +- .../experimental/CWE-942/CorsMisconfiguration.go | 14 +++++++------- .../test/query-tests/Security/CWE-918/websocket.go | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go/ql/src/experimental/CWE-369/DivideByZero.qhelp b/go/ql/src/experimental/CWE-369/DivideByZero.qhelp index ae39d1df890..dc5cb2cf205 100644 --- a/go/ql/src/experimental/CWE-369/DivideByZero.qhelp +++ b/go/ql/src/experimental/CWE-369/DivideByZero.qhelp @@ -18,7 +18,7 @@ possibly causing a divide-by-zero panic.

    -This can be fixed by testing the divisor against against zero: +This can be fixed by testing the divisor against zero:

    diff --git a/go/ql/test/experimental/CWE-942/CorsMisconfiguration.go b/go/ql/test/experimental/CWE-942/CorsMisconfiguration.go index cac752dbcb2..5e6bf92ddcf 100644 --- a/go/ql/test/experimental/CWE-942/CorsMisconfiguration.go +++ b/go/ql/test/experimental/CWE-942/CorsMisconfiguration.go @@ -120,7 +120,7 @@ func main() { } }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - // OK-ish: the input origin header is validated agains a whitelist. + // OK-ish: the input origin header is validated against a whitelist. responseHeader := w.Header() { origin := req.Header.Get("origin") @@ -137,7 +137,7 @@ func main() { }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { originSuffix := ".example.com" - // OK-ish: the input origin header is validated agains a suffix. + // OK-ish: the input origin header is validated against a suffix. origin := req.Header.Get("Origin") if origin != "" && (originSuffix == "" || strings.HasSuffix(origin, originSuffix)) { w.Header().Set("Access-Control-Allow-Origin", origin) @@ -152,7 +152,7 @@ func main() { }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { originSuffix := ".example.com" - // OK-ish: the input origin header is validated agains a whitelist. + // OK-ish: the input origin header is validated against a whitelist. origin := req.Header.Get("Origin") if origin != "" && (originSuffix == "" || AccessControlAllowOrigins[origin]) { w.Header().Set("Access-Control-Allow-Origin", origin) @@ -166,7 +166,7 @@ func main() { } }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - // OK-ish: the input origin header is validated agains a whitelist. + // OK-ish: the input origin header is validated against a whitelist. origin := req.Header.Get("origin") if origin != "" && origin != "null" { if len(AccessControlAllowOrigins) == 0 || AccessControlAllowOrigins[origin] { @@ -178,7 +178,7 @@ func main() { } }) // http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - // // OK-ish: the input origin header is validated agains a whitelist. + // // OK-ish: the input origin header is validated against a whitelist. // origin := req.Header.Get("origin") // if origin != "" && origin != "null" { // if _, ok := AccessControlAllowOrigins[origin]; ok { @@ -190,7 +190,7 @@ func main() { // } // }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - // OK-ish: the input origin header is validated agains a whitelist. + // OK-ish: the input origin header is validated against a whitelist. if origin := req.Header.Get("Origin"); cors[origin] { w.Header().Set("Access-Control-Allow-Origin", origin) } else if len(origin) > 0 && cors["*"] { @@ -202,7 +202,7 @@ func main() { w.Header().Set("Access-Control-Allow-Credentials", "true") }) http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { - // OK-ish: the input origin header is validated agains a whitelist. + // OK-ish: the input origin header is validated against a whitelist. origin := req.Header.Get("origin") for _, v := range GetAllowOrigin() { if v == origin { diff --git a/go/ql/test/query-tests/Security/CWE-918/websocket.go b/go/ql/test/query-tests/Security/CWE-918/websocket.go index db613fe5fa5..328200770ae 100644 --- a/go/ql/test/query-tests/Security/CWE-918/websocket.go +++ b/go/ql/test/query-tests/Security/CWE-918/websocket.go @@ -96,7 +96,7 @@ func test() { http.HandleFunc("/ex5", func(w http.ResponseWriter, r *http.Request) { untrustedInput := r.Referer() - // good as input is tested againt regex + // good as input is tested against regex if m, _ := regexp.MatchString("ws://localhost:12345/*", untrustedInput); m { nhooyr.Dial(context.TODO(), untrustedInput, nil) } From b95af76dab09565f32d58afe844cd69a74dca9c6 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 05:45:56 -0400 Subject: [PATCH 078/164] spelling: although Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- python/ql/src/Security/CWE-611/Xxe.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/Security/CWE-611/Xxe.qhelp b/python/ql/src/Security/CWE-611/Xxe.qhelp index 19bbc955fd6..2260966f480 100644 --- a/python/ql/src/Security/CWE-611/Xxe.qhelp +++ b/python/ql/src/Security/CWE-611/Xxe.qhelp @@ -38,7 +38,7 @@ default parser from lxml.etree allows local external entities t

    To guard against XXE attacks with the lxml library, you should create a parser with resolve_entities set to false. This means that no -entity expansion is undertaken, althuogh standard predefined entities such as +entity expansion is undertaken, although standard predefined entities such as &gt;, for writing > inside the text of an XML element, are still allowed.

    From 3358c5f664971e06fa5e96f83fba86804fe4600c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:38:57 -0400 Subject: [PATCH 079/164] spelling: apparent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- javascript/ql/src/LanguageFeatures/NonLinearPattern.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/LanguageFeatures/NonLinearPattern.qhelp b/javascript/ql/src/LanguageFeatures/NonLinearPattern.qhelp index 7690d9df1ce..3013551354a 100644 --- a/javascript/ql/src/LanguageFeatures/NonLinearPattern.qhelp +++ b/javascript/ql/src/LanguageFeatures/NonLinearPattern.qhelp @@ -40,7 +40,7 @@ From context, it appears that the second binding should have been for variable <

    -This can sometimes happen in TypeScript, due to the apparant similarity between property patterns +This can sometimes happen in TypeScript, due to the apparent similarity between property patterns and type annotations. In the following example, the function uses a pattern parameter with properties x and y. These appear to have type number, but are in fact untyped properties both stored in a variable named number.

    From c2a0dbe71589815d04b80a840ec06929a8449cad Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:42 -0400 Subject: [PATCH 080/164] spelling: application Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../experimental/Security/CWE/CWE-470/UnsafeReflection.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-470/UnsafeReflection.qhelp b/java/ql/src/experimental/Security/CWE/CWE-470/UnsafeReflection.qhelp index b4c66b9ef00..e85a0aef371 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-470/UnsafeReflection.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-470/UnsafeReflection.qhelp @@ -3,7 +3,7 @@

    -Allowing users to freely choose the name of a class to instantiate could provide means to attack a vulnerable appplication. +Allowing users to freely choose the name of a class to instantiate could provide means to attack a vulnerable application.

    From 6db36616cd75eac5dd354c87b22fed1549213ded Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:39:07 -0400 Subject: [PATCH 081/164] spelling: arbitrary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Security/CWE/CWE-094/SpringViewManipulation.qhelp | 2 +- javascript/ql/src/CHANGELOG.md | 2 +- javascript/ql/src/Security/CWE-079/XssThroughDom.qhelp | 2 +- javascript/ql/src/change-notes/released/0.0.10.md | 2 +- .../ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp index dadd20dfdb7..45c981f0e29 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp @@ -8,7 +8,7 @@ including invocation of methods available in the JVM.

    - An unrestricted view name manipulation vulnerability in Spring Framework could lead to attacker-controlled arbitary SpEL expressions being evaluated using attacker-controlled data, which may in turn allow an attacker to run arbitrary code. + An unrestricted view name manipulation vulnerability in Spring Framework could lead to attacker-controlled arbitrary SpEL expressions being evaluated using attacker-controlled data, which may in turn allow an attacker to run arbitrary code.

    Note: two related variants of this problem are detected by different queries, `java/spring-view-manipulation` and `java/spring-view-manipulation-implicit`. The first detects taint flow problems where the return types is always String. While the latter, `java/spring-view-manipulation-implicit` detects cases where the request mapping method has a non-string return type such as void. diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index b166176b56f..be49d069c0c 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -123,7 +123,7 @@ No user-facing changes. ### New Queries -* A new query, `js/unsafe-code-construction`, has been added to the query suite, highlighting libraries that may leave clients vulnerable to arbitary code execution. +* A new query, `js/unsafe-code-construction`, has been added to the query suite, highlighting libraries that may leave clients vulnerable to arbitrary code execution. The query is not run by default. * A new query `js/file-system-race` has been added. The query detects when there is time between a file being checked and used. The query is not run by default. * A new query `js/jwt-missing-verification` has been added. The query detects applications that don't verify JWT tokens. diff --git a/javascript/ql/src/Security/CWE-079/XssThroughDom.qhelp b/javascript/ql/src/Security/CWE-079/XssThroughDom.qhelp index 5aa2fe63253..f3c6d27c5de 100644 --- a/javascript/ql/src/Security/CWE-079/XssThroughDom.qhelp +++ b/javascript/ql/src/Security/CWE-079/XssThroughDom.qhelp @@ -33,7 +33,7 @@ selector to determine which element should be manipulated.

    However, if an attacker can control the data-target attribute, then the value of target can be used to cause the $ function -to execute arbitary JavaScript. +to execute arbitrary JavaScript.

    The above vulnerability can be fixed by using $.find instead of $. diff --git a/javascript/ql/src/change-notes/released/0.0.10.md b/javascript/ql/src/change-notes/released/0.0.10.md index ef8f27dd689..029d450716f 100644 --- a/javascript/ql/src/change-notes/released/0.0.10.md +++ b/javascript/ql/src/change-notes/released/0.0.10.md @@ -2,7 +2,7 @@ ### New Queries -* A new query, `js/unsafe-code-construction`, has been added to the query suite, highlighting libraries that may leave clients vulnerable to arbitary code execution. +* A new query, `js/unsafe-code-construction`, has been added to the query suite, highlighting libraries that may leave clients vulnerable to arbitrary code execution. The query is not run by default. * A new query `js/file-system-race` has been added. The query detects when there is time between a file being checked and used. The query is not run by default. * A new query `js/jwt-missing-verification` has been added. The query detects applications that don't verify JWT tokens. diff --git a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp index c720cd78745..406ba24935b 100644 --- a/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp +++ b/ruby/ql/src/queries/security/cwe-502/UnsafeDeserialization.qhelp @@ -12,7 +12,7 @@ to execute arbitrary code.

    Avoid deserialization of untrusted data if possible. If the architecture permits -it, use serialization formats that cannot represent arbitarary objects. For +it, use serialization formats that cannot represent arbitrary objects. For libraries that support it, such as the Ruby standard library's JSON module, ensure that the parser is configured to disable deserialization of arbitrary objects. From 5755159f08cbdc2867158c845f7c00046da38e27 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:18:18 -0400 Subject: [PATCH 082/164] spelling: authentication Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp b/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp index 34240696b4d..e3b57cdf328 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp @@ -3,7 +3,7 @@

    Transport Layer Security (TLS) provides a number of security features such as -confidentiality, integrity, replay prevention and authenticatin. +confidentiality, integrity, replay prevention and authentication. There are several versions of TLS protocols. The latest is TLS 1.3. Unfortunately, older versions were found to be vulnerable to a number of attacks.

    From 879158a653d83e93f18c0cdbe93994ba63f7b5a1 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:39:33 -0400 Subject: [PATCH 083/164] spelling: behavior Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp index 5cc0ae21af9..fe25fae8f4a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp @@ -49,7 +49,7 @@ pointer overflow.

    While it's not the subject of this query, the expression ptr + i < -ptr_end is also an invalid range check. It's undefined behavor in +ptr_end is also an invalid range check. It's undefined behavior in C/C++ to create a pointer that points more than one past the end of an allocation.

    From 0581f2fe1cbd930889d0fde04889707328d9f3a5 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:23:51 -0400 Subject: [PATCH 084/164] spelling: can Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- csharp/ql/src/Likely Bugs/ConstantComparison.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Likely Bugs/ConstantComparison.qhelp b/csharp/ql/src/Likely Bugs/ConstantComparison.qhelp index e1d6f9d5f9f..5e52142c84e 100644 --- a/csharp/ql/src/Likely Bugs/ConstantComparison.qhelp +++ b/csharp/ql/src/Likely Bugs/ConstantComparison.qhelp @@ -5,7 +5,7 @@

    Comparisons which always yield the same result are unnecessary and may indicate a bug in the - logic. This can can happen when the data type of one of the operands has a limited range of values. + logic. This can happen when the data type of one of the operands has a limited range of values. For example unsigned integers are always greater than or equal to zero, and byte values are always less than 256.

    From 9b372f3db47ed611f670d4a181dfa6ac2e19896f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:40:06 -0400 Subject: [PATCH 085/164] spelling: characters Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- go/ql/src/experimental/CWE-918/SSRF.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/src/experimental/CWE-918/SSRF.qhelp b/go/ql/src/experimental/CWE-918/SSRF.qhelp index 7eeeabb68f6..ea37350698e 100644 --- a/go/ql/src/experimental/CWE-918/SSRF.qhelp +++ b/go/ql/src/experimental/CWE-918/SSRF.qhelp @@ -14,7 +14,7 @@ server side request forgery attacks, where the attacker controls the request tar

    To guard against server side request forgery, it is advisable to avoid putting user input directly into a network request. If using user input is necessary, then it must be validated. It is recommended to only allow -user input consisting of alphanumeric characters. Simply URL-encoding other chracters is not always a solution, +user input consisting of alphanumeric characters. Simply URL-encoding other characters is not always a solution, for example because a downstream entity that is itself vulnerable may decode again before forwarding the request.

    From 88408fbd59a4167ebad4501ec1c48f5b36fec325 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:44 -0400 Subject: [PATCH 086/164] spelling: ciphertext Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- csharp/ql/src/Security Features/Encryption using ECB.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Security Features/Encryption using ECB.qhelp b/csharp/ql/src/Security Features/Encryption using ECB.qhelp index 0315813d7bc..db66106f834 100644 --- a/csharp/ql/src/Security Features/Encryption using ECB.qhelp +++ b/csharp/ql/src/Security Features/Encryption using ECB.qhelp @@ -4,7 +4,7 @@

    ECB should not be used as a mode for encryption. It has dangerous weaknesses. Data is encrypted the same way every time -meaning the same plaintext input will always produce the same cyphertext. This makes encrypted messages vulnerable +meaning the same plaintext input will always produce the same ciphertext. This makes encrypted messages vulnerable to replay attacks.

    From e6998d40c3978fa0017db71bcfa9e99a88c2acb1 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:43 -0400 Subject: [PATCH 087/164] spelling: cryptographically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- go/ql/src/experimental/CWE-321/HardcodedKeys.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/src/experimental/CWE-321/HardcodedKeys.qhelp b/go/ql/src/experimental/CWE-321/HardcodedKeys.qhelp index b641cbda184..ddbb4572eae 100644 --- a/go/ql/src/experimental/CWE-321/HardcodedKeys.qhelp +++ b/go/ql/src/experimental/CWE-321/HardcodedKeys.qhelp @@ -18,7 +18,7 @@

    - Generating a cryptograhically secure secret key during application initialization and using this generated key for future JWT signing requests can prevent this vulnerability. + Generating a cryptographically secure secret key during application initialization and using this generated key for future JWT signing requests can prevent this vulnerability.

    From 3e6477f8787846119d2907f81531a3ae1daf6df5 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:34:16 -0400 Subject: [PATCH 088/164] spelling: currently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp b/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp index e3b57cdf328..6e9225f3b79 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-327/UnsafeTlsVersion.qhelp @@ -10,7 +10,7 @@ Unfortunately, older versions were found to be vulnerable to a number of attacks -

    An application should use TLS 1.3. Currenlty, TLS 1.2 is also considered acceptable.

    +

    An application should use TLS 1.3. Currently, TLS 1.2 is also considered acceptable.

    From c08cfe23e092fe6d85824858a4c33f6ba0c78dcb Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:40:28 -0400 Subject: [PATCH 089/164] spelling: dependencies Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Metrics/Namespaces/StableNamespaces.qhelp | 2 +- cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.qhelp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Metrics/Namespaces/StableNamespaces.qhelp b/cpp/ql/src/Metrics/Namespaces/StableNamespaces.qhelp index 44bdc327634..13eef3113da 100644 --- a/cpp/ql/src/Metrics/Namespaces/StableNamespaces.qhelp +++ b/cpp/ql/src/Metrics/Namespaces/StableNamespaces.qhelp @@ -11,7 +11,7 @@ by changes to other packages. If this metric value is high, a package is easily influenced. If the values is low, the impact of changes to other packages is likely to be minimal. Instability is estimated as the number of outgoing dependencies relative to the total - number of depencies.

    + number of dependencies.

    diff --git a/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.qhelp b/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.qhelp index bac1609760b..2f6620f95aa 100644 --- a/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.qhelp +++ b/cpp/ql/src/Metrics/Namespaces/UnstableNamespaces.qhelp @@ -11,7 +11,7 @@ by changes to other packages. If this metric value is high, a package is easily influenced. If the values is low, the impact of changes to other packages is likely to be minimal. Instability is estimated as the number of outgoing dependencies relative to the total - number of depencies.

    + number of dependencies.

    From 3b9546f02e6f2d56916eefccc181e1b02b8afc4b Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:45 -0400 Subject: [PATCH 090/164] spelling: deserialization Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp b/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp index 02ee7d7dab1..67d1a89f8fa 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-502/UnsafeDeserializationRmi.qhelp @@ -50,7 +50,7 @@ whose methods use only primitive types and strings:

    -The next example shows how to set a deserilization filter for a remote object: +The next example shows how to set a deserialization filter for a remote object:

    From cbea5ec40cc11f7f65febd7b6467d278825aa26f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:45 -0400 Subject: [PATCH 091/164] spelling: executables Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- javascript/ql/src/Security/CWE-829/InsecureDownload.qhelp | 2 +- ruby/ql/src/queries/security/cwe-829/InsecureDownload.qhelp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-829/InsecureDownload.qhelp b/javascript/ql/src/Security/CWE-829/InsecureDownload.qhelp index 807f6be401e..56585485a4f 100644 --- a/javascript/ql/src/Security/CWE-829/InsecureDownload.qhelp +++ b/javascript/ql/src/Security/CWE-829/InsecureDownload.qhelp @@ -4,7 +4,7 @@

    - Downloading executeables or other sensitive files over an unencrypted connection + Downloading executables or other sensitive files over an unencrypted connection can leave a server open to man-in-the-middle attacks (MITM). Such an attack can allow an attacker to insert arbitrary content into the downloaded file, and in the worst case, allow the attacker to execute diff --git a/ruby/ql/src/queries/security/cwe-829/InsecureDownload.qhelp b/ruby/ql/src/queries/security/cwe-829/InsecureDownload.qhelp index 7c4d6131568..44726e36aa9 100644 --- a/ruby/ql/src/queries/security/cwe-829/InsecureDownload.qhelp +++ b/ruby/ql/src/queries/security/cwe-829/InsecureDownload.qhelp @@ -4,7 +4,7 @@

    - Downloading executeables or other sensitive files over an unencrypted connection + Downloading executables or other sensitive files over an unencrypted connection can leave a server open to man-in-the-middle attacks (MITM). Such an attack can allow an attacker to insert arbitrary content into the downloaded file, and in the worst case, allow the attacker to execute From 479a4fb4a2fc483de98ca657f61c054ad998bcf0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:40:51 -0400 Subject: [PATCH 092/164] spelling: expectations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Documentation/DocumentApi.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Documentation/DocumentApi.qhelp b/cpp/ql/src/Documentation/DocumentApi.qhelp index 9bc19d35056..4154e5cebc4 100644 --- a/cpp/ql/src/Documentation/DocumentApi.qhelp +++ b/cpp/ql/src/Documentation/DocumentApi.qhelp @@ -15,7 +15,7 @@ As an exception, because their purpose is usually obvious, it is not necessary t

    -Add comments to document the purpose of the function. In particular, ensure that the public API of the function is carefully documented. This reduces the chance that a future change to the function will introduce a defect by changing the API and breaking the expections of the calling functions. +Add comments to document the purpose of the function. In particular, ensure that the public API of the function is carefully documented. This reduces the chance that a future change to the function will introduce a defect by changing the API and breaking the expectations of the calling functions.

    From e8754967ea8cc581496f407078ce03c191a0cba6 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:41:00 -0400 Subject: [PATCH 093/164] spelling: explaining Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- javascript/ql/src/Statements/UselessComparisonTest.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/UselessComparisonTest.qhelp b/javascript/ql/src/Statements/UselessComparisonTest.qhelp index 27483f5516a..9af227fe4b7 100644 --- a/javascript/ql/src/Statements/UselessComparisonTest.qhelp +++ b/javascript/ql/src/Statements/UselessComparisonTest.qhelp @@ -17,7 +17,7 @@ longer needed, remove it.

    -If the check is needed to guard against NaN values, insert a comment explaning the possibility of NaN. +If the check is needed to guard against NaN values, insert a comment explaining the possibility of NaN.

    From b5bed9cbf55c6f5accceaaac0902890f017d19f7 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:41:08 -0400 Subject: [PATCH 094/164] spelling: explicitly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Architecture/Refactoring Opportunities/UnusedBean.qhelp | 2 +- ruby/ql/src/CHANGELOG.md | 2 +- ruby/ql/src/change-notes/released/0.0.4.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.qhelp b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.qhelp index 1c32e1cf952..7d4dfcf82a6 100644 --- a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.qhelp +++ b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.qhelp @@ -16,7 +16,7 @@ A bean definition is considered to be used if one or more of the following is tr
  • The bean is injected in to a constructor or method of a live bean due to autowiring. This includes autowiring by annotation (@Autowired or @Inject), and autowiring configured by the autowired attribute within bean configuration files.
  • -
  • The bean is explictly loaded from a factory bean. It is not always possible to determine when +
  • The bean is explicitly loaded from a factory bean. It is not always possible to determine when this occurs, because factory beans are loaded using a String value, which may contain arbitrary values.
  • The bean is called reflectively by the Spring framework. For example, if the class is a Spring diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index 6792b3e61c0..07c98ee6c9a 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -119,7 +119,7 @@ ### New Queries * A new query (`rb/request-forgery`) has been added. The query finds HTTP requests made with user-controlled URLs. -* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explictly disabled. +* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explicitly disabled. ### Query Metadata Changes diff --git a/ruby/ql/src/change-notes/released/0.0.4.md b/ruby/ql/src/change-notes/released/0.0.4.md index e406cd11ae8..7a5116b2ee9 100644 --- a/ruby/ql/src/change-notes/released/0.0.4.md +++ b/ruby/ql/src/change-notes/released/0.0.4.md @@ -3,7 +3,7 @@ ### New Queries * A new query (`rb/request-forgery`) has been added. The query finds HTTP requests made with user-controlled URLs. -* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explictly disabled. +* A new query (`rb/csrf-protection-disabled`) has been added. The query finds cases where cross-site forgery protection is explicitly disabled. ### Query Metadata Changes From 86ee8c2d006a444b80cd9e48420e46a568eae756 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:23:20 -0400 Subject: [PATCH 095/164] spelling: first Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp index ab40910f5d3..69402cc08ae 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp +++ b/cpp/ql/src/experimental/Security/CWE/CWE-754/ImproperCheckReturnValueScanf.qhelp @@ -12,7 +12,7 @@ The user should check the return value of `scanf` and related functions and chec

    -

    The first first example below is correct, as value of `i` is only read once it is checked that `scanf` has read one item. The second example is incorrect, as the return value of `scanf` is not checked, and as `scanf` might have failed to read any item before returning.

    +

    The first example below is correct, as value of `i` is only read once it is checked that `scanf` has read one item. The second example is incorrect, as the return value of `scanf` is not checked, and as `scanf` might have failed to read any item before returning.

    From 29da681bbb63bcac43eb3dfce8017847a75a70c0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:41:20 -0400 Subject: [PATCH 096/164] spelling: functions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.qhelp b/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.qhelp index f283056d2a8..1af359e5c50 100644 --- a/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.qhelp +++ b/cpp/ql/src/Metrics/Classes/CLackOfCohesionCK.qhelp @@ -6,7 +6,7 @@

    This metric provides an indication of the lack of cohesion of a class, using a method proposed by Chidamber and Kemerer in 1994. The idea -behind measuring a class's cohesion is that most funcions in well-designed +behind measuring a class's cohesion is that most functions in well-designed classes will access the same fields. Types that exhibit a lack of cohesion are often trying to take on multiple responsibilities, and should be split into several smaller classes. From f06c15b86ad38caac6f314fb6121ff79090722a4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:41:33 -0400 Subject: [PATCH 097/164] spelling: genuinely Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Best Practices/Unused Entities/UnusedStaticVariables.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.qhelp b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.qhelp index 6e0c263e4fa..b8838c26c52 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.qhelp +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.qhelp @@ -11,7 +11,7 @@ caused by an unhandled case.

    -

    Check that the unused static variable does not indicate a defect, for example, an unhandled case. If the static variable is genuinuely not needed, +

    Check that the unused static variable does not indicate a defect, for example, an unhandled case. If the static variable is genuinely not needed, then removing it will make code more readable. If the static variable is needed then you should update the code to fix the defect.

    From 0a4c724b69341f2b3e3fc5c52452d0ac8653b81f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:43:03 -0400 Subject: [PATCH 098/164] spelling: implementation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- go/ql/src/Security/CWE-322/InsecureHostKeyCallback.qhelp | 2 +- javascript/ql/lib/semmle/javascript/PrintAst.qll | 2 +- javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go/ql/src/Security/CWE-322/InsecureHostKeyCallback.qhelp b/go/ql/src/Security/CWE-322/InsecureHostKeyCallback.qhelp index 02fa1e6bc8d..ce4872fa66c 100644 --- a/go/ql/src/Security/CWE-322/InsecureHostKeyCallback.qhelp +++ b/go/ql/src/Security/CWE-322/InsecureHostKeyCallback.qhelp @@ -30,7 +30,7 @@ When the allow list contains only a single host key then the function Fixe -

    The following example shows the use of InsecureIgnoreHostKey and an insecure host key callback implemention commonly used in non-production code.

    +

    The following example shows the use of InsecureIgnoreHostKey and an insecure host key callback implementation commonly used in non-production code.

    diff --git a/javascript/ql/lib/semmle/javascript/PrintAst.qll b/javascript/ql/lib/semmle/javascript/PrintAst.qll index 29b1d619016..a4d71362818 100644 --- a/javascript/ql/lib/semmle/javascript/PrintAst.qll +++ b/javascript/ql/lib/semmle/javascript/PrintAst.qll @@ -161,7 +161,7 @@ private module PrintJavaScript { /** * A print node representing an `ASTNode`. * - * Provides a default implemention that works for some (but not all) ASTNode's. + * Provides a default implementation that works for some (but not all) ASTNode's. * More specific subclasses can override this class to get more specific behavior. * * The more specific subclasses are mostly used aggregate the children of the `ASTNode`. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll index 3a5ef400801..1adaed5b439 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll @@ -7,7 +7,7 @@ import javascript /** * Provides classes implementing data-flow for Immutable. * - * The implemention rely on the flowsteps implemented in `Collections.qll`. + * The implementation rely on the flowsteps implemented in `Collections.qll`. */ private module Immutable { /** From 8f7e76f0cb2a33ca3ff279e1582f9b6a618d72a6 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 11 Oct 2022 03:59:08 -0400 Subject: [PATCH 099/164] spelling: initialization Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- ...JMXConnectorServerFactoryEnvironmentInitialization.java} | 0 ...CorrectRMIConnectorServerEnvironmentInitialization.java} | 0 .../CWE-665/InsecureRmiJmxEnvironmentConfiguration.qhelp | 6 +++--- 3 files changed, 3 insertions(+), 3 deletions(-) rename java/ql/src/experimental/Security/CWE/CWE-665/{CorrectJMXConnectorServerFactoryEnvironmentInitialisation.java => CorrectJMXConnectorServerFactoryEnvironmentInitialization.java} (100%) rename java/ql/src/experimental/Security/CWE/CWE-665/{CorrectRMIConnectorServerEnvironmentInitalisation.java => CorrectRMIConnectorServerEnvironmentInitialization.java} (100%) diff --git a/java/ql/src/experimental/Security/CWE/CWE-665/CorrectJMXConnectorServerFactoryEnvironmentInitialisation.java b/java/ql/src/experimental/Security/CWE/CWE-665/CorrectJMXConnectorServerFactoryEnvironmentInitialization.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-665/CorrectJMXConnectorServerFactoryEnvironmentInitialisation.java rename to java/ql/src/experimental/Security/CWE/CWE-665/CorrectJMXConnectorServerFactoryEnvironmentInitialization.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-665/CorrectRMIConnectorServerEnvironmentInitalisation.java b/java/ql/src/experimental/Security/CWE/CWE-665/CorrectRMIConnectorServerEnvironmentInitialization.java similarity index 100% rename from java/ql/src/experimental/Security/CWE/CWE-665/CorrectRMIConnectorServerEnvironmentInitalisation.java rename to java/ql/src/experimental/Security/CWE/CWE-665/CorrectRMIConnectorServerEnvironmentInitialization.java diff --git a/java/ql/src/experimental/Security/CWE/CWE-665/InsecureRmiJmxEnvironmentConfiguration.qhelp b/java/ql/src/experimental/Security/CWE/CWE-665/InsecureRmiJmxEnvironmentConfiguration.qhelp index c74d5a9d4b4..51e36dc830c 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-665/InsecureRmiJmxEnvironmentConfiguration.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-665/InsecureRmiJmxEnvironmentConfiguration.qhelp @@ -6,7 +6,7 @@

    For special use cases some applications may implement a custom service which handles JMX-RMI connections.

    -

    When creating such a custom service, a developer should pass a certain environment configuration to the JMX-RMI server initalisation, +

    When creating such a custom service, a developer should pass a certain environment configuration to the JMX-RMI server initialization, as otherwise the JMX-RMI service is susceptible to an unsafe deserialization vulnerability.

    This is because the JMX-RMI service allows attackers to supply arbitrary objects to the service authentication @@ -41,11 +41,11 @@ For this reason an initialization with a null environment is also v

    The first example shows how an JMX server is initialized securely with the JMXConnectorServerFactory.newJMXConnectorServer() call.

    - +

    The second example shows how a JMX Server is initialized securely if the RMIConnectorServer class is used.

    - +
    From 4e220330a7cf10c14b7d9d8f12489712b78195dc Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:55:02 -0400 Subject: [PATCH 100/164] spelling: interface Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Implementation Hiding/AbstractToConcreteCollection.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.qhelp b/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.qhelp index bac228017c8..2d0c1849914 100644 --- a/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.qhelp +++ b/csharp/ql/src/Bad Practices/Implementation Hiding/AbstractToConcreteCollection.qhelp @@ -18,7 +18,7 @@ more difficult to change which implementation you are using at a later date.

    -
  • C# Corner, C# Interface Based Development.
  • +
  • C# Corner, C# Interface Based Development.
  • From 22141e378e3f6bbdffb348dae2279f72b72ca67d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:57:18 -0400 Subject: [PATCH 101/164] spelling: necessary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Concurrency/DoubleCheckedLockingShared.inc.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingShared.inc.qhelp b/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingShared.inc.qhelp index 274eb6b1608..28bdebf85b1 100644 --- a/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingShared.inc.qhelp +++ b/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingShared.inc.qhelp @@ -62,7 +62,7 @@ runtime.

    The code above should be rewritten to both use volatile and finish all initialization before f is updated. Additionally, a local -variable can be used to avoid reading the field more times than neccessary. +variable can be used to avoid reading the field more times than necessary.

    From 704aba8c1c45233e74f41d40412918b0ca2a844f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:46 -0400 Subject: [PATCH 102/164] spelling: necessitates Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- python/ql/src/experimental/Security/CWE-091/Xslt.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/experimental/Security/CWE-091/Xslt.qhelp b/python/ql/src/experimental/Security/CWE-091/Xslt.qhelp index d35da4e82d4..307314f00df 100644 --- a/python/ql/src/experimental/Security/CWE-091/Xslt.qhelp +++ b/python/ql/src/experimental/Security/CWE-091/Xslt.qhelp @@ -8,7 +8,7 @@

    This vulnerability can be prevented by not allowing untrusted user input to be passed as an XSL stylesheet. - If the application logic necessiates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use. + If the application logic necessitates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use.

    From 2b75562037dcda454e3ffe0d98adc1619de2ee6d Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 11 Oct 2022 11:39:45 +0200 Subject: [PATCH 103/164] Ruby: Use `DataFlow::Configuration` in `RegExpConfiguration.qll` --- config/identical-files.json | 1 - .../TaintTrackingImpl.qll | 191 ------------------ .../TaintTrackingParameter.qll | 6 - .../regexp/internal/RegExpConfiguration.qll | 28 ++- 4 files changed, 21 insertions(+), 205 deletions(-) delete mode 100644 ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll delete mode 100644 ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingParameter.qll diff --git a/config/identical-files.json b/config/identical-files.json index c168f540f1e..832fac7741c 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -70,7 +70,6 @@ "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking3/TaintTrackingImpl.qll", "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking4/TaintTrackingImpl.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", - "ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll", "swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTrackingImpl.qll" ], "DataFlow Java/C++/C#/Python Consistency checks": [ diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll deleted file mode 100644 index bf937b6de31..00000000000 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingImpl.qll +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) taint tracking. - * This file re-exports the local (intraprocedural) taint-tracking analysis - * from `TaintTrackingParameter::Public` and adds a global analysis, mainly - * exposed through the `Configuration` class. For some languages, this file - * exists in several identical copies, allowing queries to use multiple - * `Configuration` classes that depend on each other without introducing - * mutual recursion among those configurations. - */ - -import TaintTrackingParameter::Public -private import TaintTrackingParameter::Private - -/** - * A configuration of interprocedural taint tracking analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the taint tracking library must define its own unique extension of - * this abstract class. - * - * A taint-tracking configuration is a special data flow configuration - * (`DataFlow::Configuration`) that allows for flow through nodes that do not - * necessarily preserve values but are still relevant from a taint tracking - * perspective. (For example, string concatenation, where one of the operands - * is tainted.) - * - * To create a configuration, extend this class with a subclass whose - * characteristic predicate is a unique singleton string. For example, write - * - * ```ql - * class MyAnalysisConfiguration extends TaintTracking::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isSanitizer`. - * // Optionally override `isSanitizerIn`. - * // Optionally override `isSanitizerOut`. - * // Optionally override `isSanitizerGuard`. - * // Optionally override `isAdditionalTaintStep`. - * } - * ``` - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but it is unsupported to depend on - * another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the - * overridden predicates that define sources, sinks, or additional steps. - * Instead, the dependency should go to a `TaintTracking2::Configuration` or a - * `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc. - */ -abstract class Configuration extends DataFlow::Configuration { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant taint source. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source) { none() } - - /** - * Holds if `source` is a relevant taint source with the given initial - * `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() } - - /** - * Holds if `sink` is a relevant taint sink - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink) { none() } - - /** - * Holds if `sink` is a relevant taint sink accepting `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() } - - /** Holds if the node `node` is a taint sanitizer. */ - predicate isSanitizer(DataFlow::Node node) { none() } - - final override predicate isBarrier(DataFlow::Node node) { - this.isSanitizer(node) or - defaultTaintSanitizer(node) - } - - /** - * Holds if the node `node` is a taint sanitizer when the flow state is - * `state`. - */ - predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() } - - final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { - this.isSanitizer(node, state) - } - - /** Holds if taint propagation into `node` is prohibited. */ - predicate isSanitizerIn(DataFlow::Node node) { none() } - - final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } - - /** Holds if taint propagation out of `node` is prohibited. */ - predicate isSanitizerOut(DataFlow::Node node) { none() } - - final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - - deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { - this.isSanitizerGuard(guard) - } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited - * when the flow state is `state`. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { - none() - } - - deprecated final override predicate isBarrierGuard( - DataFlow::BarrierGuard guard, DataFlow::FlowState state - ) { - this.isSanitizerGuard(guard, state) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - */ - predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } - - final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - this.isAdditionalTaintStep(node1, node2) or - defaultAdditionalTaintStep(node1, node2) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - none() - } - - final override predicate isAdditionalFlowStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - this.isAdditionalTaintStep(node1, state1, node2, state2) - } - - override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - ( - this.isSink(node) or - this.isSink(node, _) or - this.isAdditionalTaintStep(node, _) or - this.isAdditionalTaintStep(node, _, _, _) - ) and - defaultImplicitTaintRead(node, c) - } - - /** - * Holds if taint may flow from `source` to `sink` for this configuration. - */ - // overridden to provide taint-tracking specific qldoc - override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { - super.hasFlow(source, sink) - } -} diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingParameter.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingParameter.qll deleted file mode 100644 index 77949aa5ccf..00000000000 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/tainttrackingforregexp/TaintTrackingParameter.qll +++ /dev/null @@ -1,6 +0,0 @@ -import codeql.ruby.dataflow.internal.TaintTrackingPublic as Public - -module Private { - import codeql.ruby.dataflow.internal.DataFlowImplForRegExp as DataFlow - import codeql.ruby.dataflow.internal.TaintTrackingPrivate -} diff --git a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll index 310844fbbd9..3c451b15b78 100644 --- a/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll +++ b/ruby/ql/lib/codeql/ruby/regexp/internal/RegExpConfiguration.qll @@ -1,8 +1,9 @@ private import codeql.ruby.Regexp -private import codeql.ruby.ast.Literal as Ast +private import codeql.ruby.AST as Ast +private import codeql.ruby.CFG private import codeql.ruby.DataFlow private import codeql.ruby.controlflow.CfgNodes -private import codeql.ruby.dataflow.internal.tainttrackingforregexp.TaintTrackingImpl +private import codeql.ruby.dataflow.internal.DataFlowImplForRegExp private import codeql.ruby.typetracking.TypeTracker private import codeql.ruby.ApiGraphs private import codeql.ruby.dataflow.internal.DataFlowPrivate as DataFlowPrivate @@ -24,7 +25,7 @@ class RegExpConfiguration extends Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof RegExpInterpretation::Range } - override predicate isSanitizer(DataFlow::Node node) { + override predicate isBarrier(DataFlow::Node node) { exists(DataFlow::CallNode mce | mce.getMethodName() = ["match", "match?"] | // receiver of https://ruby-doc.org/core-2.4.0/String.html#method-i-match node = mce.getReceiver() and @@ -34,11 +35,24 @@ class RegExpConfiguration extends Configuration { node = mce.getArgument(0) and mce.getReceiver() = trackRegexpType() ) - or - // only include taint flow through `String` summaries - FlowSummaryImpl::Private::Steps::summaryLocalStep(_, node, false) and - not node.(DataFlowPrivate::SummaryNode).getSummarizedCallable() instanceof + } + + override predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // include taint flow through `String` summaries, + FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false) and + nodeFrom.(DataFlowPrivate::SummaryNode).getSummarizedCallable() instanceof String::SummarizedCallable + or + // string concatenations, and + exists(CfgNodes::ExprNodes::OperationCfgNode op | + op = nodeTo.asExpr() and + op.getAnOperand() = nodeFrom.asExpr() and + op.getExpr().(Ast::BinaryOperation).getOperator() = "+" + ) + or + // string interpolations + nodeFrom.asExpr() = + nodeTo.asExpr().(CfgNodes::ExprNodes::StringlikeLiteralCfgNode).getAComponent() } } From 5cfc3fe8df5b37daae06755e8f1acae664e15f41 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 11 Oct 2022 11:00:25 +0100 Subject: [PATCH 104/164] C++: Use 'DataFlowType' instead of 'Type' for the 'getType' predicate in 'PostUpdateNode'. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index b1e0779468b..28771b0bdc2 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -891,7 +891,7 @@ abstract class PostUpdateNode extends Node { */ abstract Node getPreUpdateNode(); - final override Type getType() { result = this.getPreUpdateNode().getType() } + final override DataFlowType getType() { result = this.getPreUpdateNode().getType() } } /** From 95e798565b66c651e81a92804f9c9f54818841ae Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 11 Oct 2022 12:57:51 +0100 Subject: [PATCH 105/164] C++: Expand on the comment about missing types in the database. Also rename 'getType0' to 'getTypeImpl' to avoid confusion. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 28771b0bdc2..d71fe572f03 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -605,13 +605,28 @@ private PointerType getGLValueType(Type t, int indirectionIndex) { } bindingset[isGLValue] -private DataFlowType getType0(Type t, int indirectionIndex, boolean isGLValue) { +private DataFlowType getTypeImpl(Type t, int indirectionIndex, boolean isGLValue) { if isGLValue = true then result = getGLValueType(t, indirectionIndex) or - // If the `PointerType` with the correct base type isn't in the database we cannot - // return a correct type. So instead we'll return a value that has "one indirection too little". + // Ideally, the above case would cover all glvalue cases. However, consider the case where + // the database consists only of: + // ``` + // void test() { + // int* x; + // x = nullptr; + // } + // ``` + // and we want to compute the type of `*x` in the assignment `x = nullptr`. Here, `x` is an lvalue + // of type int* (which morally is an int**). So when we call `getTypeImpl` it will be with the + // parameters: + // - t = int* + // - indirectionIndex = 1 (when we want to model the dataflow node corresponding to *x) + // - isGLValue = true + // In this case, `getTypeImpl(t, indirectionIndex, isGLValue)` should give back `int**`. In this + // case, however, `int**` does not exist in the database. So instead we return int* (which is + // wrong, but at least we have a type). not exists(getGLValueType(t, indirectionIndex)) and result = stripPointers(t, indirectionIndex - 1) else result = stripPointers(t, indirectionIndex) @@ -640,7 +655,7 @@ class IndirectOperand extends Node, TIndirectOperand { override DataFlowType getType() { exists(boolean isGLValue | if operand.isGLValue() then isGLValue = true else isGLValue = false | - result = getType0(operand.getType().getUnspecifiedType(), indirectionIndex, isGLValue) + result = getTypeImpl(operand.getType().getUnspecifiedType(), indirectionIndex, isGLValue) ) } @@ -674,7 +689,7 @@ class IndirectInstruction extends Node, TIndirectInstruction { override DataFlowType getType() { exists(boolean isGLValue | if instr.isGLValue() then isGLValue = true else isGLValue = false | - result = getType0(instr.getResultType().getUnspecifiedType(), indirectionIndex, isGLValue) + result = getTypeImpl(instr.getResultType().getUnspecifiedType(), indirectionIndex, isGLValue) ) } From 2e8f46ddd991997599c25118736bb6f3cda5b3cc Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 10 Oct 2022 13:56:48 +0200 Subject: [PATCH 106/164] Type tracking: Split up `levelStep` into `levelStepNoCall` and `levelStepCall` To reduce non-linear recursion during call graph construction. --- .../codeql/ruby/typetracking/TypeTracker.qll | 5 ++- .../ruby/typetracking/TypeTrackerSpecific.qll | 31 ++++++++++--------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll index 1ada143a475..52807799c2c 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll @@ -186,7 +186,7 @@ private module Cached { jumpStep(nodeFrom, nodeTo) and summary = JumpStep() or - levelStep(nodeFrom, nodeTo) and + levelStepNoCall(nodeFrom, nodeTo) and summary = LevelStep() or exists(TypeTrackerContent content | @@ -216,6 +216,9 @@ private module Cached { or returnStep(nodeFrom, nodeTo) and summary = ReturnStep() + or + levelStepCall(nodeFrom, nodeTo) and + summary = LevelStep() } } diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll index ca396eb7688..b916201053e 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll @@ -76,20 +76,28 @@ predicate simpleLocalFlowStep = DataFlowPrivate::localFlowStepTypeTracker/2; */ predicate jumpStep = DataFlowPrivate::jumpStep/2; -/** - * Holds if there is a summarized local flow step from `nodeFrom` to `nodeTo`, - * because there is direct flow from a parameter to a return. That is, summarized - * steps are not applied recursively. - */ +/** Holds if there is direct flow from `param` to a return. */ pragma[nomagic] -private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) { - exists(DataFlowPublic::ParameterNode param, DataFlowPrivate::ReturningNode returnNode | +private predicate flowThrough(DataFlowPublic::ParameterNode param) { + exists(DataFlowPrivate::ReturningNode returnNode | DataFlowPrivate::LocalFlow::getParameterDefNode(param.getParameter()) .(TypeTrackingNode) - .flowsTo(returnNode) and + .flowsTo(returnNode) + ) +} + +/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */ +pragma[nomagic] +predicate levelStepCall(Node nodeFrom, Node nodeTo) { + exists(DataFlowPublic::ParameterNode param | + flowThrough(param) and callStep(nodeTo.asExpr(), nodeFrom, param) ) - or +} + +/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */ +pragma[nomagic] +predicate levelStepNoCall(Node nodeFrom, Node nodeTo) { exists( SummarizedCallable callable, DataFlowPublic::CallNode call, SummaryComponentStack input, SummaryComponentStack output @@ -99,11 +107,6 @@ private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) { nodeFrom = evaluateSummaryComponentStackLocal(callable, call, input) and nodeTo = evaluateSummaryComponentStackLocal(callable, call, output) ) -} - -/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */ -predicate levelStep(Node nodeFrom, Node nodeTo) { - summarizedLocalStep(nodeFrom, nodeTo) or localFieldStep(nodeFrom, nodeTo) } From f1c44f72b5010af8d0c782b19bebb66075eaa880 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 10 Oct 2022 13:58:31 +0200 Subject: [PATCH 107/164] Python: Sync on `TypeTracker.qll` changes --- .../semmle/python/dataflow/new/internal/TypeTracker.qll | 5 ++++- .../python/dataflow/new/internal/TypeTrackerSpecific.qll | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll index 1ada143a475..52807799c2c 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll @@ -186,7 +186,7 @@ private module Cached { jumpStep(nodeFrom, nodeTo) and summary = JumpStep() or - levelStep(nodeFrom, nodeTo) and + levelStepNoCall(nodeFrom, nodeTo) and summary = LevelStep() or exists(TypeTrackerContent content | @@ -216,6 +216,9 @@ private module Cached { or returnStep(nodeFrom, nodeTo) and summary = ReturnStep() + or + levelStepCall(nodeFrom, nodeTo) and + summary = LevelStep() } } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll index 05ad3cbdd7d..fc16da4b0e2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll @@ -45,8 +45,11 @@ predicate simpleLocalFlowStep = DataFlowPrivate::simpleLocalFlowStepForTypetrack predicate jumpStep = DataFlowPrivate::jumpStepSharedWithTypeTracker/2; -/** Holds if there is a level step from `pred` to `succ`. */ -predicate levelStep(Node pred, Node succ) { none() } +/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */ +predicate levelStepCall(Node pred, Node succ) { none() } + +/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */ +predicate levelStepNoCall(Node nodeFrom, Node nodeTo) { none() } /** * Gets the name of a possible piece of content. For Python, this is currently only attribute names, From 7171fd1bb2888ec1cbabe74f67d2626ad6ad7b05 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 11 Oct 2022 09:12:09 +0200 Subject: [PATCH 108/164] Update python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll Co-authored-by: Taus --- .../semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll index fc16da4b0e2..690216089e9 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackerSpecific.qll @@ -46,7 +46,7 @@ predicate simpleLocalFlowStep = DataFlowPrivate::simpleLocalFlowStepForTypetrack predicate jumpStep = DataFlowPrivate::jumpStepSharedWithTypeTracker/2; /** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */ -predicate levelStepCall(Node pred, Node succ) { none() } +predicate levelStepCall(Node nodeFrom, Node nodeTo) { none() } /** Holds if there is a level step from `nodeFrom` to `nodeTo`, which does not depend on the call graph. */ predicate levelStepNoCall(Node nodeFrom, Node nodeTo) { none() } From a826dbbdeeb8734dfbedbad1d39d8f555d3103ba Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Tue, 11 Oct 2022 13:58:55 +0200 Subject: [PATCH 109/164] fix capitalization in stack-trace-exposure --- python/ql/src/Security/CWE-209/StackTraceExposure.ql | 2 +- .../StackTraceExposure.expected | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ql/src/Security/CWE-209/StackTraceExposure.ql b/python/ql/src/Security/CWE-209/StackTraceExposure.ql index e817edc6b09..7b8cf74c597 100644 --- a/python/ql/src/Security/CWE-209/StackTraceExposure.ql +++ b/python/ql/src/Security/CWE-209/StackTraceExposure.ql @@ -21,4 +21,4 @@ from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select sink.getNode(), source, sink, "$@ flows to this location and may be exposed to an external user.", source.getNode(), - "stack trace information" + "Stack trace information" diff --git a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected index eb0e1efe6e0..07b208caaac 100644 --- a/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected +++ b/python/ql/test/query-tests/Security/CWE-209-StackTraceExposure/StackTraceExposure.expected @@ -22,8 +22,8 @@ nodes subpaths | test.py:50:29:50:31 | ControlFlowNode for err | test.py:52:18:52:20 | ControlFlowNode for msg | test.py:53:12:53:27 | ControlFlowNode for BinaryExpr | test.py:50:16:50:32 | ControlFlowNode for format_error() | #select -| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | $@ flows to this location and may be exposed to an external user. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | stack trace information | -| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | $@ flows to this location and may be exposed to an external user. | test.py:23:25:23:25 | SSA variable e | stack trace information | -| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | $@ flows to this location and may be exposed to an external user. | test.py:31:25:31:25 | SSA variable e | stack trace information | -| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | $@ flows to this location and may be exposed to an external user. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | stack trace information | -| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | $@ flows to this location and may be exposed to an external user. | test.py:65:25:65:25 | SSA variable e | stack trace information | +| test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | test.py:16:16:16:37 | ControlFlowNode for Attribute() | $@ flows to this location and may be exposed to an external user. | test.py:16:16:16:37 | ControlFlowNode for Attribute() | Stack trace information | +| test.py:24:16:24:16 | ControlFlowNode for e | test.py:23:25:23:25 | SSA variable e | test.py:24:16:24:16 | ControlFlowNode for e | $@ flows to this location and may be exposed to an external user. | test.py:23:25:23:25 | SSA variable e | Stack trace information | +| test.py:32:16:32:30 | ControlFlowNode for Attribute | test.py:31:25:31:25 | SSA variable e | test.py:32:16:32:30 | ControlFlowNode for Attribute | $@ flows to this location and may be exposed to an external user. | test.py:31:25:31:25 | SSA variable e | Stack trace information | +| test.py:50:16:50:32 | ControlFlowNode for format_error() | test.py:49:15:49:36 | ControlFlowNode for Attribute() | test.py:50:16:50:32 | ControlFlowNode for format_error() | $@ flows to this location and may be exposed to an external user. | test.py:49:15:49:36 | ControlFlowNode for Attribute() | Stack trace information | +| test.py:66:24:66:40 | ControlFlowNode for Dict | test.py:65:25:65:25 | SSA variable e | test.py:66:24:66:40 | ControlFlowNode for Dict | $@ flows to this location and may be exposed to an external user. | test.py:65:25:65:25 | SSA variable e | Stack trace information | From ac30cfa5c1db9bc6b3ab39ab1115a3ca77c8ce4f Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 11 Oct 2022 14:05:27 +0200 Subject: [PATCH 110/164] Python: Apply suggestions from code review --- .../src/change-notes/2022-10-10-pep249-executemany-modeling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md b/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md index 556520df64f..42037942ee7 100644 --- a/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md +++ b/python/ql/src/change-notes/2022-10-10-pep249-executemany-modeling.md @@ -1,4 +1,4 @@ --- category: minorAnalysis --- -* Added model of `executemany` calls on PEP-249 compliant Database APIs, resulting in additional sinks for `py/sql-injection`. +* Added model of `executemany` calls on PEP-249 compliant database APIs, resulting in additional sinks for `py/sql-injection`. From 0892a5795d92a564666c3c27d6535a5560005400 Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 11 Oct 2022 15:33:45 +0200 Subject: [PATCH 111/164] Add taint step for subscript expressions --- .../dataflow/internal/TaintTrackingPrivate.qll | 6 ++++++ .../dataflow/taint/LocalTaint.expected | 2 ++ .../library-tests/dataflow/taint/Taint.expected | 8 ++++++++ .../library-tests/dataflow/taint/subscript.swift | 15 +++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 swift/ql/test/library-tests/dataflow/taint/subscript.swift diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll b/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll index c2fccb5a3f6..e24bf359945 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/TaintTrackingPrivate.qll @@ -49,6 +49,12 @@ private module Cached { ae.getType().getName() = "String" ) or + // flow through a subscript access + exists(SubscriptExpr se | + se.getBase() = nodeFrom.asExpr() and + se = nodeTo.asExpr() + ) + or // flow through a flow summary (extension of `SummaryModelCsv`) FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false) } diff --git a/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected b/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected index 504e4ca636b..e511009557b 100644 --- a/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/LocalTaint.expected @@ -123,3 +123,5 @@ | string.swift:39:13:39:19 | ... .+(_:_:) ... | string.swift:39:13:39:29 | ... .+(_:_:) ... | | string.swift:39:19:39:19 | tainted | string.swift:39:13:39:19 | ... .+(_:_:) ... | | string.swift:39:29:39:29 | < | string.swift:39:13:39:29 | ... .+(_:_:) ... | +| subscript.swift:13:10:13:17 | call to source() | subscript.swift:13:10:13:20 | ...[...] | +| subscript.swift:14:10:14:18 | call to source2() | subscript.swift:14:10:14:21 | ...[...] | diff --git a/swift/ql/test/library-tests/dataflow/taint/Taint.expected b/swift/ql/test/library-tests/dataflow/taint/Taint.expected index 5670d7ddd70..43086d32d08 100644 --- a/swift/ql/test/library-tests/dataflow/taint/Taint.expected +++ b/swift/ql/test/library-tests/dataflow/taint/Taint.expected @@ -10,6 +10,8 @@ edges | string.swift:28:17:28:25 | call to source2() : | string.swift:35:13:35:23 | ... .+(_:_:) ... | | string.swift:28:17:28:25 | call to source2() : | string.swift:36:13:36:23 | ... .+(_:_:) ... | | string.swift:28:17:28:25 | call to source2() : | string.swift:39:13:39:29 | ... .+(_:_:) ... | +| subscript.swift:13:10:13:17 | call to source() : | subscript.swift:13:10:13:20 | ...[...] | +| subscript.swift:14:10:14:18 | call to source2() : | subscript.swift:14:10:14:21 | ...[...] | | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | | try.swift:15:17:15:24 | call to source() : | try.swift:15:12:15:24 | try! ... | | try.swift:18:18:18:25 | call to source() : | try.swift:18:12:18:27 | ...! | @@ -65,6 +67,10 @@ nodes | string.swift:35:13:35:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | | string.swift:36:13:36:23 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | | string.swift:39:13:39:29 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... | +| subscript.swift:13:10:13:17 | call to source() : | semmle.label | call to source() : | +| subscript.swift:13:10:13:20 | ...[...] | semmle.label | ...[...] | +| subscript.swift:14:10:14:18 | call to source2() : | semmle.label | call to source2() : | +| subscript.swift:14:10:14:21 | ...[...] | semmle.label | ...[...] | | try.swift:9:13:9:24 | try ... | semmle.label | try ... | | try.swift:9:17:9:24 | call to source() : | semmle.label | call to source() : | | try.swift:15:12:15:24 | try! ... | semmle.label | try! ... | @@ -115,6 +121,8 @@ subpaths | string.swift:35:13:35:23 | ... .+(_:_:) ... | string.swift:28:17:28:25 | call to source2() : | string.swift:35:13:35:23 | ... .+(_:_:) ... | result | | string.swift:36:13:36:23 | ... .+(_:_:) ... | string.swift:28:17:28:25 | call to source2() : | string.swift:36:13:36:23 | ... .+(_:_:) ... | result | | string.swift:39:13:39:29 | ... .+(_:_:) ... | string.swift:28:17:28:25 | call to source2() : | string.swift:39:13:39:29 | ... .+(_:_:) ... | result | +| subscript.swift:13:10:13:20 | ...[...] | subscript.swift:13:10:13:17 | call to source() : | subscript.swift:13:10:13:20 | ...[...] | result | +| subscript.swift:14:10:14:21 | ...[...] | subscript.swift:14:10:14:18 | call to source2() : | subscript.swift:14:10:14:21 | ...[...] | result | | try.swift:9:13:9:24 | try ... | try.swift:9:17:9:24 | call to source() : | try.swift:9:13:9:24 | try ... | result | | try.swift:15:12:15:24 | try! ... | try.swift:15:17:15:24 | call to source() : | try.swift:15:12:15:24 | try! ... | result | | try.swift:18:12:18:27 | ...! | try.swift:18:18:18:25 | call to source() : | try.swift:18:12:18:27 | ...! | result | diff --git a/swift/ql/test/library-tests/dataflow/taint/subscript.swift b/swift/ql/test/library-tests/dataflow/taint/subscript.swift new file mode 100644 index 00000000000..d41b755a978 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/taint/subscript.swift @@ -0,0 +1,15 @@ +class SubscriptTest { + subscript(index: Int) -> String { + get { return "" } + set(newValue) {} + } +} + +func source() -> Array { return [""] } +func source2() -> SubscriptTest { return SubscriptTest() } +func sink(arg: String) {} + +func test() { + sink(source()[0]) // $ tainted=13 + sink(source2()[0]) // $ tainted=14 +} From 9b2cc6c318be6e0978495e17f47095650d527a9a Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Tue, 11 Oct 2022 15:48:42 +0200 Subject: [PATCH 112/164] Kotlin/Java: Exclude generated code from `java/missing-override-annotation` --- .../ql/src/Advisory/Declarations/MissingOverrideAnnotation.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/src/Advisory/Declarations/MissingOverrideAnnotation.ql b/java/ql/src/Advisory/Declarations/MissingOverrideAnnotation.ql index 1ad81badd22..dc73fb8fcdb 100644 --- a/java/ql/src/Advisory/Declarations/MissingOverrideAnnotation.ql +++ b/java/ql/src/Advisory/Declarations/MissingOverrideAnnotation.ql @@ -23,6 +23,8 @@ where m.overrides(overridden) and not m.hasModifier("override") and not m.isOverrideAnnotated() and - not exists(FunctionalExpr mref | mref.asMethod() = m) + not exists(FunctionalExpr mref | mref.asMethod() = m) and + // Ignore generated constructs, such as functions extracted from Kotlin code: + not m.isCompilerGenerated() select m, "This method overrides $@; it is advisable to add an Override annotation.", overridden, overridden.getDeclaringType() + "." + overridden.getName() From 078c3e9d284054d5293fb0bdba04ddc2b140d2a0 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Tue, 11 Oct 2022 15:22:42 +0100 Subject: [PATCH 113/164] Ruby: create top-level module for ActionMailer --- .../codeql/ruby/frameworks/ActionMailer.qll | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll index 13be621683b..af183333d3d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionMailer.qll @@ -7,42 +7,47 @@ private import codeql.ruby.ApiGraphs private import codeql.ruby.frameworks.internal.Rails /** - * A `ClassDeclaration` for a class that extends `ActionMailer::Base`. - * For example, - * - * ```rb - * class FooMailer < ActionMailer::Base - * ... - * end - * ``` + * Provides modeling for the `ActionMailer` library. */ -class ActionMailerMailerClass extends ClassDeclaration { - ActionMailerMailerClass() { - this.getSuperclassExpr() = - [ - API::getTopLevelMember("ActionMailer").getMember("Base"), - // In Rails applications `ApplicationMailer` typically extends - // `ActionMailer::Base`, but we treat it separately in case the - // `ApplicationMailer` definition is not in the database. - API::getTopLevelMember("ApplicationMailer") - ].getASubclass().getAValueReachableFromSource().asExpr().getExpr() - } -} - -/** A method call with a `self` receiver from within a mailer class */ -private class ActionMailerContextCall extends MethodCall { - private ActionMailerMailerClass mailerClass; - - ActionMailerContextCall() { - this.getReceiver() instanceof SelfVariableAccess and - this.getEnclosingModule() = mailerClass +module ActionMailer { + /** + * A `ClassDeclaration` for a class that extends `ActionMailer::Base`. + * For example, + * + * ```rb + * class FooMailer < ActionMailer::Base + * ... + * end + * ``` + */ + class MailerClass extends ClassDeclaration { + MailerClass() { + this.getSuperclassExpr() = + [ + API::getTopLevelMember("ActionMailer").getMember("Base"), + // In Rails applications `ApplicationMailer` typically extends + // `ActionMailer::Base`, but we treat it separately in case the + // `ApplicationMailer` definition is not in the database. + API::getTopLevelMember("ApplicationMailer") + ].getASubclass().getAValueReachableFromSource().asExpr().getExpr() + } } - /** Gets the mailer class containing this method. */ - ActionMailerMailerClass getMailerClass() { result = mailerClass } -} + /** A method call with a `self` receiver from within a mailer class */ + private class ContextCall extends MethodCall { + private MailerClass mailerClass; -/** A call to `params` from within a mailer. */ -class ActionMailerParamsCall extends ActionMailerContextCall, ParamsCallImpl { - ActionMailerParamsCall() { this.getMethodName() = "params" } + ContextCall() { + this.getReceiver() instanceof SelfVariableAccess and + this.getEnclosingModule() = mailerClass + } + + /** Gets the mailer class containing this method. */ + MailerClass getMailerClass() { result = mailerClass } + } + + /** A call to `params` from within a mailer. */ + class ParamsCall extends ContextCall, ParamsCallImpl { + ParamsCall() { this.getMethodName() = "params" } + } } From a3f096a6bc714ca1349452fc8ebdf0603e862d67 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 11 Oct 2022 15:44:00 +0100 Subject: [PATCH 114/164] Ruby: rb/unsafe-deserialization test realignment --- .../UnsafeDeserialization.expected | 112 +++++++++--------- .../UnsafeDeserialization.rb | 1 + 2 files changed, 57 insertions(+), 56 deletions(-) diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected index f6d213c9a9b..dd8b29e8dd0 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected +++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected @@ -1,61 +1,61 @@ edges -| UnsafeDeserialization.rb:9:39:9:44 | call to params : | UnsafeDeserialization.rb:9:39:9:50 | ...[...] : | -| UnsafeDeserialization.rb:9:39:9:50 | ...[...] : | UnsafeDeserialization.rb:10:27:10:41 | serialized_data | -| UnsafeDeserialization.rb:15:39:15:44 | call to params : | UnsafeDeserialization.rb:15:39:15:50 | ...[...] : | -| UnsafeDeserialization.rb:15:39:15:50 | ...[...] : | UnsafeDeserialization.rb:16:30:16:44 | serialized_data | -| UnsafeDeserialization.rb:21:17:21:22 | call to params : | UnsafeDeserialization.rb:21:17:21:28 | ...[...] : | -| UnsafeDeserialization.rb:21:17:21:28 | ...[...] : | UnsafeDeserialization.rb:22:24:22:32 | json_data | -| UnsafeDeserialization.rb:27:17:27:22 | call to params : | UnsafeDeserialization.rb:27:17:27:28 | ...[...] : | -| UnsafeDeserialization.rb:27:17:27:28 | ...[...] : | UnsafeDeserialization.rb:28:27:28:35 | json_data | -| UnsafeDeserialization.rb:39:17:39:22 | call to params : | UnsafeDeserialization.rb:39:17:39:28 | ...[...] : | -| UnsafeDeserialization.rb:39:17:39:28 | ...[...] : | UnsafeDeserialization.rb:40:24:40:32 | yaml_data | -| UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | -| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | UnsafeDeserialization.rb:52:22:52:30 | json_data | -| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | UnsafeDeserialization.rb:53:22:53:30 | json_data | -| UnsafeDeserialization.rb:58:17:58:22 | call to params : | UnsafeDeserialization.rb:58:17:58:28 | ...[...] : | -| UnsafeDeserialization.rb:58:17:58:28 | ...[...] : | UnsafeDeserialization.rb:68:23:68:31 | json_data | -| UnsafeDeserialization.rb:80:11:80:16 | call to params : | UnsafeDeserialization.rb:80:11:80:22 | ...[...] : | -| UnsafeDeserialization.rb:80:11:80:22 | ...[...] : | UnsafeDeserialization.rb:81:34:81:36 | xml | -| UnsafeDeserialization.rb:86:17:86:22 | call to params : | UnsafeDeserialization.rb:86:17:86:28 | ...[...] : | -| UnsafeDeserialization.rb:86:17:86:28 | ...[...] : | UnsafeDeserialization.rb:87:25:87:33 | yaml_data | +| UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | +| UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | +| UnsafeDeserialization.rb:16:39:16:44 | call to params : | UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | +| UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | +| UnsafeDeserialization.rb:22:17:22:22 | call to params : | UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | +| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | UnsafeDeserialization.rb:23:24:23:32 | json_data | +| UnsafeDeserialization.rb:28:17:28:22 | call to params : | UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | +| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | UnsafeDeserialization.rb:29:27:29:35 | json_data | +| UnsafeDeserialization.rb:40:17:40:22 | call to params : | UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | +| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | +| UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | +| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:53:22:53:30 | json_data | +| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:54:22:54:30 | json_data | +| UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | +| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | UnsafeDeserialization.rb:69:23:69:31 | json_data | +| UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | +| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | UnsafeDeserialization.rb:82:34:82:36 | xml | +| UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | +| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | nodes -| UnsafeDeserialization.rb:9:39:9:44 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:9:39:9:50 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:10:27:10:41 | serialized_data | semmle.label | serialized_data | -| UnsafeDeserialization.rb:15:39:15:44 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:15:39:15:50 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:16:30:16:44 | serialized_data | semmle.label | serialized_data | -| UnsafeDeserialization.rb:21:17:21:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:21:17:21:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:22:24:22:32 | json_data | semmle.label | json_data | -| UnsafeDeserialization.rb:27:17:27:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:27:17:27:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:28:27:28:35 | json_data | semmle.label | json_data | -| UnsafeDeserialization.rb:39:17:39:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:39:17:39:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:40:24:40:32 | yaml_data | semmle.label | yaml_data | -| UnsafeDeserialization.rb:51:17:51:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:52:22:52:30 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:10:39:10:44 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:11:27:11:41 | serialized_data | semmle.label | serialized_data | +| UnsafeDeserialization.rb:16:39:16:44 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:17:30:17:44 | serialized_data | semmle.label | serialized_data | +| UnsafeDeserialization.rb:22:17:22:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:23:24:23:32 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:28:17:28:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:29:27:29:35 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:40:17:40:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:41:24:41:32 | yaml_data | semmle.label | yaml_data | +| UnsafeDeserialization.rb:52:17:52:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:53:22:53:30 | json_data | semmle.label | json_data | -| UnsafeDeserialization.rb:58:17:58:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:58:17:58:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:68:23:68:31 | json_data | semmle.label | json_data | -| UnsafeDeserialization.rb:80:11:80:16 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:80:11:80:22 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:81:34:81:36 | xml | semmle.label | xml | -| UnsafeDeserialization.rb:86:17:86:22 | call to params : | semmle.label | call to params : | -| UnsafeDeserialization.rb:86:17:86:28 | ...[...] : | semmle.label | ...[...] : | -| UnsafeDeserialization.rb:87:25:87:33 | yaml_data | semmle.label | yaml_data | +| UnsafeDeserialization.rb:54:22:54:30 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:59:17:59:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:69:23:69:31 | json_data | semmle.label | json_data | +| UnsafeDeserialization.rb:81:11:81:16 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:82:34:82:36 | xml | semmle.label | xml | +| UnsafeDeserialization.rb:87:17:87:22 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | semmle.label | ...[...] : | +| UnsafeDeserialization.rb:88:25:88:33 | yaml_data | semmle.label | yaml_data | subpaths #select -| UnsafeDeserialization.rb:10:27:10:41 | serialized_data | UnsafeDeserialization.rb:9:39:9:44 | call to params : | UnsafeDeserialization.rb:10:27:10:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:9:39:9:44 | call to params | user-provided value | -| UnsafeDeserialization.rb:16:30:16:44 | serialized_data | UnsafeDeserialization.rb:15:39:15:44 | call to params : | UnsafeDeserialization.rb:16:30:16:44 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:15:39:15:44 | call to params | user-provided value | -| UnsafeDeserialization.rb:22:24:22:32 | json_data | UnsafeDeserialization.rb:21:17:21:22 | call to params : | UnsafeDeserialization.rb:22:24:22:32 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:21:17:21:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:28:27:28:35 | json_data | UnsafeDeserialization.rb:27:17:27:22 | call to params : | UnsafeDeserialization.rb:28:27:28:35 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:27:17:27:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:40:24:40:32 | yaml_data | UnsafeDeserialization.rb:39:17:39:22 | call to params : | UnsafeDeserialization.rb:40:24:40:32 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:39:17:39:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:52:22:52:30 | json_data | UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:52:22:52:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:51:17:51:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:53:22:53:30 | json_data | UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:53:22:53:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:51:17:51:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:68:23:68:31 | json_data | UnsafeDeserialization.rb:58:17:58:22 | call to params : | UnsafeDeserialization.rb:68:23:68:31 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:58:17:58:22 | call to params | user-provided value | -| UnsafeDeserialization.rb:81:34:81:36 | xml | UnsafeDeserialization.rb:80:11:80:16 | call to params : | UnsafeDeserialization.rb:81:34:81:36 | xml | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:80:11:80:16 | call to params | user-provided value | -| UnsafeDeserialization.rb:87:25:87:33 | yaml_data | UnsafeDeserialization.rb:86:17:86:22 | call to params : | UnsafeDeserialization.rb:87:25:87:33 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:86:17:86:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:11:27:11:41 | serialized_data | UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:10:39:10:44 | call to params | user-provided value | +| UnsafeDeserialization.rb:17:30:17:44 | serialized_data | UnsafeDeserialization.rb:16:39:16:44 | call to params : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:16:39:16:44 | call to params | user-provided value | +| UnsafeDeserialization.rb:23:24:23:32 | json_data | UnsafeDeserialization.rb:22:17:22:22 | call to params : | UnsafeDeserialization.rb:23:24:23:32 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:22:17:22:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:29:27:29:35 | json_data | UnsafeDeserialization.rb:28:17:28:22 | call to params : | UnsafeDeserialization.rb:29:27:29:35 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:28:17:28:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:41:24:41:32 | yaml_data | UnsafeDeserialization.rb:40:17:40:22 | call to params : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:40:17:40:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:53:22:53:30 | json_data | UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:53:22:53:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:52:17:52:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:54:22:54:30 | json_data | UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:54:22:54:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:52:17:52:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:69:23:69:31 | json_data | UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:69:23:69:31 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:59:17:59:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:82:34:82:36 | xml | UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:82:34:82:36 | xml | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:81:11:81:16 | call to params | user-provided value | +| UnsafeDeserialization.rb:88:25:88:33 | yaml_data | UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:87:17:87:22 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb index 707c098ff89..c5432596d01 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb +++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb @@ -1,3 +1,4 @@ +require "active_job" require "base64" require "json" require "oj" From 3d08a2954d0dd15135c3d8edfd1889536e8a6a0c Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 11 Oct 2022 15:45:10 +0100 Subject: [PATCH 115/164] Ruby: add rb/unsafe-deserialization sinks for const_get args --- .../UnsafeDeserializationCustomizations.qll | 25 +++++++++++++++++++ .../UnsafeDeserialization.expected | 8 ++++++ .../UnsafeDeserialization.rb | 12 +++++++++ 3 files changed, 45 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll index 517ba6fa700..da759ea28e9 100644 --- a/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll +++ b/ruby/ql/lib/codeql/ruby/security/UnsafeDeserializationCustomizations.qll @@ -8,6 +8,8 @@ private import codeql.ruby.ApiGraphs private import codeql.ruby.CFG private import codeql.ruby.DataFlow private import codeql.ruby.dataflow.RemoteFlowSources +private import codeql.ruby.frameworks.ActiveJob +private import codeql.ruby.frameworks.core.Module module UnsafeDeserialization { /** @@ -199,4 +201,27 @@ module UnsafeDeserialization { toNode = callNode ) } + + /** + * A argument in a call to `Module.const_get`, considered as a sink for unsafe + * deserialization. + * + * Calls to `Module.const_get` can return arbitrary classes which can then be + * instantiated. + */ + class ConstGetCallArgument extends Sink { + ConstGetCallArgument() { this = any(Module::ModuleConstGetCallCodeExecution c).getCode() } + } + + /** + * A argument in a call to `ActiveJob::Serializers.deserialize`, considered as + * a sink for unsafe deserialization. + * + * This is roughly equivalent to a call to `Module.const_get`. + */ + class ActiveJobSerializersDeserializeArgument extends Sink { + ActiveJobSerializersDeserializeArgument() { + this = any(ActiveJob::Serializers::DeserializeCall c).getCode() + } + } } diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected index dd8b29e8dd0..61e9d96b3e4 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected +++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.expected @@ -18,6 +18,8 @@ edges | UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | UnsafeDeserialization.rb:82:34:82:36 | xml | | UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | +| UnsafeDeserialization.rb:93:30:93:35 | call to params : | UnsafeDeserialization.rb:93:30:93:43 | ...[...] | +| UnsafeDeserialization.rb:99:48:99:53 | call to params : | UnsafeDeserialization.rb:99:48:99:61 | ...[...] | nodes | UnsafeDeserialization.rb:10:39:10:44 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | semmle.label | ...[...] : | @@ -47,6 +49,10 @@ nodes | UnsafeDeserialization.rb:87:17:87:22 | call to params : | semmle.label | call to params : | | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | semmle.label | ...[...] : | | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | semmle.label | yaml_data | +| UnsafeDeserialization.rb:93:30:93:35 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:93:30:93:43 | ...[...] | semmle.label | ...[...] | +| UnsafeDeserialization.rb:99:48:99:53 | call to params : | semmle.label | call to params : | +| UnsafeDeserialization.rb:99:48:99:61 | ...[...] | semmle.label | ...[...] | subpaths #select | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:10:39:10:44 | call to params | user-provided value | @@ -59,3 +65,5 @@ subpaths | UnsafeDeserialization.rb:69:23:69:31 | json_data | UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:69:23:69:31 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:59:17:59:22 | call to params | user-provided value | | UnsafeDeserialization.rb:82:34:82:36 | xml | UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:82:34:82:36 | xml | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:81:11:81:16 | call to params | user-provided value | | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:87:17:87:22 | call to params | user-provided value | +| UnsafeDeserialization.rb:93:30:93:43 | ...[...] | UnsafeDeserialization.rb:93:30:93:35 | call to params : | UnsafeDeserialization.rb:93:30:93:43 | ...[...] | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:93:30:93:35 | call to params | user-provided value | +| UnsafeDeserialization.rb:99:48:99:61 | ...[...] | UnsafeDeserialization.rb:99:48:99:53 | call to params : | UnsafeDeserialization.rb:99:48:99:61 | ...[...] | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:99:48:99:53 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb index c5432596d01..49816cd3592 100644 --- a/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb +++ b/ruby/ql/test/query-tests/security/cwe-502/unsafe-deserialization/UnsafeDeserialization.rb @@ -87,4 +87,16 @@ class UsersController < ActionController::Base yaml_data = params[:key] object = Psych.load yaml_data end + + # BAD - user input determines which class is instantiated + def route12 + klass = Module.const_get(params[:class]) + object = klass.new + end + + # BAD - user input determines which class is instantiated + def route13 + klass = ActiveJob::Serializers.deserialize(params[:class]) + object = klass.new + end end From 1f0a48de287e200eb30fd72facd2641ac8f3ee94 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Tue, 11 Oct 2022 10:59:00 -0400 Subject: [PATCH 116/164] Documentation suggestion Co-authored-by: Felicity Chapman --- .../ContentProviderIncompletePermissions.qhelp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp index eeb9024dea6..a867dc70314 100644 --- a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp +++ b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp @@ -3,14 +3,12 @@ "qhelp.dtd"> -

    In the Android manifest file, an application's provider elements - define the permissions necessary to access a resource using that provider. - Permissions are specified with +

    The Android manifest file contains provider elements that you should use to specify the explicit permissions an application requires to access a resource using that provider. + You specify the permissions using the android:readPermission, android:writePermission, - or android:permission attributes. If an application only - specifies the android:readPermission - or android:writePermission attribute, no permissions will be - required to do other operations. + or android:permission attributes. +If you do not specify the permission required to perform an operation, the application will implicitly have access to perform that operation. + For example, if you specify only android:readPermission, the application must have explicit permission to read data, but requires no permission to write data.

    From 80cc3fc518bb9a342ee8d830a9d0ae443489838b Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 11 Oct 2022 11:02:37 -0400 Subject: [PATCH 117/164] Reword first sentence of documentation --- .../CWE/CWE-926/ContentProviderIncompletePermissions.qhelp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp index a867dc70314..5c044d84b5b 100644 --- a/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp +++ b/java/ql/src/Security/CWE/CWE-926/ContentProviderIncompletePermissions.qhelp @@ -3,7 +3,11 @@ "qhelp.dtd"> -

    The Android manifest file contains provider elements that you should use to specify the explicit permissions an application requires to access a resource using that provider. +

    The Android manifest file specifies the content providers for the application +using provider elements. The provider element +specifies the explicit permissions an application requires in order to access a +resource using that provider. + You specify the permissions using the android:readPermission, android:writePermission, or android:permission attributes. From f88aaf37a54719eba521b50196d8de89ce8d1cde Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 11 Oct 2022 16:08:06 +0100 Subject: [PATCH 118/164] C++: Add 'UninitializedNode' to IR dataflow. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index d71fe572f03..3c7368ff1a0 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -231,6 +231,12 @@ class Node extends TIRDataFlowNode { /** Gets the positional parameter corresponding to this node, if any. */ Parameter asParameter() { result = asParameter(0) } + /** + * Gets the uninitialized local variable corresponding to this node, if + * any. + */ + LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } + /** * Gets the positional parameter corresponding to the node that represents * the value of the parameter after `index` number of loads, if any. For @@ -666,6 +672,25 @@ class IndirectOperand extends Node, TIndirectOperand { } } +/** + * The value of an uninitialized local variable, viewed as a node in a data + * flow graph. + */ +class UninitializedNode extends Node { + LocalVariable v; + + UninitializedNode() { + exists(Ssa::Def def | + def.getDefiningInstruction() instanceof UninitializedInstruction and + Ssa::nodeToDefOrUse(this, def) and + v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() + ) + } + + /** Gets the uninitialized local variable corresponding to this node. */ + LocalVariable getLocalVariable() { result = v } +} + /** * INTERNAL: Do not use. * From f4d43deec44593e2ad9742c43421949520f6872e Mon Sep 17 00:00:00 2001 From: Tony Torralba Date: Tue, 11 Oct 2022 15:22:28 +0200 Subject: [PATCH 119/164] Add taint sources for custom URL scheme URLs --- .../codeql/swift/dataflow/ExternalFlow.qll | 1 + .../StandardLibrary/CustomUrlSchemes.qll | 13 ++++++++++ .../dataflow/flowsources/FlowSources.expected | 3 +++ .../flowsources/customurlschemes.swift | 26 +++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll create mode 100644 swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index 32e4cd8f5ff..52d102d21e0 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -78,6 +78,7 @@ private import internal.FlowSummaryImplSpecific * ensuring that they are visible to the taint tracking / data flow library. */ private module Frameworks { + private import codeql.swift.frameworks.StandardLibrary.CustomUrlSchemes private import codeql.swift.frameworks.StandardLibrary.String private import codeql.swift.frameworks.StandardLibrary.Url private import codeql.swift.frameworks.StandardLibrary.UrlSession diff --git a/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll new file mode 100644 index 00000000000..78b9486a1a0 --- /dev/null +++ b/swift/ql/lib/codeql/swift/frameworks/StandardLibrary/CustomUrlSchemes.qll @@ -0,0 +1,13 @@ +import swift +private import codeql.swift.dataflow.ExternalFlow + +private class UrlRemoteFlowSource extends SourceModelCsv { + override predicate row(string row) { + row = + [ + ";UIApplicationDelegate;true;application(_:open:options:);;;Parameter[1];remote", + ";UIApplicationDelegate;true;application(_:handleOpen:);;;Parameter[1];remote", + ";UIApplicationDelegate;true;application(_:open:sourceApplication:annotation:);;;Parameter[1];remote" + ] + } +} diff --git a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected b/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected index 615c8b80776..d6c2f338008 100644 --- a/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected +++ b/swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected @@ -1,3 +1,6 @@ +| customurlschemes.swift:17:44:17:54 | url | external | +| customurlschemes.swift:20:52:20:68 | url | external | +| customurlschemes.swift:23:52:23:62 | url | external | | string.swift:27:21:27:21 | call to init(contentsOf:) | external | | string.swift:27:21:27:44 | call to init(contentsOf:) | external | | url.swift:53:15:53:19 | .resourceBytes | external | diff --git a/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift new file mode 100644 index 00000000000..210a5977d49 --- /dev/null +++ b/swift/ql/test/library-tests/dataflow/flowsources/customurlschemes.swift @@ -0,0 +1,26 @@ +// --- stubs --- +class UIApplication { + struct OpenURLOptionsKey {} +} + +struct URL {} + +protocol UIApplicationDelegate { + optional func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool + optional func application(_ application: UIApplication, handleOpen url: URL) -> Bool + optional func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool +} + +// --- tests --- + +class AppDelegate: UIApplicationDelegate { + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { // SOURCE + } + + func application(_ application: UIApplication, handleOpen url: URL) -> Bool { // SOURCE + } + + func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool { // SOURCE + } + +} \ No newline at end of file From a64286b66491eedd94af261154f6661150f275ec Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 11 Oct 2022 15:12:43 +0200 Subject: [PATCH 120/164] Ruby: add test for singleton class instance field incorrect test output --- .../library-tests/modules/ancestors.expected | 7 +++ .../library-tests/modules/callgraph.expected | 12 +++++ .../library-tests/modules/instance_fields.rb | 29 ++++++++++++ .../library-tests/modules/methods.expected | 26 +++++++++++ .../library-tests/modules/modules.expected | 45 +++++++++++++++++++ .../modules/superclasses.expected | 7 +++ 6 files changed, 126 insertions(+) create mode 100644 ruby/ql/test/library-tests/modules/instance_fields.rb diff --git a/ruby/ql/test/library-tests/modules/ancestors.expected b/ruby/ql/test/library-tests/modules/ancestors.expected index 98cfa6c7186..bd79b41a7be 100644 --- a/ruby/ql/test/library-tests/modules/ancestors.expected +++ b/ruby/ql/test/library-tests/modules/ancestors.expected @@ -120,6 +120,13 @@ hello.rb: # 18| HelloWorld #-----| super -> Greeting +instance_fields.rb: +# 11| A_target +#-----| super -> Object + +# 26| B_target +#-----| super -> Object + modules.rb: # 1| Empty diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index df2bffe2933..a3efd7cca3f 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -219,6 +219,12 @@ getTarget | hello.rb:14:16:14:20 | call to hello | hello.rb:2:5:4:7 | hello | | hello.rb:20:16:20:20 | call to super | hello.rb:13:5:15:7 | message | | hello.rb:20:30:20:34 | call to world | hello.rb:5:5:7:7 | world | +| instance_fields.rb:4:22:4:35 | call to new | calls.rb:117:5:117:16 | new | +| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:12:5:13:7 | target | +| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:27:5:28:7 | target | +| instance_fields.rb:19:22:19:35 | call to new | calls.rb:117:5:117:16 | new | +| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:12:5:13:7 | target | +| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:27:5:28:7 | target | | modules.rb:12:5:12:26 | call to puts | calls.rb:102:5:102:30 | puts | | modules.rb:22:3:22:19 | call to puts | calls.rb:102:5:102:30 | puts | | modules.rb:33:3:33:25 | call to puts | calls.rb:102:5:102:30 | puts | @@ -435,6 +441,12 @@ publicMethod | hello.rb:5:5:7:7 | world | | hello.rb:13:5:15:7 | message | | hello.rb:19:5:21:7 | message | +| instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:6:9:8:11 | use | +| instance_fields.rb:12:5:13:7 | target | +| instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:21:9:23:11 | use | +| instance_fields.rb:27:5:28:7 | target | | modules.rb:9:5:10:7 | method_in_foo_bar | | modules.rb:16:3:17:5 | method_in_foo | | modules.rb:27:3:28:5 | method_in_another_definition_of_foo | diff --git a/ruby/ql/test/library-tests/modules/instance_fields.rb b/ruby/ql/test/library-tests/modules/instance_fields.rb new file mode 100644 index 00000000000..ac981f8d5ef --- /dev/null +++ b/ruby/ql/test/library-tests/modules/instance_fields.rb @@ -0,0 +1,29 @@ +class A + class << self + def create + @field = ::A_target.new + end + def use + @field.target + end + end +end +class A_target + def target + end +end + +class B + class << self + def create + @field = ::B_target.new + end + def use + @field.target + end + end +end +class B_target + def target + end +end diff --git a/ruby/ql/test/library-tests/modules/methods.expected b/ruby/ql/test/library-tests/modules/methods.expected index d7d30b4f2e7..fb1cbb8358c 100644 --- a/ruby/ql/test/library-tests/modules/methods.expected +++ b/ruby/ql/test/library-tests/modules/methods.expected @@ -47,6 +47,8 @@ getMethod | hello.rb:1:1:8:3 | EnglishWords | world | hello.rb:5:5:7:7 | world | | hello.rb:11:1:16:3 | Greeting | message | hello.rb:13:5:15:7 | message | | hello.rb:18:1:22:3 | HelloWorld | message | hello.rb:19:5:21:7 | message | +| instance_fields.rb:11:1:14:3 | A_target | target | instance_fields.rb:12:5:13:7 | target | +| instance_fields.rb:26:1:29:3 | B_target | target | instance_fields.rb:27:5:28:7 | target | | modules.rb:4:1:24:3 | Foo | method_in_another_definition_of_foo | modules.rb:27:3:28:5 | method_in_another_definition_of_foo | | modules.rb:4:1:24:3 | Foo | method_in_foo | modules.rb:16:3:17:5 | method_in_foo | | modules.rb:5:3:14:5 | Foo::Bar | method_in_another_definition_of_foo_bar | modules.rb:52:3:53:5 | method_in_another_definition_of_foo_bar | @@ -430,6 +432,14 @@ lookupMethod | hello.rb:18:1:22:3 | HelloWorld | puts | calls.rb:102:5:102:30 | puts | | hello.rb:18:1:22:3 | HelloWorld | to_s | calls.rb:172:5:173:7 | to_s | | hello.rb:18:1:22:3 | HelloWorld | world | hello.rb:5:5:7:7 | world | +| instance_fields.rb:11:1:14:3 | A_target | new | calls.rb:117:5:117:16 | new | +| instance_fields.rb:11:1:14:3 | A_target | puts | calls.rb:102:5:102:30 | puts | +| instance_fields.rb:11:1:14:3 | A_target | target | instance_fields.rb:12:5:13:7 | target | +| instance_fields.rb:11:1:14:3 | A_target | to_s | calls.rb:172:5:173:7 | to_s | +| instance_fields.rb:26:1:29:3 | B_target | new | calls.rb:117:5:117:16 | new | +| instance_fields.rb:26:1:29:3 | B_target | puts | calls.rb:102:5:102:30 | puts | +| instance_fields.rb:26:1:29:3 | B_target | target | instance_fields.rb:27:5:28:7 | target | +| instance_fields.rb:26:1:29:3 | B_target | to_s | calls.rb:172:5:173:7 | to_s | | modules.rb:4:1:24:3 | Foo | method_in_another_definition_of_foo | modules.rb:27:3:28:5 | method_in_another_definition_of_foo | | modules.rb:4:1:24:3 | Foo | method_in_foo | modules.rb:16:3:17:5 | method_in_foo | | modules.rb:5:3:14:5 | Foo::Bar | method_in_another_definition_of_foo_bar | modules.rb:52:3:53:5 | method_in_another_definition_of_foo_bar | @@ -852,6 +862,22 @@ enclosingMethod | hello.rb:20:30:20:34 | self | hello.rb:19:5:21:7 | message | | hello.rb:20:38:20:40 | "!" | hello.rb:19:5:21:7 | message | | hello.rb:20:39:20:39 | ! | hello.rb:19:5:21:7 | message | +| instance_fields.rb:4:13:4:18 | @field | instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:4:13:4:18 | self | instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:4:13:4:35 | ... = ... | instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:4:22:4:31 | A_target | instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:4:22:4:35 | call to new | instance_fields.rb:3:9:5:11 | create | +| instance_fields.rb:7:13:7:18 | @field | instance_fields.rb:6:9:8:11 | use | +| instance_fields.rb:7:13:7:18 | self | instance_fields.rb:6:9:8:11 | use | +| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:6:9:8:11 | use | +| instance_fields.rb:19:13:19:18 | @field | instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:19:13:19:18 | self | instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:19:13:19:35 | ... = ... | instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:19:22:19:31 | B_target | instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:19:22:19:35 | call to new | instance_fields.rb:18:9:20:11 | create | +| instance_fields.rb:22:13:22:18 | @field | instance_fields.rb:21:9:23:11 | use | +| instance_fields.rb:22:13:22:18 | self | instance_fields.rb:21:9:23:11 | use | +| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:21:9:23:11 | use | | private.rb:84:7:84:32 | call to puts | private.rb:83:11:85:5 | m1 | | private.rb:84:7:84:32 | self | private.rb:83:11:85:5 | m1 | | private.rb:84:12:84:32 | "PrivateOverride1#m1" | private.rb:83:11:85:5 | m1 | diff --git a/ruby/ql/test/library-tests/modules/modules.expected b/ruby/ql/test/library-tests/modules/modules.expected index 93bcb04aec5..96182eac6ed 100644 --- a/ruby/ql/test/library-tests/modules/modules.expected +++ b/ruby/ql/test/library-tests/modules/modules.expected @@ -40,6 +40,8 @@ getModule | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | +| instance_fields.rb:11:1:14:3 | A_target | +| instance_fields.rb:26:1:29:3 | B_target | | modules.rb:1:1:2:3 | Empty | | modules.rb:4:1:24:3 | Foo | | modules.rb:5:3:14:5 | Foo::Bar | @@ -87,6 +89,7 @@ getADeclaration | calls.rb:115:1:118:3 | Object | calls.rb:1:1:550:40 | calls.rb | | calls.rb:115:1:118:3 | Object | calls.rb:115:1:118:3 | Object | | calls.rb:115:1:118:3 | Object | hello.rb:1:1:22:3 | hello.rb | +| calls.rb:115:1:118:3 | Object | instance_fields.rb:1:1:29:4 | instance_fields.rb | | calls.rb:115:1:118:3 | Object | modules.rb:1:1:129:4 | modules.rb | | calls.rb:115:1:118:3 | Object | modules_rec.rb:1:1:11:26 | modules_rec.rb | | calls.rb:115:1:118:3 | Object | private.rb:1:1:105:40 | private.rb | @@ -94,8 +97,10 @@ getADeclaration | calls.rb:125:1:138:3 | Array | calls.rb:125:1:138:3 | Array | | calls.rb:165:1:169:3 | S | calls.rb:165:1:169:3 | S | | calls.rb:171:1:174:3 | A | calls.rb:171:1:174:3 | A | +| calls.rb:171:1:174:3 | A | instance_fields.rb:1:1:10:3 | A | | calls.rb:171:1:174:3 | A | modules_rec.rb:7:1:9:3 | A | | calls.rb:176:1:179:3 | B | calls.rb:176:1:179:3 | B | +| calls.rb:176:1:179:3 | B | instance_fields.rb:16:1:25:3 | B | | calls.rb:190:1:226:3 | Singletons | calls.rb:190:1:226:3 | Singletons | | calls.rb:310:1:321:3 | SelfNew | calls.rb:310:1:321:3 | SelfNew | | calls.rb:325:1:329:3 | C1 | calls.rb:325:1:329:3 | C1 | @@ -113,6 +118,8 @@ getADeclaration | hello.rb:1:1:8:3 | EnglishWords | hello.rb:1:1:8:3 | EnglishWords | | hello.rb:11:1:16:3 | Greeting | hello.rb:11:1:16:3 | Greeting | | hello.rb:18:1:22:3 | HelloWorld | hello.rb:18:1:22:3 | HelloWorld | +| instance_fields.rb:11:1:14:3 | A_target | instance_fields.rb:11:1:14:3 | A_target | +| instance_fields.rb:26:1:29:3 | B_target | instance_fields.rb:26:1:29:3 | B_target | | modules.rb:1:1:2:3 | Empty | modules.rb:1:1:2:3 | Empty | | modules.rb:4:1:24:3 | Foo | modules.rb:4:1:24:3 | Foo | | modules.rb:4:1:24:3 | Foo | modules.rb:26:1:35:3 | Foo | @@ -185,6 +192,8 @@ getSuperClass | file://:0:0:0:0 | TrueClass | calls.rb:115:1:118:3 | Object | | hello.rb:11:1:16:3 | Greeting | calls.rb:115:1:118:3 | Object | | hello.rb:18:1:22:3 | HelloWorld | hello.rb:11:1:16:3 | Greeting | +| instance_fields.rb:11:1:14:3 | A_target | calls.rb:115:1:118:3 | Object | +| instance_fields.rb:26:1:29:3 | B_target | calls.rb:115:1:118:3 | Object | | modules.rb:6:5:7:7 | Foo::Bar::ClassInFooBar | calls.rb:115:1:118:3 | Object | | modules.rb:19:3:20:5 | Foo::ClassInFoo | calls.rb:115:1:118:3 | Object | | modules.rb:30:3:31:5 | Foo::ClassInAnotherDefinitionOfFoo | calls.rb:115:1:118:3 | Object | @@ -299,6 +308,8 @@ resolveConstantReadAccess | calls.rb:550:1:550:13 | Array | Array | | hello.rb:12:13:12:24 | EnglishWords | EnglishWords | | hello.rb:18:20:18:27 | Greeting | Greeting | +| instance_fields.rb:4:22:4:31 | A_target | A_target | +| instance_fields.rb:19:22:19:31 | B_target | B_target | | modules.rb:48:8:48:10 | Foo | Foo | | modules.rb:66:11:66:14 | Foo1 | Test::Foo1 | | modules.rb:72:11:72:14 | Foo2 | Test::Foo2::Foo2 | @@ -364,6 +375,10 @@ resolveConstantWriteAccess | hello.rb:1:1:8:3 | EnglishWords | EnglishWords | | hello.rb:11:1:16:3 | Greeting | Greeting | | hello.rb:18:1:22:3 | HelloWorld | HelloWorld | +| instance_fields.rb:1:1:10:3 | A | A | +| instance_fields.rb:11:1:14:3 | A_target | A_target | +| instance_fields.rb:16:1:25:3 | B | B | +| instance_fields.rb:26:1:29:3 | B_target | B_target | | modules.rb:1:1:2:3 | Empty | Empty | | modules.rb:4:1:24:3 | Foo | Foo | | modules.rb:5:3:14:5 | Bar | Foo::Bar | @@ -1366,6 +1381,36 @@ enclosingModule | hello.rb:20:30:20:34 | self | hello.rb:18:1:22:3 | HelloWorld | | hello.rb:20:38:20:40 | "!" | hello.rb:18:1:22:3 | HelloWorld | | hello.rb:20:39:20:39 | ! | hello.rb:18:1:22:3 | HelloWorld | +| instance_fields.rb:1:1:10:3 | A | instance_fields.rb:1:1:29:4 | instance_fields.rb | +| instance_fields.rb:2:5:9:7 | class << ... | instance_fields.rb:1:1:10:3 | A | +| instance_fields.rb:2:14:2:17 | self | instance_fields.rb:1:1:10:3 | A | +| instance_fields.rb:3:9:5:11 | create | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:4:13:4:18 | @field | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:4:13:4:18 | self | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:4:13:4:35 | ... = ... | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:4:22:4:31 | A_target | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:4:22:4:35 | call to new | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:6:9:8:11 | use | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:7:13:7:18 | @field | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:7:13:7:18 | self | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:2:5:9:7 | class << ... | +| instance_fields.rb:11:1:14:3 | A_target | instance_fields.rb:1:1:29:4 | instance_fields.rb | +| instance_fields.rb:12:5:13:7 | target | instance_fields.rb:11:1:14:3 | A_target | +| instance_fields.rb:16:1:25:3 | B | instance_fields.rb:1:1:29:4 | instance_fields.rb | +| instance_fields.rb:17:5:24:7 | class << ... | instance_fields.rb:16:1:25:3 | B | +| instance_fields.rb:17:14:17:17 | self | instance_fields.rb:16:1:25:3 | B | +| instance_fields.rb:18:9:20:11 | create | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:19:13:19:18 | @field | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:19:13:19:18 | self | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:19:13:19:35 | ... = ... | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:19:22:19:31 | B_target | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:19:22:19:35 | call to new | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:21:9:23:11 | use | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:22:13:22:18 | @field | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:22:13:22:18 | self | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:17:5:24:7 | class << ... | +| instance_fields.rb:26:1:29:3 | B_target | instance_fields.rb:1:1:29:4 | instance_fields.rb | +| instance_fields.rb:27:5:28:7 | target | instance_fields.rb:26:1:29:3 | B_target | | modules.rb:1:1:2:3 | Empty | modules.rb:1:1:129:4 | modules.rb | | modules.rb:4:1:24:3 | Foo | modules.rb:1:1:129:4 | modules.rb | | modules.rb:5:3:14:5 | Bar | modules.rb:4:1:24:3 | Foo | diff --git a/ruby/ql/test/library-tests/modules/superclasses.expected b/ruby/ql/test/library-tests/modules/superclasses.expected index f73f7962731..e1d152f1417 100644 --- a/ruby/ql/test/library-tests/modules/superclasses.expected +++ b/ruby/ql/test/library-tests/modules/superclasses.expected @@ -114,6 +114,13 @@ hello.rb: # 18| HelloWorld #-----| -> Greeting +instance_fields.rb: +# 11| A_target +#-----| -> Object + +# 26| B_target +#-----| -> Object + modules.rb: # 1| Empty From ed165c61942d6ade2970f1a689782463181a34b5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 11 Oct 2022 15:35:08 +0200 Subject: [PATCH 121/164] Ruby: bugfix in self-resolution in type-tracking --- .../ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll | 6 +++--- ruby/ql/test/library-tests/modules/callgraph.expected | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll index ca396eb7688..1c0ee2edcee 100644 --- a/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/typetracking/TypeTrackerSpecific.qll @@ -120,7 +120,7 @@ private MethodBase getAMethod(ModuleBase mod, boolean instance) { if result instanceof SingletonMethod then instance = false else instance = true or exists(SingletonClass cls | - cls.getValue().(SelfVariableAccess).getCfgScope() = mod and + cls.getValue().(SelfVariableAccess).getVariable().getDeclaringScope() = mod and result = cls.getAMethod().(Method) and instance = false ) @@ -133,7 +133,7 @@ private MethodBase getAMethod(ModuleBase mod, boolean instance) { pragma[nomagic] private Node fieldPredecessor(ModuleBase mod, boolean instance, string field) { exists(InstanceVariableWriteAccess access, AssignExpr assign | - access.getReceiver().getCfgScope() = getAMethod(mod, instance) and + access.getReceiver().getVariable().getDeclaringScope() = getAMethod(mod, instance) and field = access.getVariable().getName() and assign.getLeftOperand() = access and result.asExpr().getExpr() = assign.getRightOperand() @@ -147,7 +147,7 @@ private Node fieldPredecessor(ModuleBase mod, boolean instance, string field) { pragma[nomagic] private Node fieldSuccessor(ModuleBase mod, boolean instance, string field) { exists(InstanceVariableReadAccess access | - access.getReceiver().getCfgScope() = getAMethod(mod, instance) and + access.getReceiver().getVariable().getDeclaringScope() = getAMethod(mod, instance) and result.asExpr().getExpr() = access and field = access.getVariable().getName() ) diff --git a/ruby/ql/test/library-tests/modules/callgraph.expected b/ruby/ql/test/library-tests/modules/callgraph.expected index a3efd7cca3f..e5478960f3e 100644 --- a/ruby/ql/test/library-tests/modules/callgraph.expected +++ b/ruby/ql/test/library-tests/modules/callgraph.expected @@ -221,9 +221,7 @@ getTarget | hello.rb:20:30:20:34 | call to world | hello.rb:5:5:7:7 | world | | instance_fields.rb:4:22:4:35 | call to new | calls.rb:117:5:117:16 | new | | instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:12:5:13:7 | target | -| instance_fields.rb:7:13:7:25 | call to target | instance_fields.rb:27:5:28:7 | target | | instance_fields.rb:19:22:19:35 | call to new | calls.rb:117:5:117:16 | new | -| instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:12:5:13:7 | target | | instance_fields.rb:22:13:22:25 | call to target | instance_fields.rb:27:5:28:7 | target | | modules.rb:12:5:12:26 | call to puts | calls.rb:102:5:102:30 | puts | | modules.rb:22:3:22:19 | call to puts | calls.rb:102:5:102:30 | puts | From 4e3a6e60b241a091cd018d29d5bf0967a9bff753 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 17:48:46 +0000 Subject: [PATCH 122/164] JS: Bump patch version of ML-powered library and query packs --- .../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index b437e4de0ba..76f5f49ba26 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -version: 0.3.4 +version: 0.3.5 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 0942785b20a..6966c6dccd7 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.3.4 +version: 0.3.5 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: From 06bbede92b97b7b3d9d95ca1dd7b2b8824d4972d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 17:58:33 +0000 Subject: [PATCH 123/164] JS: Bump version of ML-powered library and query packs to 0.3.6 --- .../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +- .../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml index 76f5f49ba26..45d58aae0aa 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-experimental-atm-lib -version: 0.3.5 +version: 0.3.6 extractor: javascript library: true groups: diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml index 6966c6dccd7..c6bf027a58a 100644 --- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml +++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml @@ -1,6 +1,6 @@ name: codeql/javascript-experimental-atm-queries language: javascript -version: 0.3.5 +version: 0.3.6 suites: codeql-suites defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls groups: From d3c8ce3f48f4a23d170e561380fc839f471827d0 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 11 Oct 2022 21:35:58 +0100 Subject: [PATCH 124/164] Ruby: ActiveSupport extends Pathname with an existence method that may return itself --- .../codeql/ruby/frameworks/ActiveSupport.qll | 25 +++++++++++++++++++ .../ActiveSupportDataFlow.expected | 17 +++++++++++++ .../active_support/active_support.rb | 9 +++++++ 3 files changed, 51 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll index d21877fe49d..c62f4678c7b 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll @@ -140,6 +140,31 @@ module ActiveSupport { } } + /** + * Type summaries for extensions to the `Pathname` module. + */ + private class PathnameTypeSummary extends ModelInput::TypeModelCsv { + override predicate row(string row) { + // package1;type1;package2;type2;path + row = + [ + // Pathname#existence : Pathname + ";Pathname;;Pathname;Method[existence].ReturnValue", + ] + } + } + + /** Taint flow summaries for extensions to the `Pathname` module. */ + private class PathnameTaintSummary extends ModelInput::SummaryModelCsv { + override predicate row(string row) { + row = + [ + // Pathname#existence + ";Pathname;Method[existence];Argument[self];ReturnValue;taint", + ] + } + } + /** * `ActiveSupport::SafeBuffer` wraps a string, providing HTML-safe methods * for concatenation. diff --git a/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected b/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected index 2128d0173b1..6ad05678f03 100644 --- a/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected +++ b/ruby/ql/test/library-tests/frameworks/active_support/ActiveSupportDataFlow.expected @@ -136,6 +136,14 @@ edges | active_support.rb:191:34:191:34 | a : | active_support.rb:191:7:191:35 | call to new : | | active_support.rb:192:7:192:7 | x : | active_support.rb:192:7:192:16 | call to to_param : | | active_support.rb:192:7:192:16 | call to to_param : | active_support.rb:193:8:193:8 | y | +| active_support.rb:197:7:197:16 | call to source : | active_support.rb:198:20:198:20 | a : | +| active_support.rb:198:7:198:21 | call to new : | active_support.rb:199:7:199:7 | x : | +| active_support.rb:198:20:198:20 | a : | active_support.rb:198:7:198:21 | call to new : | +| active_support.rb:199:7:199:7 | x : | active_support.rb:199:7:199:17 | call to existence : | +| active_support.rb:199:7:199:17 | call to existence : | active_support.rb:200:8:200:8 | y | +| active_support.rb:199:7:199:17 | call to existence : | active_support.rb:201:7:201:7 | y : | +| active_support.rb:201:7:201:7 | y : | active_support.rb:201:7:201:17 | call to existence : | +| active_support.rb:201:7:201:17 | call to existence : | active_support.rb:202:8:202:8 | z | nodes | active_support.rb:9:9:9:18 | call to source : | semmle.label | call to source : | | active_support.rb:10:10:10:10 | x : | semmle.label | x : | @@ -310,6 +318,15 @@ nodes | active_support.rb:192:7:192:7 | x : | semmle.label | x : | | active_support.rb:192:7:192:16 | call to to_param : | semmle.label | call to to_param : | | active_support.rb:193:8:193:8 | y | semmle.label | y | +| active_support.rb:197:7:197:16 | call to source : | semmle.label | call to source : | +| active_support.rb:198:7:198:21 | call to new : | semmle.label | call to new : | +| active_support.rb:198:20:198:20 | a : | semmle.label | a : | +| active_support.rb:199:7:199:7 | x : | semmle.label | x : | +| active_support.rb:199:7:199:17 | call to existence : | semmle.label | call to existence : | +| active_support.rb:200:8:200:8 | y | semmle.label | y | +| active_support.rb:201:7:201:7 | y : | semmle.label | y : | +| active_support.rb:201:7:201:17 | call to existence : | semmle.label | call to existence : | +| active_support.rb:202:8:202:8 | z | semmle.label | z | subpaths #select | active_support.rb:106:10:106:13 | ...[...] | active_support.rb:104:10:104:17 | call to source : | active_support.rb:106:10:106:13 | ...[...] | $@ | active_support.rb:104:10:104:17 | call to source : | call to source : | diff --git a/ruby/ql/test/library-tests/frameworks/active_support/active_support.rb b/ruby/ql/test/library-tests/frameworks/active_support/active_support.rb index 9dac336f3dc..425a941cbd6 100644 --- a/ruby/ql/test/library-tests/frameworks/active_support/active_support.rb +++ b/ruby/ql/test/library-tests/frameworks/active_support/active_support.rb @@ -192,3 +192,12 @@ def m_safe_buffer_to_param y = x.to_param sink y # $hasTaintFlow=a end + +def m_pathname_existence + a = source "a" + x = Pathname.new(a) + y = x.existence + sink y # $hasTaintFlow=a + z = y.existence + sink z # $hasTaintFlow=a +end From bf4dac78c511dae1a53e67618bd51d745580a6e1 Mon Sep 17 00:00:00 2001 From: Alex Ford Date: Tue, 11 Oct 2022 21:44:52 +0100 Subject: [PATCH 125/164] Ruby: remove some singleton set literals --- .../lib/codeql/ruby/frameworks/ActiveSupport.qll | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll index c62f4678c7b..0cf990ad00a 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll @@ -146,22 +146,16 @@ module ActiveSupport { private class PathnameTypeSummary extends ModelInput::TypeModelCsv { override predicate row(string row) { // package1;type1;package2;type2;path - row = - [ - // Pathname#existence : Pathname - ";Pathname;;Pathname;Method[existence].ReturnValue", - ] + // Pathname#existence : Pathname + row = ";Pathname;;Pathname;Method[existence].ReturnValue" } } /** Taint flow summaries for extensions to the `Pathname` module. */ private class PathnameTaintSummary extends ModelInput::SummaryModelCsv { override predicate row(string row) { - row = - [ - // Pathname#existence - ";Pathname;Method[existence];Argument[self];ReturnValue;taint", - ] + // Pathname#existence + row = ";Pathname;Method[existence];Argument[self];ReturnValue;taint" } } From e55be83645e4280bf5bb54b69b13dc8e60a0c219 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 12 Oct 2022 09:47:04 +0200 Subject: [PATCH 126/164] Ruby: add 'render file:' as file system access --- ruby/ql/lib/codeql/ruby/frameworks/Rails.qll | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll b/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll index 9543076d101..49e0b881660 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/Rails.qll @@ -71,6 +71,21 @@ module Rails { /** A render call that does not automatically set the HTTP response body. */ class RenderToCall extends MethodCall instanceof RenderToCallImpl { } + + /** + * A `render` call seen as a file system access. + */ + private class RenderAsFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode { + RenderAsFileSystemAccess() { + exists(MethodCall call | this.asExpr().getExpr() = call | + call instanceof RenderCall + or + call instanceof RenderToCall + ) + } + + override DataFlow::Node getAPathArgument() { result = this.getKeywordArgument("file") } + } } /** From c77f685c0c3c2a0dda665b6a5c438527784137ae Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:47 -0400 Subject: [PATCH 127/164] spelling: operations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp index 37b78dd368c..c819a9d9159 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp +++ b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp @@ -6,7 +6,7 @@

    This rule finds logical-not operator usage as an operator for in a bit-wise operation.

    -

    Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise opeartions. Violations are often indicative of a typo, using a logical-not (!) opeartor instead of the bit-wise not (~) operator.

    +

    Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise operations. Violations are often indicative of a typo, using a logical-not (!) opeartor instead of the bit-wise not (~) operator.

    This rule is restricted to analyze bit-wise and (&) and bit-wise or (|) operation in order to provide better precision.

    This rule ignores instances where a double negation (!!) is explicitly used as the opeartor of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0.

    NOTE: It is not recommended to use this rule in kernel code or older C code as it will likely find several false positive instances.

    From 114653162c5bdf39df7f56b55ade3b90026f64a4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:47 -0400 Subject: [PATCH 128/164] spelling: operator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp index c819a9d9159..bac09fe9cf1 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp +++ b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp @@ -6,9 +6,9 @@

    This rule finds logical-not operator usage as an operator for in a bit-wise operation.

    -

    Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise operations. Violations are often indicative of a typo, using a logical-not (!) opeartor instead of the bit-wise not (~) operator.

    +

    Due to the nature of logical operation result value, only the lowest bit could possibly be set, and it is unlikely to be intent in bitwise operations. Violations are often indicative of a typo, using a logical-not (!) operator instead of the bit-wise not (~) operator.

    This rule is restricted to analyze bit-wise and (&) and bit-wise or (|) operation in order to provide better precision.

    -

    This rule ignores instances where a double negation (!!) is explicitly used as the opeartor of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0.

    +

    This rule ignores instances where a double negation (!!) is explicitly used as the operator of the bitwise operation, as this is a commonly used as a mechanism to normalize an integer value to either 1 or 0.

    NOTE: It is not recommended to use this rule in kernel code or older C code as it will likely find several false positive instances.

    From 7e0bbf1bdb4566456e8d4b752cfbf6bbbfa4e320 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Tue, 11 Oct 2022 00:07:59 -0400 Subject: [PATCH 129/164] spelling: optimization Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp index 771d7e23e52..1fbb116f8ca 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp @@ -10,7 +10,7 @@ header files, and this inclusion graph contains a cycle, then at least one file cycle. Because of cases like these, all headers should be guarded as a matter of good practice, even if they do not strictly need to be.

    -Furthermore, most modern compilers contain optimisations which are triggered by header guards. If the header guard strictly conforms to the pattern +Furthermore, most modern compilers contain optimizations which are triggered by header guards. If the header guard strictly conforms to the pattern that compilers expect, then inclusions of that header other than the first have absolutely no effect: the file isn't re-read from disk, nor is it re-tokenised or re-preprocessed. This can result in a noticeable, albeit minor, improvement to compilation time.

    From 091950756502dd3b0d0ab06783b0f6a46194b766 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:48 -0400 Subject: [PATCH 130/164] spelling: outside Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Likely Bugs/Memory Management/SuspiciousCallToStrncat.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.qhelp index 13c1e6d2710..3ffc326585f 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.qhelp @@ -12,7 +12,7 @@ the third argument to the entire size of the destination buffer. Executing a call of this type may cause a buffer overflow unless the buffer is known to be empty.

    Similarly, calls of the form strncat(dest, src, sizeof (dest) - strlen (dest)) allow one -byte to be written ouside the dest buffer.

    +byte to be written outside the dest buffer.

    Buffer overflows can lead to anything from a segmentation fault to a security vulnerability.

    From ba0f34afed33e80a1714cdffb20641ff260f7c94 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:37:18 -0400 Subject: [PATCH 131/164] spelling: owasp Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../CWE/CWE-200/TempDirLocalInformationDisclosure.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.qhelp b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.qhelp index e3bf61107c4..98a3b8d36da 100644 --- a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.qhelp +++ b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.qhelp @@ -43,7 +43,7 @@ For example: PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePerm
    -
  • OSWAP: Insecure Temporary File.
  • +
  • OWASP: Insecure Temporary File.
  • CERT: FIO00-J. Do not operate on files in shared directories.
  • \ No newline at end of file From 71b0613f9ad326d09a26eb44450ae30ba354e7a9 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:49 -0400 Subject: [PATCH 132/164] spelling: parenthesized Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.qhelp index aef03996053..5cae8407887 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.qhelp @@ -6,7 +6,7 @@

    -This rule finds comparison expressions that use 2 or more comparison operators and are not completely paranthesized. +This rule finds comparison expressions that use 2 or more comparison operators and are not completely parenthesized. It is best to fully parenthesize complex comparison expressions to explicitly define the order of the comparison operators.

    From 061d1ee9fee021efc30af7834df475bd95fd34e0 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:49 -0400 Subject: [PATCH 133/164] spelling: presence Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qhelp b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qhelp index 519d21fd8c1..11d824c2d41 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.qhelp @@ -5,7 +5,7 @@

    This query indicates that a call is setting the DACL field in a SECURITY_DESCRIPTOR to null.

    -

    When using SetSecurityDescriptorDacl to set a discretionary access control (DACL), setting the bDaclPresent argument to TRUE indicates the prescence of a DACL in the security description in the argument pDacl.

    +

    When using SetSecurityDescriptorDacl to set a discretionary access control (DACL), setting the bDaclPresent argument to TRUE indicates the presence of a DACL in the security description in the argument pDacl.

    When the pDacl parameter does not point to a DACL (i.e. it is NULL) and the bDaclPresent flag is TRUE, a NULL DACL is specified.

    A NULL DACL grants full access to any user who requests it; normal security checking is not performed with respect to the object.

    From 1a14c060088ecf2e9a4cbcb606ea0c5958c3601c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:37:42 -0400 Subject: [PATCH 134/164] spelling: receiver Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp b/java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp index e489e411379..3fda3697dfa 100644 --- a/java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp +++ b/java/ql/src/Security/CWE/CWE-925/ImproperIntentVerification.qhelp @@ -26,7 +26,7 @@ Otherwise, a third-party application could impersonate the system this way to ca

    -In the onReceive method of a BroadcastReciever, the action of the received Intent should be checked. The following code demonstrates this. +In the onReceive method of a BroadcastReceiver, the action of the received Intent should be checked. The following code demonstrates this.

    From 08a79531cfb1446c36902ccac509fc9518b8653f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:37:50 -0400 Subject: [PATCH 135/164] spelling: response Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Security/CWE/CWE-094/SpringViewManipulation.qhelp | 4 ++-- .../ql/lib/semmle/javascript/frameworks/ClientRequests.qll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp index 45c981f0e29..67d348dfdb3 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-094/SpringViewManipulation.qhelp @@ -19,7 +19,7 @@

    In general, using user input to determine Spring view name should be avoided. If user input must be included in the expression, the controller can be annotated by - a @ReponseBody annotation. In this case, Spring Framework does not interpret + a @ResponseBody annotation. In this case, Spring Framework does not interpret it as a view name, but just returns this string in HTTP Response. The same applies to using a @RestController annotation on a class, as internally it inherits @ResponseBody.

    @@ -31,7 +31,7 @@

    - This can be easily prevented by using the ResponseBody annotation which marks the reponse is already processed preventing exploitation of Spring View Manipulation vulnerabilities. Alternatively, this can also be fixed by adding a HttpServletResponse parameter to the method definition as shown in the example below. + This can be easily prevented by using the ResponseBody annotation which marks the response is already processed preventing exploitation of Spring View Manipulation vulnerabilities. Alternatively, this can also be fixed by adding a HttpServletResponse parameter to the method definition as shown in the example below.

    diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll index f570c9d3a38..1453f995433 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll @@ -671,7 +671,7 @@ module ClientRequest { } /** - * Gets the response type corresponding to `getReponse()` but not + * Gets the response type corresponding to `getResponse()` but not * for explicitly typed calls like `getResponseJson()`. */ string getAssignedResponseType() { From 9eac158d7cb4dd009c8b6923710e8efa07f84c4c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:50 -0400 Subject: [PATCH 136/164] spelling: revocation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../Security/CWE/CWE-299/DisabledRevocationChecking.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/experimental/Security/CWE/CWE-299/DisabledRevocationChecking.qhelp b/java/ql/src/experimental/Security/CWE/CWE-299/DisabledRevocationChecking.qhelp index 2b359faf1ed..9883a64bc7a 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-299/DisabledRevocationChecking.qhelp +++ b/java/ql/src/experimental/Security/CWE/CWE-299/DisabledRevocationChecking.qhelp @@ -23,7 +23,7 @@ then revocation checking is not going to happen.

    -

    An application should not disable the default revocationg checking mechanism +

    An application should not disable the default revocation checking mechanism unless it provides a custom revocation checker.

    From b9d8903bdb3b606217db87080a831a039f1dad63 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 06:38:05 -0400 Subject: [PATCH 137/164] spelling: similarly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp index 1fbb116f8ca..bc51714ec69 100644 --- a/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp +++ b/cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp @@ -5,7 +5,7 @@

    Some header files, such as those which define structures or classes, cannot be included more than once within a translation unit, as doing so would -cause a redefinition error. Such headers must be guarded to prevent ill-effects from multiple inclusion. Simlarly, if header files include other +cause a redefinition error. Such headers must be guarded to prevent ill-effects from multiple inclusion. Similarly, if header files include other header files, and this inclusion graph contains a cycle, then at least one file within the cycle must contain header guards in order to break the cycle. Because of cases like these, all headers should be guarded as a matter of good practice, even if they do not strictly need to be.

    From a8e5a12ec2a904f310f9d6bff20b0dc813e1e35f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:13:51 -0400 Subject: [PATCH 138/164] spelling: specific Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- csharp/ql/src/Likely Bugs/MishandlingJapaneseEra.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/ql/src/Likely Bugs/MishandlingJapaneseEra.qhelp b/csharp/ql/src/Likely Bugs/MishandlingJapaneseEra.qhelp index a2000deb2d5..c77c656a655 100644 --- a/csharp/ql/src/Likely Bugs/MishandlingJapaneseEra.qhelp +++ b/csharp/ql/src/Likely Bugs/MishandlingJapaneseEra.qhelp @@ -9,7 +9,7 @@

    -

    Use speific era when creating DateTime and DateTimeOffset structs from previously stored date in Japanese calendar

    +

    Use specific era when creating DateTime and DateTimeOffset structs from previously stored date in Japanese calendar

    Don't store dates in Japanese format

    Don't use hard-coded era start date for date calculations converting dates from Japanese date format

    Use JapaneseCalendar class for date formatting only

    From 9d6ea28448f079f8866906be7e183cfb66bfd337 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:25:00 -0400 Subject: [PATCH 139/164] spelling: the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp b/javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp index f355ef0aa6e..4424fe363a2 100644 --- a/javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp +++ b/javascript/ql/src/Security/CWE-094/ExpressionInjection.qhelp @@ -23,7 +23,7 @@

    It is also recommended to limit the permissions of any tokens used - by a workflow such as the the GITHUB_TOKEN. + by a workflow such as the GITHUB_TOKEN.

    From c92ce69f480f0b397fe6c1f2ed5ae934815b8398 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sun, 9 Oct 2022 07:23:37 -0400 Subject: [PATCH 140/164] spelling: when Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- cpp/ql/src/Critical/DescriptorMayNotBeClosed.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.qhelp b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.qhelp index 2016e05d936..41473d68371 100644 --- a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.qhelp +++ b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.qhelp @@ -19,7 +19,7 @@ This can occur when an operation performed on the open descriptor fails, and the

    In the example below, the sockfd socket may remain open if an error is triggered. -The code should be updated to ensure that the socket is always closed when when the function ends. +The code should be updated to ensure that the socket is always closed when the function ends.

    From 3b49594c20ff2c701379f878e93d7bb8a18753e6 Mon Sep 17 00:00:00 2001 From: Chris Smowton Date: Wed, 12 Oct 2022 11:04:12 +0100 Subject: [PATCH 141/164] Kotlin: Add Callable.getKotlinParameterDefaultsProxy --- java/ql/lib/semmle/code/java/Member.qll | 42 ++++++++++ .../parameter-defaults/PrintAst.expected | 79 +++++++++++++++++++ .../parameter-defaults/defaults.expected | 15 ++++ .../parameter-defaults/defaults.ql | 7 ++ .../library-tests/parameter-defaults/test.kt | 7 ++ 5 files changed, 150 insertions(+) create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/defaults.expected create mode 100644 java/ql/test/kotlin/library-tests/parameter-defaults/defaults.ql diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 456e6e8b12a..9aa1f8d31c0 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -294,6 +294,48 @@ class Callable extends StmtParent, Member, @callable { constrs(this, _, result, _, _, _) or methods(this, _, result, _, _, _) } + + /** + * Gets this callable's Kotlin proxy that supplies default parameter values, if one exists. + * + * For example, for the Kotlin declaration `fun f(x: Int, y: Int = 0, z: String = "1")`, + * this will get the synthetic proxy method that fills in the default values for `y` and `z` + * if not supplied, and to which the Kotlin extractor dispatches calls to `f` that are missing + * one or more parameter value. Similarly, constructors with one or more default parameter values + * have a corresponding constructor that fills in default values. + */ + Callable getKotlinParameterDefaultsProxy() { + this.getDeclaringType() = result.getDeclaringType() and + exists(int proxyNParams, int extraLeadingParams, RefType lastParamType | + proxyNParams = result.getNumberOfParameters() and + extraLeadingParams = (proxyNParams - this.getNumberOfParameters()) - 2 and + extraLeadingParams >= 0 and + result.getParameterType(proxyNParams - 1) = lastParamType and + result.getParameterType(proxyNParams - 2).(PrimitiveType).hasName("int") and + ( + this instanceof Constructor and + result instanceof Constructor and + extraLeadingParams = 0 and + lastParamType.hasQualifiedName("kotlin.jvm.internal", "DefaultConstructorMarker") + or + this instanceof Method and + result instanceof Method and + this.getName() + "$default" = result.getName() and + extraLeadingParams <= 2 and + lastParamType instanceof TypeObject + ) + | + forall(int paramIdx | paramIdx in [extraLeadingParams .. proxyNParams - 3] | + this.getParameterType(paramIdx - extraLeadingParams).getErasure() = + eraseRaw(result.getParameterType(paramIdx)) + ) + ) + } +} + +/** Gets the erasure of `t1` if it is a raw type, or `t1` itself otherwise. */ +private Type eraseRaw(Type t1) { + if t1 instanceof RawType then result = t1.getErasure() else result = t1 } /** Holds if method `m1` overrides method `m2`. */ diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected index 95198f2beaa..6a850a431d2 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/PrintAst.expected @@ -1221,3 +1221,82 @@ test.kt: # 173| 5: [BlockStmt] { ... } # 173| 0: [ReturnStmt] return ... # 173| 0: [VarAccess] t +# 177| 17: [Class] TestOverloadsWithDefaults +# 177| 1: [Constructor] TestOverloadsWithDefaults +# 177| 5: [BlockStmt] { ... } +# 177| 0: [SuperConstructorInvocationStmt] super(...) +# 177| 1: [BlockStmt] { ... } +# 179| 2: [Method] f +# 179| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 179| 0: [Parameter] x +# 179| 0: [TypeAccess] int +# 179| 1: [Parameter] y +# 179| 0: [TypeAccess] String +# 179| 5: [BlockStmt] { ... } +# 179| 3: [Method] f$default +# 179| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 179| 0: [Parameter] p0 +# 179| 0: [TypeAccess] TestOverloadsWithDefaults +# 179| 1: [Parameter] p1 +# 179| 0: [TypeAccess] int +# 179| 2: [Parameter] p2 +# 179| 0: [TypeAccess] String +# 179| 3: [Parameter] p3 +# 179| 0: [TypeAccess] int +# 179| 4: [Parameter] p4 +# 179| 0: [TypeAccess] Object +# 179| 5: [BlockStmt] { ... } +# 179| 0: [IfStmt] if (...) +# 179| 0: [EQExpr] ... == ... +# 179| 0: [AndBitwiseExpr] ... & ... +# 179| 0: [IntegerLiteral] 2 +# 179| 1: [VarAccess] p3 +# 179| 1: [IntegerLiteral] 0 +# 179| 1: [ExprStmt] ; +# 179| 0: [AssignExpr] ...=... +# 179| 0: [VarAccess] p2 +# 179| 1: [StringLiteral] Hello world +# 179| 1: [ReturnStmt] return ... +# 179| 0: [MethodAccess] f(...) +# 179| -1: [VarAccess] p0 +# 179| 0: [VarAccess] p1 +# 179| 1: [VarAccess] p2 +# 180| 4: [Method] f +# 180| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 180| 0: [Parameter] z +# 180| 0: [TypeAccess] String +# 180| 1: [Parameter] w +# 180| 0: [TypeAccess] int +# 180| 5: [BlockStmt] { ... } +# 180| 5: [Method] f$default +# 180| 3: [TypeAccess] Unit +#-----| 4: (Parameters) +# 180| 0: [Parameter] p0 +# 180| 0: [TypeAccess] TestOverloadsWithDefaults +# 180| 1: [Parameter] p1 +# 180| 0: [TypeAccess] String +# 180| 2: [Parameter] p2 +# 180| 0: [TypeAccess] int +# 180| 3: [Parameter] p3 +# 180| 0: [TypeAccess] int +# 180| 4: [Parameter] p4 +# 180| 0: [TypeAccess] Object +# 180| 5: [BlockStmt] { ... } +# 180| 0: [IfStmt] if (...) +# 180| 0: [EQExpr] ... == ... +# 180| 0: [AndBitwiseExpr] ... & ... +# 180| 0: [IntegerLiteral] 2 +# 180| 1: [VarAccess] p3 +# 180| 1: [IntegerLiteral] 0 +# 180| 1: [ExprStmt] ; +# 180| 0: [AssignExpr] ...=... +# 180| 0: [VarAccess] p2 +# 180| 1: [IntegerLiteral] 0 +# 180| 1: [ReturnStmt] return ... +# 180| 0: [MethodAccess] f(...) +# 180| -1: [VarAccess] p0 +# 180| 0: [VarAccess] p1 +# 180| 1: [VarAccess] p2 diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.expected b/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.expected new file mode 100644 index 00000000000..b0bb467d954 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.expected @@ -0,0 +1,15 @@ +| test.kt:5:3:7:3 | f | test.kt:5:3:7:3 | f$default | +| test.kt:34:14:36:3 | f | test.kt:34:14:36:3 | f$default | +| test.kt:68:1:80:1 | TestConstructor | test.kt:68:1:80:1 | TestConstructor | +| test.kt:86:5:88:5 | f | test.kt:86:5:88:5 | f$default | +| test.kt:106:7:108:7 | f | test.kt:106:7:108:7 | f$default | +| test.kt:124:3:126:3 | f | test.kt:124:3:126:3 | f$default | +| test.kt:135:3:135:43 | testReturn | test.kt:135:3:135:43 | testReturn$default | +| test.kt:145:3:147:3 | f | test.kt:145:3:147:3 | f$default | +| test.kt:158:3:158:35 | f | test.kt:158:3:158:35 | f$default | +| test.kt:159:12:159:44 | g$main | test.kt:159:12:159:44 | g$main$default | +| test.kt:160:13:160:45 | h | test.kt:160:13:160:45 | h$default | +| test.kt:161:11:161:43 | i | test.kt:161:11:161:43 | i$default | +| test.kt:171:3:171:97 | f | test.kt:171:3:171:97 | f$default | +| test.kt:179:3:179:46 | f | test.kt:179:3:179:46 | f$default | +| test.kt:180:3:180:34 | f | test.kt:180:3:180:34 | f$default | diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.ql b/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.ql new file mode 100644 index 00000000000..e6f5f4b54c4 --- /dev/null +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/defaults.ql @@ -0,0 +1,7 @@ +import java + +from Callable realMethod, Callable defaultsProxy +where + defaultsProxy = realMethod.getKotlinParameterDefaultsProxy() and + realMethod.fromSource() +select realMethod, defaultsProxy diff --git a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt index 25a29fb468f..a3bd483a4b4 100644 --- a/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt +++ b/java/ql/test/kotlin/library-tests/parameter-defaults/test.kt @@ -173,3 +173,10 @@ class TestGenericUsedWithinDefaultValue { fun ident(t: T) = t } + +class TestOverloadsWithDefaults { + + fun f(x: Int, y: String = "Hello world") { } + fun f(z: String, w: Int = 0) { } + +} From aa9dc3a764da5920e8887f9139e5bc946723eb1f Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 12 Oct 2022 12:42:27 +0200 Subject: [PATCH 142/164] Kotlin: Add test case for useless parameter FP --- java/ql/test/kotlin/query-tests/UselessParameter/Test.kt | 2 ++ .../query-tests/UselessParameter/UselessParameter.expected | 2 ++ 2 files changed, 4 insertions(+) diff --git a/java/ql/test/kotlin/query-tests/UselessParameter/Test.kt b/java/ql/test/kotlin/query-tests/UselessParameter/Test.kt index f476eba616c..8675f01bf58 100644 --- a/java/ql/test/kotlin/query-tests/UselessParameter/Test.kt +++ b/java/ql/test/kotlin/query-tests/UselessParameter/Test.kt @@ -7,3 +7,5 @@ class B : A { println("a") } } + +fun fn(a: Int = 10) {} diff --git a/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected b/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected index e69de29bb2d..e53f04ec1c9 100644 --- a/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected +++ b/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected @@ -0,0 +1,2 @@ +| Test.kt:11:1:11:22 | p2 | The parameter 'p2' is never used. | +| Test.kt:11:8:11:18 | a | The parameter 'a' is never used. | From 955336fb222f8ccd626b7d0ce69b5f731ec0b494 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 12 Oct 2022 12:42:56 +0200 Subject: [PATCH 143/164] Kotlin: exclude generated code from useless parameter check --- java/ql/lib/semmle/code/java/deadcode/DeadCode.qll | 3 +++ .../query-tests/UselessParameter/UselessParameter.expected | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll index 8dbb9bb530e..c9d77a17115 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll @@ -304,6 +304,9 @@ class RootdefCallable extends Callable { this.getAnAnnotation() instanceof OverrideAnnotation or this.hasModifier("override") + or + // Exclude generated callables, such as `...$default` ones extracted from Kotlin code. + this.isCompilerGenerated() } } diff --git a/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected b/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected index e53f04ec1c9..106448e7ed7 100644 --- a/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected +++ b/java/ql/test/kotlin/query-tests/UselessParameter/UselessParameter.expected @@ -1,2 +1 @@ -| Test.kt:11:1:11:22 | p2 | The parameter 'p2' is never used. | | Test.kt:11:8:11:18 | a | The parameter 'a' is never used. | From a56770999f9df364cefbbb59bd7f2d837d56cc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 12 Oct 2022 12:54:27 +0200 Subject: [PATCH 144/164] Apply suggestions from code review Co-authored-by: Felicity Chapman Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com> --- .../CommaBeforeMisleadingIndentation.cpp | 6 +++--- .../CommaBeforeMisleadingIndentation.qhelp | 13 ++++++++----- .../CommaBeforeMisleadingIndentation.ql | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp index 2b30b6ba1f1..77246363fba 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.cpp @@ -1,5 +1,5 @@ /* - * Here, the comma should have been a semicolon: + * In this example, the developer intended to use a semicolon but accidentally used a comma: */ enum privileges entitlements = NONE; @@ -10,7 +10,7 @@ if (is_admin) restrict_privileges(entitlements); /* - * This is misleading, because the code is unexpectedly equivalent to: + * The use of a comma means that the first example is equivalent to this second example: */ enum privileges entitlements = NONE; @@ -21,7 +21,7 @@ if (is_admin) { } /* - * Whereas the following code was probably intended: + * The indentation of the first example suggests that the developer probably intended the following code: */ enum privileges entitlements = NONE; diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp index 8991ce31529..02f7cb2a64a 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -5,26 +5,29 @@

    -If the expression to the right of a comma operator starts at an earlier column than the expression to the left, then +If the expression after the comma operator starts at an earlier column than the expression before the comma, then this suspicious indentation possibly indicates a logic error, caused by a typo that may escape visual inspection.

    This query has medium precision because CodeQL currently does not distinguish between tabs and spaces in whitespace. -Alerts may therefore flag code that appears readable for one value of tab size but not another. +If a file contains mixed tabs and spaces, alerts may highlight code that is correctly indented for one value of tab size but not for other tab sizes.

    -Use standard indentation around the comma operator: begin the right-hand-side operand at the same level of -indentation (column number) as the left-hand-side operand. +To ensure that your code is easy to read and review, use standard indentation around the comma operator. Always begin the right-hand-side operand at the same level of +indentation (column number) as the left-hand-side operand. This makes it easier for other developers to see the intended behavior of your code.

    -When it comes to whitespace, either do not mix tabs and spaces, or mix them consistently. +Use whitespace consistently to communicate your coding intentions. Where possible, avoid mixing tabs and spaces within a file. If you need to mix them, use them consistently.

    +

    +This example shows three different ways of writing the same code. The first example contains a comma instead of a semicolon which means that the final line is part of the if statement, even though the indentation suggests that it is intended to be separate. The second example looks different put is functionally the same as the first example. It is more likely that the developer intended to write the third example. +

    diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 965894ba87d..2841a727e8f 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -1,6 +1,6 @@ /** * @name Comma before misleading indentation - * @description The expressions before and after the comma operator can be misread because of an unusual difference in start columns. + * @description If expressions before and after a comma operator use different indentation, it is easy to misread the purpose of the code. * @kind problem * @id cpp/comma-before-misleading-indentation * @problem.severity warning From 0d6da9ca7fca916d909257e68deea19e64bdf5f5 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Wed, 12 Oct 2022 12:58:28 +0200 Subject: [PATCH 145/164] Exclude serialization constructors from useless parameters check --- java/ql/lib/semmle/code/java/deadcode/DeadCode.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll index c9d77a17115..edeb9e9dccf 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadCode.qll @@ -307,6 +307,12 @@ class RootdefCallable extends Callable { or // Exclude generated callables, such as `...$default` ones extracted from Kotlin code. this.isCompilerGenerated() + or + // Exclude Kotlin serialization constructors. + this.(Constructor) + .getParameterType(this.getNumberOfParameters() - 1) + .(RefType) + .hasQualifiedName("kotlinx.serialization.internal", "SerializationConstructorMarker") } } From b42b88338e77b09c562d87748b116a66e76cb165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 12 Oct 2022 13:00:42 +0200 Subject: [PATCH 146/164] C++: s/put/but/ typo in QHelp --- .../Likely Errors/CommaBeforeMisleadingIndentation.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp index 02f7cb2a64a..2fd374a50d0 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -26,7 +26,7 @@ Use whitespace consistently to communicate your coding intentions. Where possibl

    -This example shows three different ways of writing the same code. The first example contains a comma instead of a semicolon which means that the final line is part of the if statement, even though the indentation suggests that it is intended to be separate. The second example looks different put is functionally the same as the first example. It is more likely that the developer intended to write the third example. +This example shows three different ways of writing the same code. The first example contains a comma instead of a semicolon which means that the final line is part of the if statement, even though the indentation suggests that it is intended to be separate. The second example looks different but is functionally the same as the first example. It is more likely that the developer intended to write the third example.

    From 93c01371c3ea42468e0e8b1c285b9546f973a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 12 Oct 2022 13:01:37 +0200 Subject: [PATCH 147/164] C++: no parens in select message Debatable; see comment thread in PR. --- .../Likely Errors/CommaBeforeMisleadingIndentation.ql | 2 +- .../CommaBeforeMisleadingIndentation.expected | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql index 2841a727e8f..b23234d4627 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.ql @@ -50,4 +50,4 @@ where not isParenthesized(ce) and leftLoc.getEndLine() < rightLoc.getStartLine() and leftLoc.getStartColumn() > rightLoc.getStartColumn() -select right, "The indentation level may be misleading (for some tab sizes)." +select right, "The indentation level may be misleading for some tab sizes." diff --git a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected index 0cc6e7f4fc4..e993345aa39 100644 --- a/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected +++ b/cpp/ql/test/query-tests/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation/CommaBeforeMisleadingIndentation.expected @@ -1,5 +1,5 @@ -| test.cpp:49:2:49:8 | (void)... | The indentation level may be misleading (for some tab sizes). | -| test.cpp:52:2:52:15 | (void)... | The indentation level may be misleading (for some tab sizes). | -| test.cpp:160:3:160:9 | (void)... | The indentation level may be misleading (for some tab sizes). | -| test.cpp:166:5:166:7 | ... ++ | The indentation level may be misleading (for some tab sizes). | -| test.cpp:176:6:178:6 | ... ? ... : ... | The indentation level may be misleading (for some tab sizes). | +| test.cpp:49:2:49:8 | (void)... | The indentation level may be misleading for some tab sizes. | +| test.cpp:52:2:52:15 | (void)... | The indentation level may be misleading for some tab sizes. | +| test.cpp:160:3:160:9 | (void)... | The indentation level may be misleading for some tab sizes. | +| test.cpp:166:5:166:7 | ... ++ | The indentation level may be misleading for some tab sizes. | +| test.cpp:176:6:178:6 | ... ? ... : ... | The indentation level may be misleading for some tab sizes. | From 695d8c6004820f6c011602f0507b9b83b7131d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nora=20Dimitrijevi=C4=87?= Date: Wed, 12 Oct 2022 13:21:24 +0200 Subject: [PATCH 148/164] C++: Add Wikipedia references to QHelp --- .../Likely Errors/CommaBeforeMisleadingIndentation.qhelp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp index 2fd374a50d0..d0aa29ca700 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp +++ b/cpp/ql/src/Best Practices/Likely Errors/CommaBeforeMisleadingIndentation.qhelp @@ -31,4 +31,9 @@ This example shows three different ways of writing the same code. The first exam + +
  • Wikipedia: Comma operator
  • +
  • Wikipedia: Indentation style — Tabs, spaces, and size of indentations
  • +
    + From f49bfa7bcced75c5610938ca5dbd7635f256d7be Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 12 Oct 2022 13:26:58 +0200 Subject: [PATCH 149/164] C#: Deprecate `Assignable(Read)::getAReachableRead` --- .../ql/lib/semmle/code/csharp/Assignable.qll | 6 +++-- .../lib/semmle/code/csharp/exprs/Access.qll | 18 ++++++++----- .../semmle/code/csharp/frameworks/Format.qll | 24 ++++++++++++------ .../API Abuse/DisposeNotCalledOnException.ql | 18 ++++++++++--- .../src/Useless code/DefaultToStringQuery.qll | 25 +++++++++++-------- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/csharp/ql/lib/semmle/code/csharp/Assignable.qll b/csharp/ql/lib/semmle/code/csharp/Assignable.qll index ede365ccf75..975f69edaa9 100644 --- a/csharp/ql/lib/semmle/code/csharp/Assignable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Assignable.qll @@ -111,6 +111,7 @@ class AssignableRead extends AssignableAccess { * - The reads of `i` on lines 7 and 8 are next to the read on line 6. * - The read of `this.Field` on line 11 is next to the read on line 10. */ + pragma[nomagic] AssignableRead getANextRead() { forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() | cfn = this.getAnAdjacentReadSameVar() @@ -124,7 +125,7 @@ class AssignableRead extends AssignableAccess { * * This is the transitive closure of `getANextRead()`. */ - AssignableRead getAReachableRead() { result = this.getANextRead+() } + deprecated AssignableRead getAReachableRead() { result = this.getANextRead+() } } /** @@ -479,6 +480,7 @@ class AssignableDefinition extends TAssignableDefinition { * Subsequent reads can be found by following the steps defined by * `AssignableRead.getANextRead()`. */ + pragma[nomagic] AssignableRead getAFirstRead() { forex(ControlFlow::Node cfn | cfn = result.getAControlFlowNode() | exists(Ssa::ExplicitDefinition def | result = def.getAFirstReadAtNode(cfn) | @@ -494,7 +496,7 @@ class AssignableDefinition extends TAssignableDefinition { * * This is the equivalent with `getAFirstRead().getANextRead*()`. */ - AssignableRead getAReachableRead() { result = this.getAFirstRead().getANextRead*() } + deprecated AssignableRead getAReachableRead() { result = this.getAFirstRead().getANextRead*() } /** Gets a textual representation of this assignable definition. */ string toString() { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll index 9d7cf3a5867..3e3c8ca79e8 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Access.qll @@ -174,7 +174,9 @@ class VariableAccess extends AssignableAccess, @variable_access_expr { class VariableRead extends VariableAccess, AssignableRead { override VariableRead getANextRead() { result = AssignableRead.super.getANextRead() } - override VariableRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() } + deprecated override VariableRead getAReachableRead() { + result = AssignableRead.super.getAReachableRead() + } } /** @@ -200,7 +202,7 @@ class LocalScopeVariableAccess extends VariableAccess, @local_scope_variable_acc class LocalScopeVariableRead extends LocalScopeVariableAccess, VariableRead { override LocalScopeVariableRead getANextRead() { result = VariableRead.super.getANextRead() } - override LocalScopeVariableRead getAReachableRead() { + deprecated override LocalScopeVariableRead getAReachableRead() { result = VariableRead.super.getAReachableRead() } } @@ -242,7 +244,7 @@ class ParameterAccess extends LocalScopeVariableAccess, @parameter_access_expr { class ParameterRead extends ParameterAccess, LocalScopeVariableRead { override ParameterRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() } - override ParameterRead getAReachableRead() { + deprecated override ParameterRead getAReachableRead() { result = LocalScopeVariableRead.super.getAReachableRead() } } @@ -297,7 +299,7 @@ class LocalVariableAccess extends LocalScopeVariableAccess, @local_variable_acce class LocalVariableRead extends LocalVariableAccess, LocalScopeVariableRead { override LocalVariableRead getANextRead() { result = LocalScopeVariableRead.super.getANextRead() } - override LocalVariableRead getAReachableRead() { + deprecated override LocalVariableRead getAReachableRead() { result = LocalScopeVariableRead.super.getAReachableRead() } } @@ -442,7 +444,9 @@ class PropertyAccess extends AssignableMemberAccess, PropertyAccessExpr { class PropertyRead extends PropertyAccess, AssignableRead { override PropertyRead getANextRead() { result = AssignableRead.super.getANextRead() } - override PropertyRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() } + deprecated override PropertyRead getAReachableRead() { + result = AssignableRead.super.getAReachableRead() + } } /** @@ -581,7 +585,9 @@ class IndexerAccess extends AssignableMemberAccess, ElementAccess, IndexerAccess class IndexerRead extends IndexerAccess, ElementRead { override IndexerRead getANextRead() { result = ElementRead.super.getANextRead() } - override IndexerRead getAReachableRead() { result = ElementRead.super.getAReachableRead() } + deprecated override IndexerRead getAReachableRead() { + result = ElementRead.super.getAReachableRead() + } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll index 54fa60e03f2..373194ef366 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/Format.qll @@ -71,6 +71,20 @@ class FormatMethod extends Method { } } +pragma[nomagic] +private predicate parameterReadPostDominatesEntry(ParameterRead pr) { + pr.getAControlFlowNode().postDominates(pr.getEnclosingCallable().getEntryPoint()) and + getParameterType(pr.getTarget()) instanceof ObjectType +} + +pragma[nomagic] +private predicate alwaysPassedToFormatItemParameter(ParameterRead pr) { + pr = any(StringFormatItemParameter other).getAnAssignedArgument() and + parameterReadPostDominatesEntry(pr) + or + alwaysPassedToFormatItemParameter(pr.getANextRead()) +} + /** * A parameter that is used as a format item for `string.Format()`. Either a * format item parameter of `string.Format()`, or a parameter of a method that @@ -85,15 +99,9 @@ class StringFormatItemParameter extends Parameter { ) or // Parameter of a source method that forwards to `string.Format()` - exists( - AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr, - StringFormatItemParameter other - | + exists(AssignableDefinitions::ImplicitParameterDefinition def | def.getParameter() = this and - pr = def.getAReachableRead() and - pr.getAControlFlowNode().postDominates(this.getCallable().getEntryPoint()) and - other.getAnAssignedArgument() = pr and - getParameterType(this) instanceof ObjectType + alwaysPassedToFormatItemParameter(def.getAFirstRead()) ) } } diff --git a/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql b/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql index abb962449b9..3349ee93251 100644 --- a/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql +++ b/csharp/ql/src/API Abuse/DisposeNotCalledOnException.ql @@ -22,12 +22,22 @@ private class DisposeCall extends MethodCall { DisposeCall() { this.getTarget() instanceof DisposeMethod } } -private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - DataFlow::localFlowStep(nodeFrom, nodeTo) and - not exists(AssignableDefinition def, UsingStmt us | - nodeTo.asExpr() = def.getAReachableRead() and +pragma[nomagic] +private predicate isDisposedAccess(AssignableRead ar) { + exists(AssignableDefinition def, UsingStmt us | + ar = def.getAFirstRead() and def.getTargetAccess() = us.getAVariableDeclExpr().getAccess() ) + or + exists(AssignableRead mid | + isDisposedAccess(mid) and + ar = mid.getANextRead() + ) +} + +private predicate localFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + DataFlow::localFlowStep(nodeFrom, nodeTo) and + not isDisposedAccess(nodeTo.asExpr()) } private predicate reachesDisposeCall(DisposeCall disposeCall, DataFlow::Node node) { diff --git a/csharp/ql/src/Useless code/DefaultToStringQuery.qll b/csharp/ql/src/Useless code/DefaultToStringQuery.qll index 9ba8be009da..9185756b0a9 100644 --- a/csharp/ql/src/Useless code/DefaultToStringQuery.qll +++ b/csharp/ql/src/Useless code/DefaultToStringQuery.qll @@ -6,6 +6,7 @@ import semmle.code.csharp.frameworks.System * Holds if expression `e`, of type `t`, invokes `ToString()` either explicitly * or implicitly. */ +pragma[nomagic] predicate invokesToString(Expr e, ValueOrRefType t) { // Explicit invocation exists(MethodCall mc | mc.getQualifier() = e | @@ -20,20 +21,24 @@ predicate invokesToString(Expr e, ValueOrRefType t) { // Implicit invocation via forwarder method t = e.stripCasts().getType() and not t instanceof StringType and - exists(Parameter p | - alwaysInvokesToStringOnParameter(p) and + exists(AssignableDefinitions::ImplicitParameterDefinition def, Parameter p | + def.getParameter() = p and + alwaysInvokesToString(def.getAFirstRead()) and e = p.getAnAssignedArgument() ) } -pragma[noinline] -private predicate alwaysInvokesToStringOnParameter(Parameter p) { - exists(AssignableDefinitions::ImplicitParameterDefinition def, ParameterRead pr | - def.getParameter() = p and - pr = def.getAReachableRead() and - pr.getAControlFlowNode().postDominates(p.getCallable().getEntryPoint()) and - invokesToString(pr, _) - ) +pragma[nomagic] +private predicate parameterReadPostDominatesEntry(ParameterRead pr) { + pr.getAControlFlowNode().postDominates(pr.getEnclosingCallable().getEntryPoint()) +} + +pragma[nomagic] +private predicate alwaysInvokesToString(ParameterRead pr) { + parameterReadPostDominatesEntry(pr) and + invokesToString(pr, _) + or + alwaysInvokesToString(pr.getANextRead()) } /** From 7bfb3497eb7f2ede685152b45a8eef3f9a1d7b28 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 12 Oct 2022 14:27:36 +0200 Subject: [PATCH 150/164] Ruby: change note --- ruby/ql/src/change-notes/2022-10-12-rails-render-file.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ruby/ql/src/change-notes/2022-10-12-rails-render-file.md diff --git a/ruby/ql/src/change-notes/2022-10-12-rails-render-file.md b/ruby/ql/src/change-notes/2022-10-12-rails-render-file.md new file mode 100644 index 00000000000..2801a999279 --- /dev/null +++ b/ruby/ql/src/change-notes/2022-10-12-rails-render-file.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `rb/path-injection` query now treats the `file:` argument of the Rails `render` method as a sink. From d42c74f1a402db18cb9e49f4b6786c3eb18785a8 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 11 Oct 2022 13:49:23 +0200 Subject: [PATCH 151/164] C#: Include CIL SSA definitions in `DataFlow::Node` --- csharp/ql/lib/semmle/code/cil/DataFlow.qll | 22 ++-- csharp/ql/lib/semmle/code/cil/Method.qll | 2 +- csharp/ql/lib/semmle/code/cil/Ssa.qll | 9 +- csharp/ql/lib/semmle/code/cil/Stubs.qll | 19 +-- .../lib/semmle/code/cil/internal/SsaImpl.qll | 5 +- .../semmle/code/csharp/commons/Disposal.qll | 14 ++- .../dataflow/internal/DataFlowPrivate.qll | 113 ++++++++++++++++-- .../dataflow/internal/DataFlowPublic.qll | 2 +- .../internal/TaintTrackingPrivate.qll | 9 +- 9 files changed, 148 insertions(+), 47 deletions(-) diff --git a/csharp/ql/lib/semmle/code/cil/DataFlow.qll b/csharp/ql/lib/semmle/code/cil/DataFlow.qll index 55f8eb89432..9057cccf49b 100644 --- a/csharp/ql/lib/semmle/code/cil/DataFlow.qll +++ b/csharp/ql/lib/semmle/code/cil/DataFlow.qll @@ -20,16 +20,18 @@ class DataFlowNode extends @cil_dataflow_node { * Holds if this node flows to `sink` in one step. * `tt` is the tainting that occurs during this step. */ - predicate getALocalFlowSucc(DataFlowNode sink, TaintType tt) { + deprecated predicate getALocalFlowSucc(DataFlowNode sink, TaintType tt) { localExactStep(this, sink) and tt = TExactValue() or localTaintStep(this, sink) and tt = TTaintedValue() } - private predicate flowsToStep(DataFlowNode sink) { this.getALocalFlowSucc(sink, TExactValue()) } + deprecated private predicate flowsToStep(DataFlowNode sink) { + this.getALocalFlowSucc(sink, TExactValue()) + } /** Holds if this node flows to `sink` in zero or more steps. */ - predicate flowsTo(DataFlowNode sink) { this.flowsToStep*(sink) } + deprecated predicate flowsTo(DataFlowNode sink) { this.flowsToStep*(sink) } /** Gets the method that contains this dataflow node. */ Method getMethod() { none() } @@ -38,12 +40,12 @@ class DataFlowNode extends @cil_dataflow_node { Location getLocation() { none() } } -private newtype TTaintType = +deprecated private newtype TTaintType = TExactValue() or TTaintedValue() /** Describes how data is tainted. */ -class TaintType extends TTaintType { +deprecated class TaintType extends TTaintType { string toString() { this = TExactValue() and result = "exact" or @@ -52,12 +54,12 @@ class TaintType extends TTaintType { } /** A taint type where the data is untainted. */ -class Untainted extends TaintType, TExactValue { } +deprecated class Untainted extends TaintType, TExactValue { } /** A taint type where the data is tainted. */ -class Tainted extends TaintType, TTaintedValue { } +deprecated class Tainted extends TaintType, TTaintedValue { } -private predicate localFlowPhiInput(DataFlowNode input, Ssa::PhiNode phi) { +deprecated private predicate localFlowPhiInput(DataFlowNode input, Ssa::PhiNode phi) { exists(Ssa::Definition def, BasicBlock bb, int i | phi.hasLastInputRef(def, bb, i) | def.definesAt(_, bb, i) and input = def.getVariableUpdate().getSource() @@ -76,7 +78,7 @@ private predicate localFlowPhiInput(DataFlowNode input, Ssa::PhiNode phi) { ) } -private predicate localExactStep(DataFlowNode src, DataFlowNode sink) { +deprecated private predicate localExactStep(DataFlowNode src, DataFlowNode sink) { src = sink.(Opcodes::Dup).getAnOperand() or exists(Ssa::Definition def, VariableUpdate vu | @@ -103,7 +105,7 @@ private predicate localExactStep(DataFlowNode src, DataFlowNode sink) { src = sink.(ConditionalBranch).getAnOperand() } -private predicate localTaintStep(DataFlowNode src, DataFlowNode sink) { +deprecated private predicate localTaintStep(DataFlowNode src, DataFlowNode sink) { src = sink.(BinaryArithmeticExpr).getAnOperand() or src = sink.(Opcodes::Neg).getOperand() or src = sink.(UnaryBitwiseOperation).getOperand() diff --git a/csharp/ql/lib/semmle/code/cil/Method.qll b/csharp/ql/lib/semmle/code/cil/Method.qll index f4f65bbaca1..da1c46b5dfd 100644 --- a/csharp/ql/lib/semmle/code/cil/Method.qll +++ b/csharp/ql/lib/semmle/code/cil/Method.qll @@ -270,7 +270,7 @@ class Setter extends Accessor { */ class TrivialSetter extends Method { TrivialSetter() { - exists(MethodImplementation impl | impl = this.getImplementation() | + exists(MethodImplementation impl | impl = this.getAnImplementation() | impl.getInstruction(0) instanceof ThisAccess and impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and impl.getInstruction(2) instanceof FieldWriteAccess diff --git a/csharp/ql/lib/semmle/code/cil/Ssa.qll b/csharp/ql/lib/semmle/code/cil/Ssa.qll index 50338d3284d..ec419c1773a 100644 --- a/csharp/ql/lib/semmle/code/cil/Ssa.qll +++ b/csharp/ql/lib/semmle/code/cil/Ssa.qll @@ -24,10 +24,10 @@ module Ssa { } /** Gets a first read of this SSA definition. */ - final ReadAccess getAFirstRead() { result = SsaImpl::getAFirstRead(this) } + deprecated final ReadAccess getAFirstRead() { result = SsaImpl::getAFirstRead(this) } /** Holds if `first` and `second` are adjacent reads of this SSA definition. */ - final predicate hasAdjacentReads(ReadAccess first, ReadAccess second) { + deprecated final predicate hasAdjacentReads(ReadAccess first, ReadAccess second) { SsaImpl::hasAdjacentReads(this, first, second) } @@ -58,8 +58,9 @@ module Ssa { * index `i` in basic block `bb` can reach this phi node without going through * other references. */ - final predicate hasLastInputRef(Definition def, BasicBlock bb, int i) { - SsaImpl::hasLastInputRef(this, def, bb, i) + deprecated final predicate hasLastInputRef(Definition def, BasicBlock bb, int i) { + SsaImpl::lastRefRedef(def, bb, i, this) and + def = SsaImpl::getAPhiInput(this) } } } diff --git a/csharp/ql/lib/semmle/code/cil/Stubs.qll b/csharp/ql/lib/semmle/code/cil/Stubs.qll index 692b7750f1f..afe95d3ae77 100644 --- a/csharp/ql/lib/semmle/code/cil/Stubs.qll +++ b/csharp/ql/lib/semmle/code/cil/Stubs.qll @@ -29,14 +29,17 @@ private module Cached { cached predicate bestImplementation(MethodImplementation mi) { - not assemblyIsStubImpl(mi.getLocation()) and - not exists(MethodImplementation better | mi.getMethod() = better.getMethod() | - mi.getNumberOfInstructions() < better.getNumberOfInstructions() - or - mi.getNumberOfInstructions() = better.getNumberOfInstructions() and - mi.getLocation().getFile().toString() > better.getLocation().getFile().toString() - ) and - exists(mi.getAnInstruction()) + exists(Assembly asm | + asm = mi.getLocation() and + (assemblyIsStubImpl(asm) implies asm.getFile().extractedQlTest()) and + not exists(MethodImplementation better | mi.getMethod() = better.getMethod() | + mi.getNumberOfInstructions() < better.getNumberOfInstructions() + or + mi.getNumberOfInstructions() = better.getNumberOfInstructions() and + asm.getFile().toString() > better.getLocation().getFile().toString() + ) and + exists(mi.getAnInstruction()) + ) } } diff --git a/csharp/ql/lib/semmle/code/cil/internal/SsaImpl.qll b/csharp/ql/lib/semmle/code/cil/internal/SsaImpl.qll index 9ca724cb08d..683ee6268aa 100644 --- a/csharp/ql/lib/semmle/code/cil/internal/SsaImpl.qll +++ b/csharp/ql/lib/semmle/code/cil/internal/SsaImpl.qll @@ -68,9 +68,8 @@ private module Cached { Definition getAPhiInput(PhiNode phi) { phiHasInputFromBlock(phi, result, _) } cached - predicate hasLastInputRef(Definition phi, Definition def, BasicBlock bb, int i) { - lastRefRedef(def, bb, i, phi) and - def = getAPhiInput(phi) + predicate lastRefBeforeRedef(Definition def, BasicBlock bb, int i, Definition next) { + lastRefRedef(def, bb, i, next) } } diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Disposal.qll b/csharp/ql/lib/semmle/code/csharp/commons/Disposal.qll index 090599a60a7..f3c1c7a3c78 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Disposal.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Disposal.qll @@ -11,15 +11,19 @@ private predicate isDisposeMethod(DotNet::Callable method) { method.getNumberOfParameters() = 0 } -private predicate cilVariableReadFlowsTo(CIL::Variable variable, CIL::DataFlowNode n) { - n = variable.getARead() +private predicate cilVariableReadFlowsToNode(CIL::Variable variable, DataFlow::Node n) { + n.asExpr() = variable.getARead() or - exists(CIL::DataFlowNode mid | - cilVariableReadFlowsTo(variable, mid) and - mid.getALocalFlowSucc(n, any(CIL::Untainted u)) + exists(DataFlow::Node mid | + cilVariableReadFlowsToNode(variable, mid) and + DataFlow::localFlowStep(mid, n) ) } +private predicate cilVariableReadFlowsTo(CIL::Variable variable, CIL::DataFlowNode n) { + cilVariableReadFlowsToNode(variable, DataFlow::exprNode(n)) +} + private predicate disposedCilVariable(CIL::Variable variable) { // `variable` is the `this` parameter on a dispose method. isDisposeMethod(variable.(CIL::ThisParameter).getMethod()) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 5d455e6b387..dbbae7a1eea 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -17,6 +17,7 @@ private import semmle.code.csharp.frameworks.EntityFramework private import semmle.code.csharp.frameworks.NHibernate private import semmle.code.csharp.frameworks.system.Collections private import semmle.code.csharp.frameworks.system.threading.Tasks +private import semmle.code.cil.Ssa::Ssa as CilSsa /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(NodeImpl n) { result = n.getEnclosingCallableImpl() } @@ -177,6 +178,12 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No ) } +/** Gets the CIL data-flow node for `node`, if any. */ +CIL::DataFlowNode asCilDataFlowNode(Node node) { + result = node.asParameter() or + result = node.asExpr() +} + /** Provides predicates related to local data flow. */ module LocalFlow { private class LocalExprStepConfiguration extends ControlFlowReachabilityConfiguration { @@ -281,15 +288,6 @@ module LocalFlow { } } - private CIL::DataFlowNode asCilDataFlowNode(Node node) { - result = node.asParameter() or - result = node.asExpr() - } - - private predicate localFlowStepCil(Node nodeFrom, Node nodeTo) { - asCilDataFlowNode(nodeFrom).getALocalFlowSucc(asCilDataFlowNode(nodeTo), any(CIL::Untainted t)) - } - /** * An uncertain SSA definition. Either an uncertain explicit definition or an * uncertain qualifier definition. @@ -341,7 +339,7 @@ module LocalFlow { /** * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving - * SSA definition `def. + * SSA definition `def`. */ predicate localSsaFlowStep(Ssa::Definition def, Node nodeFrom, Node nodeTo) { // Flow from SSA definition/parameter to first read @@ -386,6 +384,76 @@ module LocalFlow { ) } + private module CilFlow { + private import semmle.code.cil.internal.SsaImpl as CilSsaImpl + + /** + * Holds if `nodeFrom` is a last node referencing SSA definition `def`, which + * can reach `next`. + */ + private predicate localFlowCilSsaInput( + Node nodeFrom, CilSsa::Definition def, CilSsa::Definition next + ) { + exists(CIL::BasicBlock bb, int i | CilSsaImpl::lastRefBeforeRedef(def, bb, i, next) | + def.definesAt(_, bb, i) and + def = nodeFrom.(CilSsaDefinitionNode).getDefinition() + or + nodeFrom = TCilExprNode(bb.getNode(i).(CIL::ReadAccess)) + ) + } + + /** + * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving + * CIL SSA definition `def`. + */ + private predicate localCilSsaFlowStep(CilSsa::Definition def, Node nodeFrom, Node nodeTo) { + // Flow into SSA definition + exists(CIL::VariableUpdate vu | + vu = def.getVariableUpdate() and + vu.getSource() = asCilDataFlowNode(nodeFrom) and + def = nodeTo.(CilSsaDefinitionNode).getDefinition() + ) + or + // Flow from SSA definition to first read + def = nodeFrom.(CilSsaDefinitionNode).getDefinition() and + nodeTo = TCilExprNode(CilSsaImpl::getAFirstRead(def)) + or + // Flow from read to next read + exists(CIL::ReadAccess readFrom, CIL::ReadAccess readTo | + CilSsaImpl::hasAdjacentReads(def, readFrom, readTo) and + nodeTo = TCilExprNode(readTo) and + nodeFrom = TCilExprNode(readFrom) + ) + or + // Flow into phi node + exists(CilSsa::PhiNode phi | + localFlowCilSsaInput(nodeFrom, def, phi) and + phi = nodeTo.(CilSsaDefinitionNode).getDefinition() and + def = CilSsaImpl::getAPhiInput(phi) + ) + } + + private predicate localExactStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) { + src = sink.(CIL::Opcodes::Dup).getAnOperand() + or + src = sink.(CIL::Conversion).getExpr() + or + src = sink.(CIL::WriteAccess).getExpr() + or + src = sink.(CIL::Method).getAnImplementation().getAnInstruction().(CIL::Return) + or + src = sink.(CIL::Return).getExpr() + or + src = sink.(CIL::ConditionalBranch).getAnOperand() + } + + predicate localFlowStepCil(Node nodeFrom, Node nodeTo) { + localExactStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo)) + or + localCilSsaFlowStep(_, nodeFrom, nodeTo) + } + } + predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) { exists(Ssa::Definition def | localSsaFlowStep(def, nodeFrom, nodeTo) and @@ -398,7 +466,7 @@ module LocalFlow { or ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo) or - localFlowStepCil(nodeFrom, nodeTo) + CilFlow::localFlowStepCil(nodeFrom, nodeTo) } /** @@ -719,6 +787,7 @@ private module Cached { cfn.getElement() instanceof Expr } or TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or + TCilSsaDefinitionNode(CilSsa::Definition def) or TSsaDefinitionNode(Ssa::Definition def) { // Handled by `TExplicitParameterNode` below not def.(Ssa::ExplicitDefinition).getADefinition() instanceof @@ -867,6 +936,28 @@ predicate nodeIsHidden(Node n) { n.asExpr() = any(WithExpr we).getInitializer() } +/** A CIL SSA definition, viewed as a node in a data flow graph. */ +class CilSsaDefinitionNode extends NodeImpl, TCilSsaDefinitionNode { + CilSsa::Definition def; + + CilSsaDefinitionNode() { this = TCilSsaDefinitionNode(def) } + + /** Gets the underlying SSA definition. */ + CilSsa::Definition getDefinition() { result = def } + + override DataFlowCallable getEnclosingCallableImpl() { + result.asCallable() = def.getBasicBlock().getFirstNode().getImplementation().getMethod() + } + + override CIL::Type getTypeImpl() { result = def.getSourceVariable().getType() } + + override ControlFlow::Node getControlFlowNodeImpl() { none() } + + override Location getLocationImpl() { result = def.getBasicBlock().getLocation() } + + override string toStringImpl() { result = def.toString() } +} + /** An SSA definition, viewed as a node in a data flow graph. */ class SsaDefinitionNode extends NodeImpl, TSsaDefinitionNode { Ssa::Definition def; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll index a70bffabfdb..f6520147e19 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPublic.qll @@ -161,7 +161,7 @@ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } * local (intra-procedural) steps. */ pragma[inline] -predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } +predicate localExprFlow(DotNet::Expr e1, DotNet::Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } /** * A data flow node that jumps between callables. This can be extended in diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll index ec29d704248..4f823907f94 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/TaintTrackingPrivate.qll @@ -26,13 +26,14 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() } bindingset[node] predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { none() } -private CIL::DataFlowNode asCilDataFlowNode(DataFlow::Node node) { - result = node.asParameter() or - result = node.asExpr() +private predicate localCilTaintStep(CIL::DataFlowNode src, CIL::DataFlowNode sink) { + src = sink.(CIL::BinaryArithmeticExpr).getAnOperand() or + src = sink.(CIL::Opcodes::Neg).getOperand() or + src = sink.(CIL::UnaryBitwiseOperation).getOperand() } private predicate localTaintStepCil(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - asCilDataFlowNode(nodeFrom).getALocalFlowSucc(asCilDataFlowNode(nodeTo), any(CIL::Tainted t)) + localCilTaintStep(asCilDataFlowNode(nodeFrom), asCilDataFlowNode(nodeTo)) } private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityConfiguration { From af12eedb320f7b378e27e649665ee84708823f39 Mon Sep 17 00:00:00 2001 From: Sam Browning Date: Wed, 12 Oct 2022 08:46:42 -0400 Subject: [PATCH 152/164] Add clarity to CodeQL extension installation --- .../setting-up-codeql-in-visual-studio-code.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst index 5592992373b..f120518bd3f 100644 --- a/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst +++ b/docs/codeql/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code.rst @@ -21,7 +21,7 @@ You can install the CodeQL extension using any of the normal methods for install * Go to the `Visual Studio Code Marketplace `__ in your browser and click **Install**. * In the Extensions view (**Ctrl+Shift+X** or **Cmd+Shift+X**), search for ``CodeQL``, then select **Install**. -* Download the `CodeQL VSIX file `__. Then, in the Extensions view, click **More actions** > **Install from VSIX**, and select the CodeQL VSIX file. +* Download the `CodeQL VSIX file `__. Then, in the Extensions view, click the ellipsis representing the **Views and More Actions...** menu, select **Install from VSIX**, then select the CodeQL VSIX file. Configuring access to the CodeQL CLI ------------------------------------ From cfb9277cd79c836189ae465d3a98b51079de42be Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Wed, 12 Oct 2022 16:11:45 +0100 Subject: [PATCH 153/164] C++: use explicit `this` --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 3c7368ff1a0..e5f4eee3b51 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -229,7 +229,7 @@ class Node extends TIRDataFlowNode { Expr asIndirectArgument() { result = this.asIndirectArgument(_) } /** Gets the positional parameter corresponding to this node, if any. */ - Parameter asParameter() { result = asParameter(0) } + Parameter asParameter() { result = this.asParameter(0) } /** * Gets the uninitialized local variable corresponding to this node, if From 66b3fe34252269cd5992c753d33b507f0d496978 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Wed, 12 Oct 2022 19:57:01 +0200 Subject: [PATCH 154/164] add case-when expressions as a sink to rb/polynomial-redos --- .../security/regexp/PolynomialReDoSCustomizations.qll | 8 ++++++++ .../cwe-1333-polynomial-redos/PolynomialReDoS.expected | 3 +++ .../security/cwe-1333-polynomial-redos/PolynomialReDoS.rb | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll index 5e870ac4fd3..7df813d2307 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll @@ -106,6 +106,14 @@ module PolynomialReDoS { regexp.asExpr() = call.getReceiver() and this.asExpr() = call.getArgument(0) ) + or + // a case-when statement + exists(CfgNodes::ExprNodes::CaseExprCfgNode caseWhen | + matchNode.asExpr() = caseWhen and + this.asExpr() = caseWhen.getValue() and + regexp.asExpr() = + caseWhen.getBranch(_).(CfgNodes::ExprNodes::WhenClauseCfgNode).getPattern(_) + ) ) ) } diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected index 8c333d612c3..ac39dad54f2 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected @@ -15,6 +15,7 @@ edges | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:22:5:22:8 | name | | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:23:17:23:20 | name | | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:24:18:24:21 | name | +| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:42:10:42:13 | name | | PolynomialReDoS.rb:27:9:27:14 | call to params : | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | PolynomialReDoS.rb:28:5:28:5 | a | | PolynomialReDoS.rb:29:9:29:14 | call to params : | PolynomialReDoS.rb:29:9:29:18 | ...[...] : | @@ -48,6 +49,7 @@ nodes | PolynomialReDoS.rb:31:9:31:14 | call to params : | semmle.label | call to params : | | PolynomialReDoS.rb:31:9:31:18 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:32:5:32:5 | c | semmle.label | c | +| PolynomialReDoS.rb:42:10:42:13 | name | semmle.label | name | subpaths #select | PolynomialReDoS.rb:10:5:10:17 | ... =~ ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:10:5:10:8 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | @@ -68,3 +70,4 @@ subpaths | PolynomialReDoS.rb:28:5:28:21 | call to gsub! | PolynomialReDoS.rb:27:9:27:14 | call to params : | PolynomialReDoS.rb:28:5:28:5 | a | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:27:9:27:14 | call to params | user-provided value | | PolynomialReDoS.rb:30:5:30:18 | call to slice! | PolynomialReDoS.rb:29:9:29:14 | call to params : | PolynomialReDoS.rb:30:5:30:5 | b | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:29:9:29:14 | call to params | user-provided value | | PolynomialReDoS.rb:32:5:32:20 | call to sub! | PolynomialReDoS.rb:31:9:31:14 | call to params : | PolynomialReDoS.rb:32:5:32:5 | c | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:31:9:31:14 | call to params | user-provided value | +| PolynomialReDoS.rb:42:5:45:7 | case ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:42:10:42:13 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb index 55db9555584..47fd1560fd6 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb @@ -38,5 +38,10 @@ class FooController < ActionController::Base # GOOD - regex does not suffer from polynomial backtracking (regression test) params[:foo] =~ /\A[bc].*\Z/ + + case name # NOT GOOD + when regex + puts "foo" + end end end From 370da943dc2b7e666d411934601f0f47fe807000 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:55:58 -0400 Subject: [PATCH 155/164] spelling: abcdefghijklmnopqrstuvwxyz Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll | 2 +- .../ql/lib/semmle/javascript/security/regexp/NfaUtils.qll | 2 +- python/ql/lib/semmle/python/security/regexp/NfaUtils.qll | 2 +- ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll index 5112bdad11e..b6ad3696dbf 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll @@ -334,7 +334,7 @@ private module CharacterClasses { ) } - private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } + private string lowercaseLetter() { result = "abcdefghijklmnopqrstuvwxyz".charAt(_) } private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll index 5112bdad11e..b6ad3696dbf 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll @@ -334,7 +334,7 @@ private module CharacterClasses { ) } - private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } + private string lowercaseLetter() { result = "abcdefghijklmnopqrstuvwxyz".charAt(_) } private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll index 5112bdad11e..b6ad3696dbf 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll @@ -334,7 +334,7 @@ private module CharacterClasses { ) } - private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } + private string lowercaseLetter() { result = "abcdefghijklmnopqrstuvwxyz".charAt(_) } private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll index 5112bdad11e..b6ad3696dbf 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll @@ -334,7 +334,7 @@ private module CharacterClasses { ) } - private string lowercaseLetter() { result = "abdcefghijklmnopqrstuvwxyz".charAt(_) } + private string lowercaseLetter() { result = "abcdefghijklmnopqrstuvwxyz".charAt(_) } private string upperCaseLetter() { result = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(_) } From 98b317d1a578530cca7a03db07e812c6b122980d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:43:08 -0400 Subject: [PATCH 156/164] spelling: escape Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll | 2 +- .../ql/lib/semmle/python/security/regexp/NfaUtilsSpecific.qll | 2 +- ruby/ql/lib/codeql/ruby/security/regexp/NfaUtilsSpecific.qll | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll index 33441bfaba3..ea96d1ad983 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll @@ -5,7 +5,7 @@ import javascript /** - * Holds if `term` is an ecape class representing e.g. `\d`. + * Holds if `term` is an escape class representing e.g. `\d`. * `clazz` is which character class it represents, e.g. "d" for `\d`. */ predicate isEscapeClass(RegExpTerm term, string clazz) { diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtilsSpecific.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtilsSpecific.qll index 863c8ecd8ea..70ed5bcedad 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtilsSpecific.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtilsSpecific.qll @@ -6,7 +6,7 @@ import python import semmle.python.RegexTreeView /** - * Holds if `term` is an ecape class representing e.g. `\d`. + * Holds if `term` is an escape class representing e.g. `\d`. * `clazz` is which character class it represents, e.g. "d" for `\d`. */ predicate isEscapeClass(RegExpTerm term, string clazz) { diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtilsSpecific.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtilsSpecific.qll index 4a43b838dee..821586b1f90 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtilsSpecific.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtilsSpecific.qll @@ -7,7 +7,7 @@ import codeql.Locations private import codeql.ruby.ast.Literal as Ast /** - * Holds if `term` is an ecape class representing e.g. `\d`. + * Holds if `term` is an escape class representing e.g. `\d`. * `clazz` is which character class it represents, e.g. "d" for `\d`. */ predicate isEscapeClass(RegExpTerm term, string clazz) { From c7ae0728f3cce637ca0d97db74e7037518774d94 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:44:40 -0400 Subject: [PATCH 157/164] spelling: javascript Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../semmle/javascript/security/regexp/NfaUtilsSpecific.qll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll index ea96d1ad983..b5abec6667a 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtilsSpecific.qll @@ -20,13 +20,13 @@ predicate isPossessive(RegExpQuantifier term) { none() } /** * Holds if the regex that `term` is part of is used in a way that ignores any leading prefix of the input it's matched against. - * Not yet implemented for Javascript. + * Not yet implemented for JavaScript. */ predicate matchesAnyPrefix(RegExpTerm term) { any() } /** * Holds if the regex that `term` is part of is used in a way that ignores any trailing suffix of the input it's matched against. - * Not yet implemented for Javascript. + * Not yet implemented for JavaScript. */ predicate matchesAnySuffix(RegExpTerm term) { any() } From adb8860b9b96d780b7c5ae07091b8ef622ad4119 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:43:09 -0400 Subject: [PATCH 158/164] spelling: pattern Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .../lib/semmle/code/java/security/regexp/NfaUtils.qll | 11 ++++++----- .../semmle/javascript/security/regexp/NfaUtils.qll | 11 ++++++----- .../ql/lib/semmle/python/security/regexp/NfaUtils.qll | 11 ++++++----- ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll | 11 ++++++----- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll index b6ad3696dbf..5f3a7ad23d9 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll @@ -59,8 +59,8 @@ predicate matchesEpsilon(RegExpTerm t) { /** * A lookahead/lookbehind that matches the empty string. */ -class EmptyPositiveSubPatttern extends RegExpSubPattern { - EmptyPositiveSubPatttern() { +class EmptyPositiveSubPattern extends RegExpSubPattern { + EmptyPositiveSubPattern() { ( this instanceof RegExpPositiveLookahead or @@ -70,6 +70,9 @@ class EmptyPositiveSubPatttern extends RegExpSubPattern { } } +/** DEPRECATED: Use `EmptyPositiveSubPattern` instead. */ +deprecated class EmptyPositiveSubPatttern = EmptyPositiveSubPattern; + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -697,9 +700,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) or - exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | - lbl = Epsilon() and q2 = after(empty) - ) + exists(EmptyPositiveSubPattern empty | q1 = before(empty) | lbl = Epsilon() and q2 = after(empty)) } /** diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll index b6ad3696dbf..5f3a7ad23d9 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll @@ -59,8 +59,8 @@ predicate matchesEpsilon(RegExpTerm t) { /** * A lookahead/lookbehind that matches the empty string. */ -class EmptyPositiveSubPatttern extends RegExpSubPattern { - EmptyPositiveSubPatttern() { +class EmptyPositiveSubPattern extends RegExpSubPattern { + EmptyPositiveSubPattern() { ( this instanceof RegExpPositiveLookahead or @@ -70,6 +70,9 @@ class EmptyPositiveSubPatttern extends RegExpSubPattern { } } +/** DEPRECATED: Use `EmptyPositiveSubPattern` instead. */ +deprecated class EmptyPositiveSubPatttern = EmptyPositiveSubPattern; + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -697,9 +700,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) or - exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | - lbl = Epsilon() and q2 = after(empty) - ) + exists(EmptyPositiveSubPattern empty | q1 = before(empty) | lbl = Epsilon() and q2 = after(empty)) } /** diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll index b6ad3696dbf..5f3a7ad23d9 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll @@ -59,8 +59,8 @@ predicate matchesEpsilon(RegExpTerm t) { /** * A lookahead/lookbehind that matches the empty string. */ -class EmptyPositiveSubPatttern extends RegExpSubPattern { - EmptyPositiveSubPatttern() { +class EmptyPositiveSubPattern extends RegExpSubPattern { + EmptyPositiveSubPattern() { ( this instanceof RegExpPositiveLookahead or @@ -70,6 +70,9 @@ class EmptyPositiveSubPatttern extends RegExpSubPattern { } } +/** DEPRECATED: Use `EmptyPositiveSubPattern` instead. */ +deprecated class EmptyPositiveSubPatttern = EmptyPositiveSubPattern; + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -697,9 +700,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) or - exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | - lbl = Epsilon() and q2 = after(empty) - ) + exists(EmptyPositiveSubPattern empty | q1 = before(empty) | lbl = Epsilon() and q2 = after(empty)) } /** diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll index b6ad3696dbf..5f3a7ad23d9 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll @@ -59,8 +59,8 @@ predicate matchesEpsilon(RegExpTerm t) { /** * A lookahead/lookbehind that matches the empty string. */ -class EmptyPositiveSubPatttern extends RegExpSubPattern { - EmptyPositiveSubPatttern() { +class EmptyPositiveSubPattern extends RegExpSubPattern { + EmptyPositiveSubPattern() { ( this instanceof RegExpPositiveLookahead or @@ -70,6 +70,9 @@ class EmptyPositiveSubPatttern extends RegExpSubPattern { } } +/** DEPRECATED: Use `EmptyPositiveSubPattern` instead. */ +deprecated class EmptyPositiveSubPatttern = EmptyPositiveSubPattern; + /** * A branch in a disjunction that is the root node in a literal, or a literal * whose root node is not a disjunction. @@ -697,9 +700,7 @@ predicate delta(State q1, EdgeLabel lbl, State q2) { lbl = Epsilon() and q2 = Accept(getRoot(dollar)) ) or - exists(EmptyPositiveSubPatttern empty | q1 = before(empty) | - lbl = Epsilon() and q2 = after(empty) - ) + exists(EmptyPositiveSubPattern empty | q1 = before(empty) | lbl = Epsilon() and q2 = after(empty)) } /** From bb1ce8973a1f98a13945c433c3f4f1ab3d401d17 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:43:09 -0400 Subject: [PATCH 159/164] spelling: repeatable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll | 2 +- .../ql/lib/semmle/javascript/security/regexp/NfaUtils.qll | 2 +- python/ql/lib/semmle/python/security/regexp/NfaUtils.qll | 2 +- ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll index 5f3a7ad23d9..23ca81c49cd 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll @@ -1029,7 +1029,7 @@ module ReDoSPruning { * as the suffix "X" will cause both the regular expressions to be rejected. * * The string `w` is repeated any number of times because it needs to be - * infinitely repeatedable for the attack to work. + * infinitely repeatable for the attack to work. * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll index 5f3a7ad23d9..23ca81c49cd 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll @@ -1029,7 +1029,7 @@ module ReDoSPruning { * as the suffix "X" will cause both the regular expressions to be rejected. * * The string `w` is repeated any number of times because it needs to be - * infinitely repeatedable for the attack to work. + * infinitely repeatable for the attack to work. * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll index 5f3a7ad23d9..23ca81c49cd 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll @@ -1029,7 +1029,7 @@ module ReDoSPruning { * as the suffix "X" will cause both the regular expressions to be rejected. * * The string `w` is repeated any number of times because it needs to be - * infinitely repeatedable for the attack to work. + * infinitely repeatable for the attack to work. * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll index 5f3a7ad23d9..23ca81c49cd 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll @@ -1029,7 +1029,7 @@ module ReDoSPruning { * as the suffix "X" will cause both the regular expressions to be rejected. * * The string `w` is repeated any number of times because it needs to be - * infinitely repeatedable for the attack to work. + * infinitely repeatable for the attack to work. * For the regular expression `/((ab)+)*abab/` the accepting state is not reachable from the fork * using epsilon transitions. But any attempt at repeating `w` will end in a state that accepts all suffixes. */ From 09c8a9876181019bd077371cc602995df48376f9 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:43:10 -0400 Subject: [PATCH 160/164] spelling: representation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll | 2 +- .../ql/lib/semmle/javascript/security/regexp/NfaUtils.qll | 2 +- python/ql/lib/semmle/python/security/regexp/NfaUtils.qll | 2 +- ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll index 23ca81c49cd..a6e4db6764e 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/NfaUtils.qll @@ -136,7 +136,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { } /** - * Gets a string reperesentation of the flags used with the regular expression. + * Gets a string representation of the flags used with the regular expression. * Only the flags that are relevant for the canonicalization are included. */ string getCanonicalizationFlags(RegExpTerm root) { diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll index 23ca81c49cd..a6e4db6764e 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/NfaUtils.qll @@ -136,7 +136,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { } /** - * Gets a string reperesentation of the flags used with the regular expression. + * Gets a string representation of the flags used with the regular expression. * Only the flags that are relevant for the canonicalization are included. */ string getCanonicalizationFlags(RegExpTerm root) { diff --git a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll index 23ca81c49cd..a6e4db6764e 100644 --- a/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll +++ b/python/ql/lib/semmle/python/security/regexp/NfaUtils.qll @@ -136,7 +136,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { } /** - * Gets a string reperesentation of the flags used with the regular expression. + * Gets a string representation of the flags used with the regular expression. * Only the flags that are relevant for the canonicalization are included. */ string getCanonicalizationFlags(RegExpTerm root) { diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll index 23ca81c49cd..a6e4db6764e 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/NfaUtils.qll @@ -136,7 +136,7 @@ private predicate isCanonicalTerm(RelevantRegExpTerm term, string str) { } /** - * Gets a string reperesentation of the flags used with the regular expression. + * Gets a string representation of the flags used with the regular expression. * Only the flags that are relevant for the canonicalization are included. */ string getCanonicalizationFlags(RegExpTerm root) { From c4915b27e7fd91a333890b678b7e4fcd12a89854 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 13 Oct 2022 11:03:08 +0200 Subject: [PATCH 161/164] Dataflow: Add additional annotation. --- .../java/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and From 036724ce8df057f276bf76a075b3a2da7c7cc64a Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Thu, 13 Oct 2022 11:03:30 +0200 Subject: [PATCH 162/164] Dataflow: Sync. --- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../dataflow/internal/DataFlowImplLocal.qll | 26 ++++++++++--------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../ir/dataflow/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../csharp/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../dataflow/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../dataflow/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../dataflow/internal/DataFlowImpl5.qll | 26 ++++++++++--------- .../DataFlowImplForContentDataFlow.qll | 26 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl5.qll | 26 ++++++++++--------- .../java/dataflow/internal/DataFlowImpl6.qll | 26 ++++++++++--------- .../DataFlowImplForOnActivityResult.qll | 26 ++++++++++--------- .../DataFlowImplForSerializability.qll | 26 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl3.qll | 26 ++++++++++--------- .../dataflow/new/internal/DataFlowImpl4.qll | 26 ++++++++++--------- .../ruby/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- .../ruby/dataflow/internal/DataFlowImpl2.qll | 26 ++++++++++--------- .../DataFlowImplForHttpClientLibraries.qll | 26 ++++++++++--------- .../internal/DataFlowImplForPathname.qll | 26 ++++++++++--------- .../internal/DataFlowImplForRegExp.qll | 26 ++++++++++--------- .../swift/dataflow/internal/DataFlowImpl.qll | 26 ++++++++++--------- 36 files changed, 504 insertions(+), 432 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index 9053019a6d0..b5631b26b0b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index 9053019a6d0..b5631b26b0b 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index 9053019a6d0..b5631b26b0b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index 9053019a6d0..b5631b26b0b 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index 9053019a6d0..b5631b26b0b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index 9053019a6d0..b5631b26b0b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index 9053019a6d0..b5631b26b0b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll index 9053019a6d0..b5631b26b0b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index 9053019a6d0..b5631b26b0b 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -838,13 +838,13 @@ private module Stage1 implements StageSig { * by `revFlow`. */ pragma[nomagic] - predicate revFlowIsReadAndStored(Content c, Configuration conf) { + additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { revFlowConsCand(c, conf) and revFlowStore(c, _, _, conf) } pragma[nomagic] - predicate viableReturnPosOutNodeCandFwd1( + additional predicate viableReturnPosOutNodeCandFwd1( DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config ) { fwdFlowReturnPosition(pos, _, config) and @@ -860,7 +860,7 @@ private module Stage1 implements StageSig { } pragma[nomagic] - predicate viableParamArgNodeCandFwd1( + additional predicate viableParamArgNodeCandFwd1( DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config ) { viableParamArgEx(call, p, arg) and @@ -907,7 +907,7 @@ private module Stage1 implements StageSig { ) } - predicate revFlowState(FlowState state, Configuration config) { + additional predicate revFlowState(FlowState state, Configuration config) { exists(NodeEx node | sinkNode(node, state, config) and revFlow(node, _, pragma[only_bind_into](config)) and @@ -999,7 +999,7 @@ private module Stage1 implements StageSig { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and @@ -1260,7 +1260,7 @@ private module MkStage { * argument. */ pragma[nomagic] - predicate fwdFlow( + additional predicate fwdFlow( NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config ) { fwdFlow0(node, state, cc, argAp, ap, config) and @@ -1484,7 +1484,7 @@ private module MkStage { * the access path of the returned value. */ pragma[nomagic] - predicate revFlow( + additional predicate revFlow( NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config ) { revFlow0(node, state, toReturn, returnAp, ap, config) and @@ -1662,7 +1662,7 @@ private module MkStage { ) } - predicate revFlow(NodeEx node, FlowState state, Configuration config) { + additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { revFlow(node, state, _, _, _, config) } @@ -1675,11 +1675,13 @@ private module MkStage { // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } + additional predicate revFlowAlias(NodeEx node, Configuration config) { + revFlow(node, _, _, _, _, config) + } // use an alias as a workaround for bad functionality-induced joins pragma[nomagic] - predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { revFlow(node, state, ap, config) } @@ -1700,7 +1702,7 @@ private module MkStage { ) } - predicate consCand(TypedContent tc, Ap ap, Configuration config) { + additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { revConsCand(tc, ap, config) and validAp(ap, config) } @@ -1742,7 +1744,7 @@ private module MkStage { ) } - predicate stats( + additional predicate stats( boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config ) { fwd = true and From 3a3a5aa17c9b64ecf84ddc8fe006dea3c837cf0c Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Thu, 13 Oct 2022 12:36:07 +0200 Subject: [PATCH 163/164] add case-in as a sink for polynomial-redos --- .../ruby/security/regexp/PolynomialReDoSCustomizations.qll | 6 +++++- .../cwe-1333-polynomial-redos/PolynomialReDoS.expected | 3 +++ .../security/cwe-1333-polynomial-redos/PolynomialReDoS.rb | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll index 7df813d2307..8c05642fc83 100644 --- a/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll +++ b/ruby/ql/lib/codeql/ruby/security/regexp/PolynomialReDoSCustomizations.qll @@ -110,9 +110,13 @@ module PolynomialReDoS { // a case-when statement exists(CfgNodes::ExprNodes::CaseExprCfgNode caseWhen | matchNode.asExpr() = caseWhen and - this.asExpr() = caseWhen.getValue() and + this.asExpr() = caseWhen.getValue() + | regexp.asExpr() = caseWhen.getBranch(_).(CfgNodes::ExprNodes::WhenClauseCfgNode).getPattern(_) + or + regexp.asExpr() = + caseWhen.getBranch(_).(CfgNodes::ExprNodes::InClauseCfgNode).getPattern() ) ) ) diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected index ac39dad54f2..975b3f9ce39 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.expected @@ -16,6 +16,7 @@ edges | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:23:17:23:20 | name | | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:24:18:24:21 | name | | PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:42:10:42:13 | name | +| PolynomialReDoS.rb:4:12:4:24 | ...[...] : | PolynomialReDoS.rb:47:10:47:13 | name | | PolynomialReDoS.rb:27:9:27:14 | call to params : | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | | PolynomialReDoS.rb:27:9:27:18 | ...[...] : | PolynomialReDoS.rb:28:5:28:5 | a | | PolynomialReDoS.rb:29:9:29:14 | call to params : | PolynomialReDoS.rb:29:9:29:18 | ...[...] : | @@ -50,6 +51,7 @@ nodes | PolynomialReDoS.rb:31:9:31:18 | ...[...] : | semmle.label | ...[...] : | | PolynomialReDoS.rb:32:5:32:5 | c | semmle.label | c | | PolynomialReDoS.rb:42:10:42:13 | name | semmle.label | name | +| PolynomialReDoS.rb:47:10:47:13 | name | semmle.label | name | subpaths #select | PolynomialReDoS.rb:10:5:10:17 | ... =~ ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:10:5:10:8 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | @@ -71,3 +73,4 @@ subpaths | PolynomialReDoS.rb:30:5:30:18 | call to slice! | PolynomialReDoS.rb:29:9:29:14 | call to params : | PolynomialReDoS.rb:30:5:30:5 | b | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:29:9:29:14 | call to params | user-provided value | | PolynomialReDoS.rb:32:5:32:20 | call to sub! | PolynomialReDoS.rb:31:9:31:14 | call to params : | PolynomialReDoS.rb:32:5:32:5 | c | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:31:9:31:14 | call to params | user-provided value | | PolynomialReDoS.rb:42:5:45:7 | case ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:42:10:42:13 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:7:19:7:21 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | +| PolynomialReDoS.rb:47:5:50:7 | case ... | PolynomialReDoS.rb:4:12:4:17 | call to params : | PolynomialReDoS.rb:47:10:47:13 | name | This $@ that depends on a $@ may run slow on strings with many repetitions of ' '. | PolynomialReDoS.rb:48:14:48:16 | \\s+ | regular expression | PolynomialReDoS.rb:4:12:4:17 | call to params | user-provided value | diff --git a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb index 47fd1560fd6..0f9ec026d40 100644 --- a/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb +++ b/ruby/ql/test/query-tests/security/cwe-1333-polynomial-redos/PolynomialReDoS.rb @@ -43,5 +43,10 @@ class FooController < ActionController::Base when regex puts "foo" end + + case name # NOT GOOD + in /^\s+|\s+$/ then + puts "foo" + end end end From 16b035600e83eef97940341b34851515c1439b83 Mon Sep 17 00:00:00 2001 From: Arthur Baars Date: Thu, 13 Oct 2022 13:01:06 +0200 Subject: [PATCH 164/164] Ruby: remove warning --- ruby/extractor/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/ruby/extractor/src/main.rs b/ruby/extractor/src/main.rs index ca1039e4e0d..3f69a67d043 100644 --- a/ruby/extractor/src/main.rs +++ b/ruby/extractor/src/main.rs @@ -68,7 +68,6 @@ fn main() -> std::io::Result<()> { .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("ruby_extractor=warn")), ) .init(); - tracing::warn!("Support for Ruby is currently in Beta: https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/"); let num_threads = num_codeql_threads(); tracing::info!( "Using {} {}",