From 9745073024be8d0ec3e1b2213a691c4d5a9026e6 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 6 Sep 2022 14:33:33 +0100 Subject: [PATCH 01/27] C++: Speedup 'cpp/using-expired-stack-address' by avoiding a large negation. --- .../UsingExpiredStackAddress.ql | 51 ++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql b/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql index 663f2e990b5..51d0bc71da7 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/UsingExpiredStackAddress.ql @@ -163,19 +163,46 @@ TGlobalAddress globalAddress(Instruction instr) { result = globalAddress(instr.(PointerOffsetInstruction).getLeft()) } -/** Gets a `StoreInstruction` that may be executed after executing `store`. */ -pragma[inline] -StoreInstruction getAStoreStrictlyAfter(StoreInstruction store) { - exists(IRBlock block, int index1, int index2 | - block.getInstruction(index1) = store and - block.getInstruction(index2) = result and - index2 > index1 +/** + * Gets a first `StoreInstruction` that writes to address `globalAddress` reachable + * from `block`. + */ +StoreInstruction getFirstStore(IRBlock block, TGlobalAddress globalAddress) { + 1 = getStoreRank(result, block, globalAddress) + or + not exists(getStoreRank(_, block, globalAddress)) and + result = getFirstStore(block.getASuccessor(), globalAddress) +} + +/** + * Gets the rank of `store` in block `block` (i.e., a rank of `1` means that it is the + * first `store` to write to `globalAddress`, a rank of `2` means it's the second, etc.) + */ +int getStoreRank(StoreInstruction store, IRBlock block, TGlobalAddress globalAddress) { + blockStoresToAddress(block, _, store, globalAddress) and + store = + rank[result](StoreInstruction anotherStore, int i | + blockStoresToAddress(_, i, anotherStore, globalAddress) + | + anotherStore order by i + ) +} + +/** + * Gets a next subsequent `StoreInstruction` to write to `globalAddress` + * after `store` has done so. + */ +StoreInstruction getANextStoreTo(StoreInstruction store, TGlobalAddress globalAddress) { + exists(IRBlock block, int rnk | + rnk = getStoreRank(store, block, globalAddress) and + rnk + 1 = getStoreRank(result, block, globalAddress) ) or - exists(IRBlock block1, IRBlock block2 | - store.getBlock() = block1 and - result.getBlock() = block2 and - block1.getASuccessor+() = block2 + exists(IRBlock block, int rnk, IRBlock succ | + rnk = getStoreRank(store, block, globalAddress) and + not rnk + 1 = getStoreRank(_, block, globalAddress) and + succ = block.getASuccessor() and + result = getFirstStore(succ, globalAddress) ) } @@ -192,7 +219,7 @@ predicate stackAddressEscapes( stackPointerFlowsToUse(store.getSourceValue(), vai) ) and // Ensure there's no subsequent store that overrides the global address. - not globalAddress = globalAddress(getAStoreStrictlyAfter(store).getDestinationAddress()) + not exists(getANextStoreTo(store, globalAddress)) } predicate blockStoresToAddress( From d6b8f2531213a857855be9189371a7284ba182a8 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 6 Sep 2022 15:22:10 +0100 Subject: [PATCH 02/27] C++: Add more tests. --- .../UsingExpiredStackAddress.expected | 6 ++ .../UsingExpiredStackAddress/test.cpp | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected index 80d09858338..955668b4e7a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/UsingExpiredStackAddress.expected @@ -64,6 +64,10 @@ edges | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | EnterFunction: maybe_deref_p | | test.cpp:210:3:210:9 | Call: call to escape1 | test.cpp:201:5:201:17 | VariableAddress: maybe_deref_p | +| test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:238:3:238:9 | Call: call to escape2 | +| test.cpp:238:3:238:9 | Call: call to escape2 | test.cpp:239:17:239:17 | Load: p | +| test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:267:3:267:9 | Call: call to escape3 | +| test.cpp:267:3:267:9 | Call: call to escape3 | test.cpp:268:17:268:17 | Load: p | #select | test.cpp:15:16:15:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:15:16:15:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | | test.cpp:24:16:24:16 | Load: p | test.cpp:10:3:10:13 | Store: ... = ... | test.cpp:24:16:24:16 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:9:7:9:7 | x | x | test.cpp:10:3:10:13 | Store: ... = ... | here | @@ -90,3 +94,5 @@ edges | test.cpp:180:14:180:19 | Load: * ... | test.cpp:154:3:154:22 | Store: ... = ... | test.cpp:180:14:180:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:133:7:133:8 | b2 | b2 | test.cpp:154:3:154:22 | Store: ... = ... | here | | test.cpp:181:13:181:20 | Load: access to array | test.cpp:155:3:155:21 | Store: ... = ... | test.cpp:181:13:181:20 | Load: access to array | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:155:3:155:21 | Store: ... = ... | here | | test.cpp:182:14:182:19 | Load: * ... | test.cpp:156:3:156:25 | Store: ... = ... | test.cpp:182:14:182:19 | Load: * ... | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:134:7:134:8 | b3 | b3 | test.cpp:156:3:156:25 | Store: ... = ... | here | +| test.cpp:239:17:239:17 | Load: p | test.cpp:234:3:234:13 | Store: ... = ... | test.cpp:239:17:239:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:232:7:232:7 | x | x | test.cpp:234:3:234:13 | Store: ... = ... | here | +| test.cpp:268:17:268:17 | Load: p | test.cpp:263:3:263:13 | Store: ... = ... | test.cpp:268:17:268:17 | Load: p | Stack variable $@ escapes $@ and is used after it has expired. | test.cpp:260:7:260:7 | x | x | test.cpp:263:3:263:13 | Store: ... = ... | here | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp index 3e8a7e90b84..616305a8174 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/UsingExpiredStackAddress/test.cpp @@ -209,4 +209,61 @@ int maybe_deref_p(bool b) { int field_indirect_maybe_bad(bool b) { escape1(); return maybe_deref_p(b); +} + +// These next tests cover subsequent stores to the same address in the same basic block. + +static struct S100 s102; + +void not_escape1() { + int x; + s102.p = &x; + s102.p = nullptr; +} + +void calls_not_escape1() { + not_escape1(); + int x = *s102.p; // GOOD +} + +static struct S100 s103; + +void escape2() { + int x; + s103.p = nullptr; + s103.p = &x; +} + +void calls_escape2() { + escape2(); + int x = *s103.p; // BAD +} + +bool unknown(); +static struct S100 s104; + +void not_escape2() { + int x; + s104.p = &x; + if(unknown()) { } + s104.p = nullptr; +} + +void calls_not_escape2() { + not_escape2(); + int x = *s104.p; // GOOD +} + +static struct S100 s105; + +void escape3() { + int x; + s105.p = nullptr; + if(unknown()) { } + s105.p = &x; +} + +void calls_escape3() { + escape3(); + int x = *s105.p; // BAD } \ No newline at end of file From a9d80a5a4859ada235748e25dec18757f2c3e77a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 8 Sep 2022 11:35:54 +0000 Subject: [PATCH 03/27] Release preparation for version 2.10.5 --- cpp/ql/lib/CHANGELOG.md | 2 ++ cpp/ql/lib/change-notes/released/0.3.5.md | 1 + cpp/ql/lib/codeql-pack.release.yml | 2 +- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/CHANGELOG.md | 2 ++ cpp/ql/src/change-notes/released/0.3.4.md | 1 + cpp/ql/src/codeql-pack.release.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md | 2 ++ .../ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md | 1 + csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/src/CHANGELOG.md | 2 ++ .../ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md | 1 + csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/CHANGELOG.md | 2 ++ csharp/ql/lib/change-notes/released/0.3.5.md | 1 + csharp/ql/lib/codeql-pack.release.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/CHANGELOG.md | 2 ++ csharp/ql/src/change-notes/released/0.3.4.md | 1 + csharp/ql/src/codeql-pack.release.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/lib/CHANGELOG.md | 2 ++ go/ql/lib/change-notes/released/0.2.5.md | 1 + go/ql/lib/codeql-pack.release.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/CHANGELOG.md | 2 ++ go/ql/src/change-notes/released/0.2.5.md | 1 + go/ql/src/codeql-pack.release.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/CHANGELOG.md | 2 ++ java/ql/lib/change-notes/released/0.3.5.md | 1 + java/ql/lib/codeql-pack.release.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/CHANGELOG.md | 2 ++ java/ql/src/change-notes/released/0.3.4.md | 1 + java/ql/src/codeql-pack.release.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/CHANGELOG.md | 2 ++ javascript/ql/lib/change-notes/released/0.2.5.md | 1 + javascript/ql/lib/codeql-pack.release.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/CHANGELOG.md | 2 ++ javascript/ql/src/change-notes/released/0.3.4.md | 1 + javascript/ql/src/codeql-pack.release.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- python/ql/lib/CHANGELOG.md | 2 ++ python/ql/lib/change-notes/released/0.5.5.md | 1 + python/ql/lib/codeql-pack.release.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/CHANGELOG.md | 2 ++ python/ql/src/change-notes/released/0.4.3.md | 1 + python/ql/src/codeql-pack.release.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/CHANGELOG.md | 2 ++ ruby/ql/lib/change-notes/released/0.3.5.md | 1 + ruby/ql/lib/codeql-pack.release.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/CHANGELOG.md | 2 ++ ruby/ql/src/change-notes/released/0.3.4.md | 1 + ruby/ql/src/codeql-pack.release.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- 64 files changed, 80 insertions(+), 32 deletions(-) create mode 100644 cpp/ql/lib/change-notes/released/0.3.5.md create mode 100644 cpp/ql/src/change-notes/released/0.3.4.md create mode 100644 csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md create mode 100644 csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md create mode 100644 csharp/ql/lib/change-notes/released/0.3.5.md create mode 100644 csharp/ql/src/change-notes/released/0.3.4.md create mode 100644 go/ql/lib/change-notes/released/0.2.5.md create mode 100644 go/ql/src/change-notes/released/0.2.5.md create mode 100644 java/ql/lib/change-notes/released/0.3.5.md create mode 100644 java/ql/src/change-notes/released/0.3.4.md create mode 100644 javascript/ql/lib/change-notes/released/0.2.5.md create mode 100644 javascript/ql/src/change-notes/released/0.3.4.md create mode 100644 python/ql/lib/change-notes/released/0.5.5.md create mode 100644 python/ql/src/change-notes/released/0.4.3.md create mode 100644 ruby/ql/lib/change-notes/released/0.3.5.md create mode 100644 ruby/ql/src/change-notes/released/0.3.4.md diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index 07ef45e843a..6d2dc736630 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/cpp/ql/lib/change-notes/released/0.3.5.md b/cpp/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 2151c51c317..10d87da8f2b 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.3.5-dev +version: 0.3.5 groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index ad35d01050b..5546465c50e 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### Minor Analysis Improvements diff --git a/cpp/ql/src/change-notes/released/0.3.4.md b/cpp/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/cpp/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 6b0f6e7ed01..fb1043cf900 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.3.4-dev +version: 0.3.4 groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 072581ceeec..d993fc0868f 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.5 + ## 1.2.4 ## 1.2.3 diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md new file mode 100644 index 00000000000..e040f831239 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.2.5.md @@ -0,0 +1 @@ +## 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index 172090f46b6..40355f0807f 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.2.4 +lastReleaseVersion: 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index db606ea8fbe..79f23b2b333 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.2.5-dev +version: 1.2.5 groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 072581ceeec..d993fc0868f 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.5 + ## 1.2.4 ## 1.2.3 diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md new file mode 100644 index 00000000000..e040f831239 --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.2.5.md @@ -0,0 +1 @@ +## 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index 172090f46b6..40355f0807f 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.2.4 +lastReleaseVersion: 1.2.5 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 1eab4e25bb0..8f1c7ce969f 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.2.5-dev +version: 1.2.5 groups: - csharp - solorigate diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index bae0baebc1d..4b79fb8ee02 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/csharp/ql/lib/change-notes/released/0.3.5.md b/csharp/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/csharp/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 2690f4bb43e..3b5e0f4ebd6 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.3.5-dev +version: 0.3.5 groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index 60b637b99cd..121f81270df 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### Minor Analysis Improvements diff --git a/csharp/ql/src/change-notes/released/0.3.4.md b/csharp/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/csharp/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 1cc369a1319..4efd85c33ae 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.3.4-dev +version: 0.3.4 groups: - csharp - queries diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 21888c17ed4..2a6ee5dbcb2 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.2.5 + ## 0.2.4 ### Minor Analysis Improvements diff --git a/go/ql/lib/change-notes/released/0.2.5.md b/go/ql/lib/change-notes/released/0.2.5.md new file mode 100644 index 00000000000..ec3e1ae7d2f --- /dev/null +++ b/go/ql/lib/change-notes/released/0.2.5.md @@ -0,0 +1 @@ +## 0.2.5 diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 7f1e3841dcd..211454ed306 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.4 +lastReleaseVersion: 0.2.5 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index b34e1d09f52..142cb56bdf0 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.2.5-dev +version: 0.2.5 groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index 0f01c599559..7f394f66ff0 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.2.5 + ## 0.2.4 ## 0.2.3 diff --git a/go/ql/src/change-notes/released/0.2.5.md b/go/ql/src/change-notes/released/0.2.5.md new file mode 100644 index 00000000000..ec3e1ae7d2f --- /dev/null +++ b/go/ql/src/change-notes/released/0.2.5.md @@ -0,0 +1 @@ +## 0.2.5 diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 7f1e3841dcd..211454ed306 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.4 +lastReleaseVersion: 0.2.5 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 4e9b30f4fc5..687a6f19339 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.2.5-dev +version: 0.2.5 groups: - go - queries diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index 6409aa6a1e7..08015c8974b 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/java/ql/lib/change-notes/released/0.3.5.md b/java/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/java/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 00b39029b01..8244ec88325 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.3.5-dev +version: 0.3.5 groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 7a2df51efce..add95173a56 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### New Queries diff --git a/java/ql/src/change-notes/released/0.3.4.md b/java/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/java/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 3e24af43783..e4fd07d53c6 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.3.4-dev +version: 0.3.4 groups: - java - queries diff --git a/javascript/ql/lib/CHANGELOG.md b/javascript/ql/lib/CHANGELOG.md index ad777dc3758..b75b634cb41 100644 --- a/javascript/ql/lib/CHANGELOG.md +++ b/javascript/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.2.5 + ## 0.2.4 ### Deprecated APIs diff --git a/javascript/ql/lib/change-notes/released/0.2.5.md b/javascript/ql/lib/change-notes/released/0.2.5.md new file mode 100644 index 00000000000..ec3e1ae7d2f --- /dev/null +++ b/javascript/ql/lib/change-notes/released/0.2.5.md @@ -0,0 +1 @@ +## 0.2.5 diff --git a/javascript/ql/lib/codeql-pack.release.yml b/javascript/ql/lib/codeql-pack.release.yml index 7f1e3841dcd..211454ed306 100644 --- a/javascript/ql/lib/codeql-pack.release.yml +++ b/javascript/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.2.4 +lastReleaseVersion: 0.2.5 diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index 8f644347429..b4cc4229c5d 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.2.5-dev +version: 0.2.5 groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/CHANGELOG.md b/javascript/ql/src/CHANGELOG.md index b26d54a5a01..b276538589f 100644 --- a/javascript/ql/src/CHANGELOG.md +++ b/javascript/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### New Queries diff --git a/javascript/ql/src/change-notes/released/0.3.4.md b/javascript/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/javascript/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/javascript/ql/src/codeql-pack.release.yml b/javascript/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/javascript/ql/src/codeql-pack.release.yml +++ b/javascript/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index b371302105e..4c29faf8f6e 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.3.4-dev +version: 0.3.4 groups: - javascript - queries diff --git a/python/ql/lib/CHANGELOG.md b/python/ql/lib/CHANGELOG.md index dcd958642e2..f2a727eaac5 100644 --- a/python/ql/lib/CHANGELOG.md +++ b/python/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.5.5 + ## 0.5.4 ### Deprecated APIs diff --git a/python/ql/lib/change-notes/released/0.5.5.md b/python/ql/lib/change-notes/released/0.5.5.md new file mode 100644 index 00000000000..43d9edcf6f4 --- /dev/null +++ b/python/ql/lib/change-notes/released/0.5.5.md @@ -0,0 +1 @@ +## 0.5.5 diff --git a/python/ql/lib/codeql-pack.release.yml b/python/ql/lib/codeql-pack.release.yml index cd3f72e2513..03e491f0899 100644 --- a/python/ql/lib/codeql-pack.release.yml +++ b/python/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.4 +lastReleaseVersion: 0.5.5 diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 05847e4583c..394957b4ff2 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.5.5-dev +version: 0.5.5 groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/CHANGELOG.md b/python/ql/src/CHANGELOG.md index 64a150e5d26..3dcb357340c 100644 --- a/python/ql/src/CHANGELOG.md +++ b/python/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.4.3 + ## 0.4.2 ### New Queries diff --git a/python/ql/src/change-notes/released/0.4.3.md b/python/ql/src/change-notes/released/0.4.3.md new file mode 100644 index 00000000000..46d087ac75f --- /dev/null +++ b/python/ql/src/change-notes/released/0.4.3.md @@ -0,0 +1 @@ +## 0.4.3 diff --git a/python/ql/src/codeql-pack.release.yml b/python/ql/src/codeql-pack.release.yml index 94c5b17423c..1ec9c4ea5d9 100644 --- a/python/ql/src/codeql-pack.release.yml +++ b/python/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.2 +lastReleaseVersion: 0.4.3 diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index aa3ae63928e..8beca495a77 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.4.3-dev +version: 0.4.3 groups: - python - queries diff --git a/ruby/ql/lib/CHANGELOG.md b/ruby/ql/lib/CHANGELOG.md index 52ab1a60e7b..fe86f4ecc2c 100644 --- a/ruby/ql/lib/CHANGELOG.md +++ b/ruby/ql/lib/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.5 + ## 0.3.4 ### Deprecated APIs diff --git a/ruby/ql/lib/change-notes/released/0.3.5.md b/ruby/ql/lib/change-notes/released/0.3.5.md new file mode 100644 index 00000000000..88b60b4e980 --- /dev/null +++ b/ruby/ql/lib/change-notes/released/0.3.5.md @@ -0,0 +1 @@ +## 0.3.5 diff --git a/ruby/ql/lib/codeql-pack.release.yml b/ruby/ql/lib/codeql-pack.release.yml index 5ed15c24b9c..468917f2543 100644 --- a/ruby/ql/lib/codeql-pack.release.yml +++ b/ruby/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.4 +lastReleaseVersion: 0.3.5 diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index db4dd46754b..0815ff3c100 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.3.5-dev +version: 0.3.5 groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/CHANGELOG.md b/ruby/ql/src/CHANGELOG.md index 64fed9793c3..b2e4430ba2d 100644 --- a/ruby/ql/src/CHANGELOG.md +++ b/ruby/ql/src/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.3.4 + ## 0.3.3 ### New Queries diff --git a/ruby/ql/src/change-notes/released/0.3.4.md b/ruby/ql/src/change-notes/released/0.3.4.md new file mode 100644 index 00000000000..d62a8a1780d --- /dev/null +++ b/ruby/ql/src/change-notes/released/0.3.4.md @@ -0,0 +1 @@ +## 0.3.4 diff --git a/ruby/ql/src/codeql-pack.release.yml b/ruby/ql/src/codeql-pack.release.yml index 9da182d3394..5ed15c24b9c 100644 --- a/ruby/ql/src/codeql-pack.release.yml +++ b/ruby/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.3.3 +lastReleaseVersion: 0.3.4 diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index 54e53470b32..bf62aa5e568 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.3.4-dev +version: 0.3.4 groups: - ruby - queries From ed663885515788f306b4cf8dc27d173c96911fff Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Thu, 18 Aug 2022 15:28:50 -0700 Subject: [PATCH 04/27] Port Pack Docs changes to 3.7 This moves the following three PRs to the 3.7 branch: - https://github.com/github/codeql/pull/10182 - https://github.com/github/codeql/pull/10146 - https://github.com/github/codeql/pull/10105 --- docs/codeql/codeql-cli/about-codeql-packs.rst | 306 ++++++++++++++++-- .../codeql-cli/about-codeql-workspaces.rst | 94 ++++++ docs/codeql/codeql-cli/about-ql-packs.rst | 245 -------------- ...nalyzing-databases-with-the-codeql-cli.rst | 89 ++--- .../codeql-cli/codeql-cli-reference.rst | 9 +- ...creating-and-working-with-codeql-packs.rst | 15 +- .../codeql-cli/creating-codeql-databases.rst | 64 ++-- .../creating-codeql-query-suites.rst | 77 +++-- .../getting-started-with-the-codeql-cli.rst | 25 +- .../publishing-and-using-codeql-packs.rst | 3 +- .../codeql-cli/query-reference-files.rst | 22 +- ...options-in-a-codeql-configuration-file.rst | 10 +- .../codeql-cli/testing-custom-queries.rst | 111 +++---- .../codeql-cli/testing-query-help-files.rst | 42 +-- .../codeql-cli/upgrading-codeql-databases.rst | 55 ---- ...ing-custom-queries-with-the-codeql-cli.rst | 19 +- .../codeql-cli/using-the-codeql-cli.rst | 15 +- .../analyzing-your-projects.rst | 14 +- ...etting-up-codeql-in-visual-studio-code.rst | 2 +- .../codeql-overview/codeql-glossary.rst | 52 +-- .../ql-language-specification.rst | 14 +- docs/codeql/reusables/test-qlpack.rst | 14 +- .../about-codeql-queries.rst | 4 +- 23 files changed, 668 insertions(+), 633 deletions(-) create mode 100644 docs/codeql/codeql-cli/about-codeql-workspaces.rst delete mode 100644 docs/codeql/codeql-cli/about-ql-packs.rst delete mode 100644 docs/codeql/codeql-cli/upgrading-codeql-databases.rst diff --git a/docs/codeql/codeql-cli/about-codeql-packs.rst b/docs/codeql/codeql-cli/about-codeql-packs.rst index 2f9c6eebd37..dca601c530a 100644 --- a/docs/codeql/codeql-cli/about-codeql-packs.rst +++ b/docs/codeql/codeql-cli/about-codeql-packs.rst @@ -14,11 +14,18 @@ There are two types of CodeQL packs: query packs and library packs. You can use the package management commands in the CodeQL CLI to create CodeQL packs, add dependencies to packs, and install or update dependencies. For more information, see ":ref:`Creating and working with CodeQL packs `." You can also publish and download CodeQL packs using the CodeQL CLI. For more information, see ":doc:`Publishing and using CodeQL packs `." + +The standard CodeQL packages for all supported languages are published in the `GitHub Container registry `__. +The `CodeQL repository `__ contains source files for the standard CodeQL packs for all supported languages. + +.. _codeql-pack-structure: + CodeQL pack structure --------------------- -A CodeQL pack must contain a file called ``qlpack.yml`` in its root directory. In the ``qlpack.yml`` file, the ``name:`` field must have a value that follows the format of ``/``, where ```` is the GitHub organization or user account that the pack will be published to and ```` is the name of the pack. The other -files and directories within the pack should be logically organized. For example, typically: +A CodeQL pack must contain a file called ``qlpack.yml`` in its root directory. In the ``qlpack.yml`` file, the ``name:`` field must have a value that follows the format of ``/``, where ```` is the GitHub organization or user account that the pack will be published to and ```` is the name of the pack. Additionally, query packs and library packs with CodeQL tests contain a ``codeql-pack.lock.yml`` file that contains the resolved dependencies of the pack. This file is generated during a call to the ``codeql pack install`` command, is not meant to be edited by hand, and should be added to your version control system. + +The other files and directories within the pack should be logically organized. For example, typically: - Queries are organized into directories for specific categories. - Queries for specific products, libraries, and frameworks are organized into @@ -27,21 +34,17 @@ files and directories within the pack should be logically organized. For example About ``qlpack.yml`` files -------------------------- -When executing query-related commands, CodeQL first looks in siblings of the installation directory (and their subdirectories) for ``qlpack.yml`` files. -Then it checks the package cache for CodeQL packs which have been downloaded. This means that when you are developing queries locally, the local packages +When executing query-related commands, CodeQL first looks in siblings of the installation directory (and their subdirectories) for ``qlpack.yml`` files. +Then it checks the package cache for CodeQL packs which have been downloaded. This means that when you are developing queries locally, the local packages in the installation directory override packages of the same name in the package cache, so that you can test your local changes. -The metadata in each `qlpack.yml`` file tells +The metadata in each ``qlpack.yml`` file tells CodeQL how to compile any queries in the pack, what libraries the pack depends on, and where to find query suite definitions. -The contents of the CodeQL pack (queries or libraries used in CodeQL analysis) is -included in the same directory as ``qlpack.yml``, or its subdirectories. +The contents of the CodeQL pack (queries or libraries used in CodeQL analysis) is included in the same directory as ``qlpack.yml``, or its subdirectories. -The location of ``qlpack.yml`` defines the library path for the content -of the CodeQL pack. That is, for all ``.ql`` and ``.qll`` files in the pack, -CodeQL will resolve all import statements relative to the ``qlpack.yml`` at the -pack's root. +The directory containing the ``qlpack.yml`` file serves as the root directory for the content of the CodeQL pack. That is, for all ``.ql`` and ``.qll`` files in the pack, CodeQL will resolve all import statements relative to the directory containing the ``qlpack.yml`` file at the pack's root. .. _codeqlpack-yml-properties: @@ -56,49 +59,282 @@ The following properties are supported in ``qlpack.yml`` files. * - Property - Example - - Required + - Required by - Purpose * - ``name`` - - ``octo-org/security-queries`` + - .. code-block:: yaml + + name: octo-org/security-queries + - All packs - - The scope, where the CodeQL pack is published, and the name of the pack defined using alphanumeric characters and hyphens. It must be unique as CodeQL cannot differentiate between CodeQL packs with identical names. Name components cannot start or end with a hyphen. Additionally, a period is not allowed in pack names at all. Use the pack name to specify queries to run using ``database analyze`` and to define dependencies between QL packs (see examples below). + - The scope, where the CodeQL pack is published, and the name of the pack defined using alphanumeric characters and hyphens. It must be unique as CodeQL cannot differentiate between CodeQL packs with identical names. Use the pack name to specify queries to run using ``database analyze`` and to define dependencies between CodeQL packs (see examples below). * - ``version`` - - ``0.0.0`` + - .. code-block:: yaml + + version: 0.0.0 + - All packs - - A version range for this CodeQL pack. This must be a valid semantic version that meets the `SemVer v2.0.0 specification `__. + - A semantic version for this CodeQL pack that must adhere to the `SemVer v2.0.0 specification `__. * - ``dependencies`` - - ``codeql/javascript-all: ^1.2.3`` - - Optional - - The names and version ranges of any CodeQL packs that this pack depends on, as a mapping. This gives the pack access to any libraries, database schema, and query suites defined in the dependency. For more information, see `SemVer ranges `__ in the NPM documentation. + - .. code-block:: yaml + + dependencies: + codeql/cpp-all: ^0.0.2 + + - Packs that define CodeQL package dependencies on other packs + - A map from pack references to the semantic version range that is compatible with this pack. Supported for CLI versions v2.6.0 and later. + * - ``defaultSuiteFile`` + - .. code-block:: yaml + + defaultSuiteFile: cpp-code-scanning.qls + + - Packs that export a set of default queries to run + - The path to a query suite file relative to the package root, containing all of the queries that are run by default when this pack is passed to the ``codeql database analyze`` command. Supported from CLI version v2.6.0 and onwards. Only one of ``defaultSuiteFile`` or ``defaultSuite`` can be defined. + * - ``defaultSuite`` + - .. code-block:: yaml + + defaultSuite: + queries: . + exclude: + precision: medium + + - Packs that export a set of default queries to run + - An inlined query suite containing all of the queries that are run by default when this pack is passed to the ``codeql database analyze`` command. Supported from CLI version v2.6.0 and onwards. Only one of ``defaultSuiteFile`` or ``defaultSuite`` can be defined. + * - ``library`` + - .. code-block:: yaml + + library: true + + - Library packs + - A boolean value that indicates whether this pack is a library pack. Library packs do not contain queries and are not compiled. Query packs can ignore this field or explicitly set it to ``false``. * - ``suites`` - - ``octo-org-query-suites`` + - .. code-block:: yaml + + suites: octo-org-query-suites + - Optional - - The path to a directory in the pack that contains the query suites you want to make known to the CLI, defined relative to the pack directory. QL pack users can run "well-known" suites stored in this directory by specifying the pack name, without providing their full path. This is not supported for CodeQL packs downloaded from a package registry. For more information about query suites, see ":doc:`Creating CodeQL query suites `." + - The path to a directory in the pack that contains the query suites you want to make known to the CLI, defined relative to the pack directory. CodeQL pack users can run "well-known" suites stored in this directory by specifying the pack name, without providing their full path. This is not supported for CodeQL packs downloaded from the Container registry. For more information about query suites, see ":doc:`Creating CodeQL query suites `." * - ``extractor`` - - ``javascript`` - - All test packs - - The CodeQL language extractor to use when the CLI creates a database in the pack. For more information about testing queries, see ":doc:`Testing custom queries `." + - .. code-block:: yaml + + extractor: javascript + + - All packs containing CodeQL tests + - The CodeQL language extractor to use when running the CodeQL tests in the pack. For more information about testing queries, see ":doc:`Testing custom queries `." * - ``tests`` - - ``.`` - - Optional for test packs - - The path to a directory within the pack that contains tests, defined relative to the pack directory. Use ``.`` to specify the whole pack. Any queries in this directory are run as tests when ``test run`` is run with the ``--strict-test-discovery`` option. These queries are ignored by query suite definitions that use ``queries`` or ``qlpack`` instructions to ask for all queries in a particular pack. + - .. code-block:: yaml + + tests: . + + - Optional for packs containing CodeQL tests. Ignored for packs without tests. + - The path to a directory within the pack that contains tests, defined relative to the pack directory. Use ``.`` to specify the whole pack. Any queries in this directory are run as tests when ``test run`` is run with the ``--strict-test-discovery`` option. These queries are ignored by query suite definitions that use ``queries`` or ``qlpack`` instructions to ask for all queries in a particular pack. If this property is missing, then ``.`` is assumed. * - ``dbscheme`` - - ``semmlecode.python.dbscheme`` + - .. code-block:: yaml + + dbscheme: semmlecode.python.dbscheme + - Core language packs only - The path to the :ref:`database schema ` for all libraries and queries written for this CodeQL language (see example below). * - ``upgrades`` - - ``.`` + - .. code-block:: yaml + + upgrades: . + - Core language packs only - - The path to a directory within the pack that contains upgrade scripts, defined relative to the pack directory. The ``database upgrade`` action uses these scripts to update databases that were created by an older version of an extractor so they're compatible with the current extractor (see `Upgrade scripts for a language <#upgrade-scripts-for-a-language>`__ below.) + - The path to a directory within the pack that contains database upgrade scripts, defined relative to the pack directory. Database upgrades are used internally to ensure that a database created with a different version of the CodeQL CLI is compatible with the current version of the CLI. * - ``authors`` - - ``example@github.com`` + - .. code-block:: yaml + + authors: author1@github.com,author2@github.com + - All packs - Metadata that will be displayed on the packaging search page in the packages section of the account that the CodeQL pack is published to. - * - ``licenses`` - - ``(LGPL-2.1 AND MIT)`` + * - ``license`` + - .. code-block:: yaml + + license: MIT + - All packs - - Metadata that will be displayed on the packaging search page in the packages section of the account that the CodeQL pack is published to. For a list of allowed licenses, see `SPDX License List `__ in the SPDX Specification. + - Metadata that will be displayed on the packaging search page in the packages section of the account that the CodeQL pack is published to. For a list of allowed licenses, see `SPDX License List `__ in the SPDX Specification. * - ``description`` - - ``Human-readable description of the contents of the CodeQL pack.`` + - .. code-block:: yaml + + description: Human-readable description of the contents of the CodeQL pack. + - All packs - Metadata that will be displayed on the packaging search page in the packages section of the account that the CodeQL pack is published to. + * - ``libraryPathDependencies`` + - .. code-block:: yaml + + libraryPathDependencies: codeql/javascript-all + + - Optional, deprecated + - Use the ``dependencies`` property instead. The names of any CodeQL packs that this CodeQL pack depends on, as an array. This gives the pack access to any libraries, database schema, and query suites defined in the dependency. + +.. _about-codeql-pack-lock: + +About ``codeql-pack.lock.yml`` files +------------------------------------ + +``codeql-pack.lock.yml`` files store the versions of the resolved transitive dependencies of a CodeQL pack. This file is created by the ``codeql pack install`` command if it does not already exist and should be added to your version control system. The ``dependencies`` section of the ``qlpack.yml`` file contains version ranges that are compatible with the pack. The ``codeql-pack.lock.yml`` file locks the versions to precise dependencies. This ensures that running ``codeql pack install`` on this the pack will always retrieve the same versions of dependencies even if newer compatible versions exist. + +For example, if a ``qlpack.yml`` file contains the following dependencies: + +.. code-block:: yaml + + dependencies: + codeql/cpp-all: ^0.1.2 + my-user/my-lib: ^0.2.3 + other-dependency/from-source: "*" + +The ``codeql-pack.lock.yml`` file will contain something like the following: + +.. code-block:: yaml + + dependencies: + codeql/cpp-all: + version: 0.1.4 + my-user/my-lib: + version: 0.2.4 + my-user/transitive-dependency: + version: 1.2.4 + +The ``codeql/cpp-all`` dependency is locked to version 0.1.4. The ``my-user/my-lib`` dependency is locked to version 0.2.4. The ``my-user/transitive-dependency``, which is a transitive dependency and is not specified in the ``qlpack.yml`` file, is locked to version 1.2.4. The ``other-dependency/from-source`` is absent from the lock file since it is resolved from source. This dependency must be available in the same CodeQL workspace as the pack. For more information about CodeQL workspaces and resolving dependencies from source, see ":doc:`About CodeQL Workspaces `." + +In most cases, the ``codeql-pack.lock.yml`` file is only relevant for query packs since library packs are non-executable and usually do not need their transitive dependencies to be fixed. The exception to this is for library packs that contain tests. In this case, the ``codeql-pack.lock.yml`` file is used to ensure that the tests are always run with the same versions of dependencies to avoid spurious failures when there are mismatched dependencies. + +.. _custom-codeql-packs: + +Examples of custom CodeQL packs +------------------------------- + +When you write custom queries or tests, you should save them in custom CodeQL packs. For simplicity, try to organize each pack logically. For more information, see "`CodeQL pack structure <#codeql-pack-structure>`__." Save files for queries and tests in separate packs and, where possible, organize custom packs into specific folders for each target language. This is particuarly useful if you intend to publish your CodeQL packs so they can be shared with others or used in GitHub `Code scanning `__. + +CodeQL packs for custom libraries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A custom CodeQL pack containing custom C++ libraries, with no queries or tests, may have a ``qlpack.yml`` file containing: + +.. code-block:: yaml + + name: my-github-user/my-custom-libraries + version: 1.2.3 + library: true + dependencies: + codeql/cpp-all: ^0.1.2 + +where ``codeql/cpp-all`` is the name of the CodeQL pack for C/C++ analysis included in the CodeQL repository. The version range ``^0.1.2`` indicates that this pack is compatible with all versions of ``codeql/cpp-all`` that are greater than or equal to ``0.1.2`` and less than ``0.2.0``. Any CodeQL library file (a file with a ``.qll`` extension) defined in this pack will be available to queries defined in any query pack that includes this pack in its dependencies block. + +The ``library`` property indicates that this pack is a library pack and does not contain any queries. + +CodeQL packs for custom queries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A custom CodeQL pack containing custom C++ queries and libraries may have a ``qlpack.yml`` file containing: + +.. code-block:: yaml + + name: my-github-user/my-custom-queries + version: 1.2.3 + dependencies: + codeql/cpp-all: ^0.1.2 + my-github-user/my-custom-libraries: ^1.2.3 + suites: my-custom-suites + +where ``codeql/cpp-all`` is the name of the CodeQL pack for C/C++ analysis included in the CodeQL repository. The version range ``^0.1.2`` indicates that this pack is compatible with all versions of ``codeql/cpp-all`` that are greater than or equal to ``0.1.2`` and less than ``0.2.0``. ``my-github-user/my-custom-libraries`` is the name of a CodeQL pack containing custom CodeQL libraries for C++. Any CodeQL library file (a file with a ``.qll`` extension) defined in this pack will be available to queries in the ``my-github-user/my-custom-queries`` pack. + +The ``suites`` property indicates a directory where "well-known" query suites can be found. These suites can be used on the command line by referring to their name only, rather than their full path. For more information about query suites, see ":doc:`Creating CodeQL query suites `." + +CodeQL packs for custom tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For custom CodeQL packs containing test files, you also need to include an +``extractor`` property so that the ``test run`` command knows how to create test +databases. You may also wish to specify the ``tests`` property. + +.. include:: ../reusables/test-qlpack.rst + +For more information about running tests, see ":doc:`Testing custom queries +`." + +.. _standard-codeql-packs: + +Examples of CodeQL packs in the CodeQL repository +------------------------------------------------- + +Each of the languages in the CodeQL repository has four main CodeQL packs: + +- Core library pack for the language, with the :ref:`database schema ` + used by the language, and CodeQL libraries, and queries at ``/ql/lib`` +- Core query pack for the language that includes the default queries for the language, along + with their query suites at ``/ql/src`` +- Tests for the core language libraries and queries at ``/ql/test`` +- Example queries for the language at ``/ql/examples`` + +Core library pack +~~~~~~~~~~~~~~~~~ + +Here is an example ``qlpack.yml`` file for the `C/C++ analysis libraries +`__ +core language pack: + +.. code-block:: yaml + + name: codeql/cpp-all + version: x.y.z-dev + dbscheme: semmlecode.cpp.dbscheme + library: true + upgrades: upgrades + +Some extra notes on the following properties: + +- ``library``: Indicates that this is a library pack with no executable queries. It is only meant to be used as a dependency for other packs. +- ``dbscheme`` and ``upgrades``: These properties are internal to the CodeQL CLI and should only be defined in the core QL pack for a language. + +.. _standard-codeql-query-packs: + +Core query pack +~~~~~~~~~~~~~~~ + +Here is an example ``qlpack.yml`` file for `C/C++ analysis queries +`__ +core query pack: + +.. code-block:: yaml + + name: codeql/cpp-queries + version: x.y.z-dev + dependencies: + codeql/cpp-all: "*" + codeql/suite-helpers: "*" + suites: codeql-suites + defaultSuiteFile: codeql-suites/cpp-code-scanning.qls + +Some extra notes on the following properties: + +- ``dependencies``: This query pack depends on ``codeql/cpp-all`` and ``codeql/suite-helpers``. Since these dependencies are resolved from source, it does not matter what version of the CodeQL pack they are compatible with. For more information about resolving dependencies from source, see ":ref:`Source Dependencies `." +- ``suites``: Indicates the directory containing "well-known" query suites. +- ``defaultSuiteFile``: The name of the default query suite file that is used when no query suite is specified. + +Tests for the core CodeQL pack +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here is an example ``qlpack.yml`` file for `C/C++ analysis tests +`__ +core test pack: + +.. code-block:: yaml + + name: codeql/cpp-tests + dependencies: + codeql/cpp-all: "*" + codeql/cpp-queries: "*" + extractor: cpp + tests: . + +Some extra notes on the following properties: + +- ``dependencies``: This pack depends on the core CodeQL query and library packs for C++. +- ``extractor``: This specifies that all the tests will use the same C++ extractor to create the database for the tests. +- ``tests``: This specifies the location of the tests. In this case, the tests are in the root folder (and all sub-folders) of the pack. +- ``version``: There is no ``version`` property for the tests pack. This prevents test packs from accidentally being published. diff --git a/docs/codeql/codeql-cli/about-codeql-workspaces.rst b/docs/codeql/codeql-cli/about-codeql-workspaces.rst new file mode 100644 index 00000000000..3f27672d502 --- /dev/null +++ b/docs/codeql/codeql-cli/about-codeql-workspaces.rst @@ -0,0 +1,94 @@ +.. _about-codeql-workspaces: + +About CodeQL Workspaces +======================= + +.. include:: ../reusables/beta-note-package-management.rst + +CodeQL workspaces are used to group multiple CodeQL packs together. A typical use case for a CodeQL workspace is to develop a set of CodeQL library and query packs that are mutually dependent. For more information on CodeQL packs, see ":doc:`About CodeQL packs `." + +The main benefit of a CodeQL workspace is that it makes it easier for you to develop and maintain multiple CodeQL packs. When you use a CodeQL workspace, all the CodeQL packs in the workspace are available as *source dependencies* for each other when you run a CodeQL command that resolves queries. This makes it easier to develop, maintain, and publish multiple, related CodeQL packs. + +In most cases, you should store the CodeQL workspace and the CodeQL packs contained in it in one git repository. This makes it easier to share your CodeQL development environment. + +The ``codeql-workspace.yml`` file +--------------------------------- + +A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally an ``ignore`` block. + +* The ``provide`` block contains a list of glob patterns that define the CodeQL packs that are available in the workspace. +* The ``ignore`` block contains a list of glob patterns that define CodeQL packs that are not available in the workspace. + +Each entry in the ``provide`` or ``ignore`` section must map to the location of a ``qlpack.yml`` file. All glob patterns are defined relative to the directory that contains the workspace file. For a list of patterns accepted in this file, see" `@actions/glob `__ . + +For example, the following ``codeql-workspace.yml`` file defines a workspace that contains all the CodeQL packs recursively found in the ``codeql-packs`` directory, except for the packs in the ``experimental`` directory: + +.. code-block:: yaml + + provide: + - "*/codeql-packs/**/qlpack.yml" + ignore: + - "*/codeql-packs/**/experimental/**/qlpack.yml" + +To verify that your ``codeql-workspace.yml`` file includes the CodeQL packs that you expect, run the ``codeql pack ls`` command in the same directory as your workspace. The result of the command is a list of all CodeQL packs in the workspace. + +.. _source-dependencies: + +Source Dependencies +------------------- + +Source dependencies are CodeQL packs that are resolved from the local file system outside of the CodeQL package cache. These dependencies can be in the same CodeQL workspace, or specified as a path option using the ``--additional-packs`` argument. When you compile and run queries locally, source dependencies override any dependencies found in the CodeQL package cache as well as version constraints defined in the ``qlpack.yml``. All references to CodeQL packs in the same workspace are resolved as source dependencies. + +This is particularly useful in the following situations: + +- One of the dependencies of the query pack you are running is not yet published. Resolving from source is the only way to reference that pack. +- You are making changes to multiple packs at the same time and want to test them together. Resolving from source ensures that you are using the version of the pack with your changes in it. + +CodeQL workspaces and query resolution +-------------------------------------- + +All CodeQL packs in a workspace are available as source dependencies for each other when you run any CodeQL command that resolves queries or packs. For example, when you run ``codeql pack install`` in a pack directory in a workspace, any dependency that can be found in the workspace will be used instead of downloading that dependency to the package cache and adding it to the ``codeql-pack.lock.yml`` file. For more information, see ":ref:Adding and Installing Dependencies `." + +Similarly, when you publish a CodeQL query pack to the GitHub container registry using ``codeql pack publish`` the command will always use the dependencies from the workspace instead of using dependencies found in the local package cache. + +This ensures that any local changes you make to a query library in a dependency are automatically reflected in any query packs you publish from that workspace. + +Example +~~~~~~~ + +Consider the following ``codeql-workspace.yml`` file: + +.. code-block:: yaml + + provide: + - "**/qlpack.yml" + +And the following CodeQL library pack ``qlpack.yml`` file in the workspace: + +.. code-block:: yaml + + name: my-company/my-library + library: true + version: 1.0.0 + +And the following CodeQL query pack ``qlpack.yml`` file in the workspace: + +.. code-block:: yaml + + name: my-company/my-queries + version: 1.0.0 + dependencies: + my-company/my-library: "*" + codeql/cpp-all: ~0.2.0 + +Notice that the ``dependencies`` block for the CodeQL query pack, ``my-company/my-queries``, specifies ``"*"`` as the version of the library pack. Since the library pack is already defined as a source dependency in ``codeql-workspace.yml``, the library pack's content is always resolved from inside the workspace. Any version constraint you define will be ignored in this case. We recommend that you use ``"*"`` for source dependencies to make it clear that the version is inherited from the workspace. + +When you execute ``codeql pack install`` from the query pack directory, an appropriate version of ``codeql/cpp-all`` is downloaded to the local package cache. Also, a ``codeql-pack.lock.yml`` file is created that contains the resolved version of ``codeql/cpp-all``. The lock file won't contain an entry for ``my-company/my-library`` since it is resolved from source dependencies. The ``codeql-pack.lock.yml`` file will look something like this: + +.. code-block:: yaml + + dependencies: + codeql/cpp-all: + version: 0.2.2 + +When you execute ``codeql pack publish`` from the query pack directory, the ``codeql/cpp-all`` dependency from the package cache and the ``my-company/my-library`` from the workspace are bundled with ``my-company/my-queries`` and published to the GitHub container registry. diff --git a/docs/codeql/codeql-cli/about-ql-packs.rst b/docs/codeql/codeql-cli/about-ql-packs.rst deleted file mode 100644 index 6568cf0a3e6..00000000000 --- a/docs/codeql/codeql-cli/about-ql-packs.rst +++ /dev/null @@ -1,245 +0,0 @@ -.. _about-ql-packs: - -About QL packs -============== - -QL packs are used to organize the files used in CodeQL analysis. They -contain queries, library files, query suites, and important metadata. - -The `CodeQL repository `__ contains standard QL packs for all supported languages. -You can also make custom QL packs to contain your own queries and libraries. - -QL pack structure ------------------ - -A QL pack must contain a file called ``qlpack.yml`` in its root directory. The other -files and directories within the pack should be logically organized. For example, typically: - -- Queries are organized into directories for specific categories. -- Queries for specific products, libraries, and frameworks are organized into - their own top-level directories. -- There is a top-level directory named ``/`` for query library - (``.qll``) files. Within this directory, ``.qll`` files should be organized into - subdirectories for specific categories. - -About ``qlpack.yml`` files --------------------------- - -When executing commands, CodeQL scans siblings of the installation directory (and -their subdirectories) for ``qlpack.yml`` files. The metadata in the file tells -CodeQL how to compile queries, what libraries the pack depends on, and where to -find query suite definitions. - -The content of the QL pack (queries and libraries used in CodeQL analysis) is -included in the same directory as ``qlpack.yml``, or its subdirectories. - -The location of ``qlpack.yml`` defines the library path for the content -of the QL pack. That is, for all ``.ql`` and ``.qll`` files in the QL pack, -CodeQL will resolve all import statements relative to the ``qlpack.yml`` at the -pack's root. - -For example, in a QL pack with the following contents, you can import ``CustomSinks.qll`` -from any location in the pack by declaring ``import mycompany.java.CustomSinks``. - -.. code-block:: none - - qlpack.yml - mycompany/ - java/ - security/ - CustomSinks.qll - Security/ - CustomQuery.ql - -For more information, see ":ref:`Importing modules `" -in the QL language reference. - -.. _qlpack-yml-properties: - -``qlpack.yml`` properties -~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following properties are supported in ``qlpack.yml`` files. - -.. list-table:: - :header-rows: 1 - :widths: auto - - * - Property - - Example - - Required - - Purpose - * - ``name`` - - ``org-queries`` - - All packs - - The name of the QL pack defined using alphanumeric characters, hyphens, and periods. It must be unique as CodeQL cannot differentiate between QL packs with identical names. If you intend to distribute the pack, prefix the name with your (or your organization's) name followed by a hyphen. Use the pack name to specify queries to run using ``database analyze`` and to define dependencies between QL packs (see examples below). - * - ``version`` - - ``0.0.0`` - - All packs - - A version number for this QL pack. This must be a valid semantic version that meets the `SemVer v2.0.0 specification `__. - * - ``libraryPathDependencies`` - - ``codeql/javascript-all`` - - Optional - - The names of any QL packs that this QL pack depends on, as a sequence. This gives the pack access to any libraries, database schema, and query suites defined in the dependency. - * - ``suites`` - - ``suites`` - - Optional - - The path to a directory in the pack that contains the query suites you want to make known to the CLI, defined relative to the pack directory. QL pack users can run "well-known" suites stored in this directory by specifying the pack name, without providing their full path. For more information about query suites, see ":doc:`Creating CodeQL query suites `." - * - ``extractor`` - - ``javascript`` - - All test packs - - The CodeQL language extractor to use when the CLI creates a database from test files in the pack. For more information about testing queries, see ":doc:`Testing custom queries `." - * - ``tests`` - - ``.`` - - Optional for test packs - - Supported from release 2.1.0 onwards. The path to a directory within the pack that contains tests, defined relative to the pack directory. Use ``.`` to specify the whole pack. Any queries in this directory are run as tests when ``test run`` is run with the ``--strict-test-discovery`` option. These queries are ignored by query suite definitions that use ``queries`` or ``qlpack`` instructions to ask for all queries in a particular pack. - * - ``dbscheme`` - - ``semmlecode.python.dbscheme`` - - Core language pack only - - The path to the :ref:`database schema ` for all libraries and queries written for this CodeQL language (see example below). - * - ``upgrades`` - - ``.`` - - Packs with upgrades - - The path to a directory within the pack that contains upgrade scripts, defined relative to the pack directory. The ``database upgrade`` action uses these scripts to update databases that were created by an older version of an extractor so they're compatible with the current extractor (see `Upgrade scripts for a language <#upgrade-scripts-for-a-language>`__ below.) - * - ``dependencies`` - - .. code-block:: yaml - - dependencies: - codeql/cpp-all: ^0.0.2 - - - Packs that define CodeQL package dependencies on other packs - - A map from pack references to the semantic version range that is compatible with this pack. Supported from CLI version v2.6.0 and onwards. - * - ``defaultSuiteFile`` - - ``defaultSuiteFile: cpp-code-scanning.qls`` - - Packs that export a set of default queries to run - - The path to a query suite file containing all of the queries that are run by default when this pack is passed to the ``codeql database analyze`` command. Supported from CLI version v2.6.0 and onwards. - -.. _custom-ql-packs: - -Examples of custom QL packs ---------------------------- - -When you write custom queries or tests, you should save them in -custom QL packs. For simplicity, try to organize each pack logically. For more -information, see `QL pack structure <#ql-pack-structure>`__. Save files for queries -and tests in separate packs and, where possible, organize custom packs into specific -folders for each target language. - -QL packs for custom queries -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A custom QL pack for queries must include a ``qlpack.yml`` file at -the pack root, containing ``name``, ``version``, -and ``libraryPathDependencies`` properties. If the pack contains query suites, you can -use the ``suites`` property to define their location. Query suites defined -here are called "well-known" suites, and can be used on the command line by referring to -their name only, rather than their full path. -For more information about query suites, see ":doc:`Creating CodeQL query suites `." - -For example, a ``qlpack.yml`` file for a QL pack featuring custom C++ queries -and libraries may contain: - -.. code-block:: yaml - - name: my-custom-queries - version: 0.0.0 - libraryPathDependencies: codeql/cpp-all - suites: my-custom-suites - -where ``codeql/cpp-all`` is the name of the QL pack for C/C++ analysis included in -the CodeQL repository. - -.. pull-quote:: - - Note - - When you create a custom QL pack, it's usually a good idea to add it to the search path in your CodeQL configuration. - This will ensure that any libraries the pack contains are available to the CodeQL CLI. - For more information, see ":ref:`Specifying command options in a CodeQL configuration file `." - -QL packs for custom test files -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For custom QL packs containing test files, you also need to include an -``extractor`` property so that the ``test run`` command knows how to create test -databases. You may also wish to specify the ``tests`` property. - -.. include:: ../reusables/test-qlpack.rst - -For more information about running tests, see ":doc:`Testing custom queries -`." - -.. _standard-ql-packs: - -Examples of QL packs in the CodeQL repository ---------------------------------------------- - -Each of the languages in the CodeQL repository has four main QL packs: - -- Core library pack for the language, with the :ref:`database schema ` - used by the language, and CodeQL libraries, and queries at ``ql//ql/lib`` -- Core query pack for the language that includes the default queries for the language, along - with their query suites at ``ql//ql/src`` -- Tests for the core language libraries and queries at ``ql//ql/test`` -- Upgrade scripts for the language at ``ql//upgrades`` - -Core library pack -~~~~~~~~~~~~~~~~~ - -The ``qlpack.yml`` file for a core library pack uses the following properties: -``name``, ``version``, ``dbscheme``. -The ``dbscheme`` property should only be defined in the core QL -pack for a language. - -For example, the ``qlpack.yml`` file for `C/C++ analysis libraries -`__ -contains: - -.. code-block:: yaml - - name: codeql/cpp-all - version: 0.0.0 - dbscheme: semmlecode.cpp.dbscheme - upgrades: upgrades - -Core query pack -~~~~~~~~~~~~~~~ - -The ``qlpack.yml`` file for a core query pack uses the following properties: -``name``, ``version``, ``suites``, ``defaultSuiteFile``, ``dependencies`` . - -For example, the ``qlpack.yml`` file for `C/C++ analysis queries -`__ -contains: - -.. code-block:: yaml - - name: codeql/cpp-queries - version: 0.0.0 - suites: codeql-suites - defaultSuiteFile: codeql-suites/cpp-code-scanning.qls - dependencies: - codeql/cpp-all: "*" - codeql/suite-helpers: "*" - -Tests for the core QL pack -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``qlpack.yml`` file for the tests for the core QL packs use the following -properties: ``name``, ``version``, and ``dependencies``. -The ``dependencies`` always specifies the core QL pack. - -For example, the ``qlpack.yml`` file for `C/C++ analysis tests -`__ -contains: - -.. code-block:: yaml - - name: codeql/cpp-tests - version: 0.0.0 - dependencies: - codeql/cpp-all: "*" - codeql/cpp-queries: "*" - - -.. _upgrade-ql-packs: diff --git a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst index bb428f2c00d..cf12953f600 100644 --- a/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/analyzing-databases-with-the-codeql-cli.rst @@ -36,6 +36,7 @@ You can analyze a database by running the following command:: codeql database analyze --format= --output= + You must specify: - ````: the path to the CodeQL database you want to analyze. @@ -58,9 +59,10 @@ You can also specify: - a path to a directory containing query files - a path to a query suite file - the name of a CodeQL query pack - If omitted, the default query suite for the language - of the database being analyzed will be used. For more information, see the - :ref:`examples ` below. + - with an optional version range + - with an optional path to a query, directory, or query suite inside the pack + + If omitted, the default query suite for the language of the database being analyzed will be used. For more information, see the :ref:`examples ` below. - ``--sarif-category``: an identifying category for the results. Used when you want to upload more than one set of results for a commit. @@ -78,17 +80,17 @@ You can also specify: - .. include:: ../reusables/threads-query-execution.rst - .. pull-quote:: Upgrading databases - If the CodeQL queries you want to use are newer than the - extractor used to create the database, then you may see a message telling you + For databases that were created by CodeQL CLI v2.3.3 or earlier, you will need + to explicitly upgrade the database before you can run an analysis with a newer + version of the CodeQL CLI. If this step is necessary, then you will see a message telling you that your database needs to be upgraded when you run ``database analyze``. - You can quickly upgrade a database by running the ``database upgrade`` - command. For more information, see ":doc:`Upgrading CodeQL databases - `." + + For databases that were created by CodeQL CLI v2.3.4 or later, the CLI will implicitly run any + required upgrades. Explicitly running the upgrade command is not necessary. For full details of all the options you can use when analyzing databases, see the `database analyze reference documentation <../manual/database-analyze>`__. @@ -122,6 +124,14 @@ You can also run your own custom queries with the ``database analyze`` command. For more information about preparing your queries to use with the CodeQL CLI, see ":doc:`Using custom queries with the CodeQL CLI `." +If you do not have the CodeQL repository checked out, you can execute the same queries by specifying the query pack name and the path to the queries:: + + codeql database analyze --download codeql/javascript-queries:Declarations/UnusedVariable.ql --format=csv --output=js-analysis/js-results.csv + +Use the ``--download`` flag to download the query pack if it isn't yet available locally. + +.. _run-query-pack: + Running a CodeQL pack ~~~~~~~~~~~~~~~~~~~~~ @@ -135,6 +145,34 @@ pack names and use the ``--download`` flag:: The ``analyze`` command above runs the default suite from ``microsoft/coding-standards v1.0.0`` and the latest version of ``github/security-queries`` on the specified database. For further information about default suites, see ":ref:`Publishing and using CodeQL packs `". +Running all queries in a directory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can run all the queries located in a directory by providing the directory +path, rather than listing all the individual query files. Paths are searched +recursively, so any queries contained in subfolders will also be executed. + +.. pull-quote:: + + Important + + You should avoid specifying the root of a :ref:`core CodeQL query pack + ` when executing ``database analyze`` + as it might contain some special queries that aren't designed to be used with + the command. Rather, :ref:`run the query pack ` to include the + pack's default queries in the analysis, or run one of the + code scanning query suites. + +For example, to execute all Python queries contained in the ``Functions`` directory you would run:: + + codeql database analyze ../ql/python/ql/src/Functions/ --format=sarif-latest --output=python-analysis/python-results.sarif + +When the analysis has finished, a SARIF results file is generated. Specifying ``--format=sarif-latest`` ensures +that the results are formatted according to the most recent SARIF specification +supported by CodeQL. + +.. _including-query-help-for-custom-codeql-queries-in-sarif-files: + Running a subset of queries in a CodeQL pack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -192,10 +230,10 @@ For more information, see `Analyzing a CodeQL database `__ in the GitHub documentation. CodeQL query suites are ``.qls`` files that use directives to select queries to run -based on certain metadata properties. The standard QL packs have metadata that specify +based on certain metadata properties. The standard CodeQL packs have metadata that specify the location of the query suites used by code scanning, so the CodeQL CLI knows where to find these suite files automatically, and you don't have to specify the full path on the command line. -For more information, see ":ref:`About QL packs `." +For more information, see ":ref:`About CodeQL packs `." The standard query suites are stored at the following paths in the CodeQL repository:: @@ -227,35 +265,6 @@ Integrating a CodeQL pack into a code scanning workflow in GitHub You can use CodeQL query packs in your code scanning setup. This allows you to select query packs published by various sources and use them to analyze your code. For more information, see "`Using CodeQL query packs in the CodeQL action `_" or "`Downloading and using CodeQL query packs in your CI system `_." - -Running all queries in a directory -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can run all the queries located in a directory by providing the directory -path, rather than listing all the individual query files. Paths are searched -recursively, so any queries contained in subfolders will also be executed. - -.. pull-quote:: - - Important - - You shouldn't specify the root of a :doc:`QL pack - ` when executing ``database analyze`` - as it contains some special queries that aren't designed to be used with - the command. Rather, to run a wide range of useful queries, run one of the - LGTM.com query suites. - -For example, to execute all Python queries contained in the ``Functions`` -directory you would run:: - - codeql database analyze ../ql/python/ql/src/Functions/ --format=sarif-latest --output=python-analysis/python-results.sarif - -A SARIF results file is generated. Specifying ``--format=sarif-latest`` ensures -that the results are formatted according to the most recent SARIF specification -supported by CodeQL. - -.. _including-query-help-for-custom-codeql-queries-in-sarif-files: - Including query help for custom CodeQL queries in SARIF files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/codeql/codeql-cli/codeql-cli-reference.rst b/docs/codeql/codeql-cli/codeql-cli-reference.rst index e0ffdeaaa36..a1928e2439d 100644 --- a/docs/codeql/codeql-cli/codeql-cli-reference.rst +++ b/docs/codeql/codeql-cli/codeql-cli-reference.rst @@ -3,22 +3,21 @@ CodeQL CLI reference ==================== -Learn more about the files you can use when running CodeQL processes and the results format and exit codes that CodeQL generates. +Learn more about the files you can use when running CodeQL processes and the results format and exit codes that CodeQL generates. .. toctree:: :titlesonly: :hidden: about-codeql-packs - about-ql-packs + about-codeql-workspaces query-reference-files sarif-output exit-codes extractor-options -- :doc:`About CodeQL packs `: CodeQL packs are created with the CodeQL CLI and are used to create, depend on, publish, and run CodeQL queries and libraries. -- :doc:`About QL packs `: QL packs are used to organize the files used in CodeQL analysis. They - contain queries, library files, query suites, and important metadata. +- :doc:`About CodeQL packs `: CodeQL packs are created with the CodeQL CLI and are used to create, depend on, publish, and run CodeQL queries, libraries, and query suites. +- :doc:`About CodeQL workspaces `: CodeQL workspaces are used to group multiple CodeQL packs together. - :doc:`Query reference files `: A query reference file is text file that defines the location of one query to test. - :doc:`SARIF output `: CodeQL supports SARIF as an output format for sharing static analysis results. - :doc:`Exit codes `: The CodeQL CLI reports the status of each command it runs as an exit code. diff --git a/docs/codeql/codeql-cli/creating-and-working-with-codeql-packs.rst b/docs/codeql/codeql-cli/creating-and-working-with-codeql-packs.rst index da7a0872803..7d2001dded5 100644 --- a/docs/codeql/codeql-cli/creating-and-working-with-codeql-packs.rst +++ b/docs/codeql/codeql-cli/creating-and-working-with-codeql-packs.rst @@ -34,24 +34,28 @@ You must specify: The ``codeql pack init`` command creates the directory structure and configuration files for a CodeQL pack. By default, the command creates a query pack. If you want to create a library pack, you must edit the ``qlpack.yml`` file to explicitly declare the file as a library pack by including the ``library:true`` property. -Modifying an existing QL pack to create a CodeQL pack ------------------------------------------------------ +Modifying an existing legacy QL pack to create a CodeQL pack +------------------------------------------------------------ + If you already have a ``qlpack.yml`` file, you can edit it manually to convert it into a CodeQL pack. #. Edit the ``name`` property so that it matches the format ``/``, where ```` is the name of the GitHub organization or user account that you will publish to. #. In the ``qlpack.yml`` file, include a ``version`` property with a semver identifier, as well as an optional ``dependencies`` block. +#. Migrate the list of dependencies in ``libraryPathDependencies`` to the ``dependencies`` block. Specify the version range for each dependency. If the range is unimportant, or you are unsure of compatibility, you can specify ``"*"``, which indicates that any version is acceptable and will default to the latest version when you run ``codeql pack install``. For more information about the properties, see ":ref:`About CodeQL packs `." +.. _adding-and-installing-dependencies: + Adding and installing dependencies to a CodeQL pack --------------------------------------------------- -You can add dependencies on CodeQL packs using the command ``codeql pack add``. You must specify the scope, name, and version range. +You can add dependencies on CodeQL packs using the command ``codeql pack add``. You must specify the scope, name, and (optionally) a compatible version range. :: codeql pack add /@x.x.x / -The version range is optional. If you leave off the version range, the latest version will be added. Otherwise, the latest version that satisfies the requested range will be added. +If you don't specify a version range, the latest version will be added. Otherwise, the latest version that satisfies the requested range will be added. This command updates the ``qlpack.yml`` file with the requested dependencies and downloads them into the package cache. Please note that this command will reformat the file and remove all comments. @@ -67,7 +71,8 @@ This command downloads all dependencies to the shared cache on the local disk. Note - Running the ``codeql pack add`` and ``codeql pack install`` commands will generate or update the ``qlpack.lock.yml`` file. This file should be checked-in to version control. The ``qlpack.lock.yml`` file contains the precise version numbers used by the pack. + Running the ``codeql pack add`` and ``codeql pack install`` commands will generate or update the ``codeql-pack.lock.yml`` file. This file should be checked-in to version control. The ``codeql-pack.lock.yml`` file contains the precise version numbers used by the pack. + For more information, see ":ref:`About codeql-pack.lock.yml files `." .. pull-quote:: diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index aa60cb24e79..28d4289694b 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -7,8 +7,8 @@ Before you analyze your code using CodeQL, you need to create a CodeQL database containing all the data required to run queries on your code. CodeQL analysis relies on extracting relational data from your code, and -using it to build a :ref:`CodeQL database `. CodeQL -databases contain all of the important information about a codebase, which can +using it to build a :ref:`CodeQL database `. CodeQL +databases contain all of the important information about a codebase, which can be analyzed by executing CodeQL queries against it. Before you generate a CodeQL database, you need to: @@ -18,9 +18,9 @@ Before you generate a CodeQL database, you need to: should be ready to build, with all dependencies already installed. For information about using the CodeQL CLI in a third-party CI system to create results -to display in GitHub as code scanning alerts, see `Configuring CodeQL CLI in your CI system `__ +to display in GitHub as code scanning alerts, see `Configuring CodeQL CLI in your CI system `__ in the GitHub documentation. For information about enabling CodeQL code scanning using GitHub Actions, -see `Setting up code scanning for a repository `__ +see `Setting up code scanning for a repository `__ in the GitHub documentation. Running ``codeql database create`` @@ -37,38 +37,38 @@ You must specify: - ````: a path to the new database to be created. This directory will be created when you execute the command---you cannot specify an existing - directory. + directory. - ``--language``: the identifier for the language to create a database for. - When used with ``--db-cluster``, the option accepts a comma-separated list, + When used with ``--db-cluster``, the option accepts a comma-separated list, or can be specified more than once. CodeQL supports creating databases for the following languages: .. include:: ../reusables/extractors.rst -You can specify additional options depending on the location of your source file, -if the code needs to be compiled, and if you want to create CodeQL databases for +You can specify additional options depending on the location of your source file, +if the code needs to be compiled, and if you want to create CodeQL databases for more than one language: - ``--source-root``: the root folder for the primary source files used in database creation. By default, the command assumes that the current directory is the source root---use this option to specify a different location. - ``--db-cluster``: use for multi-language codebases when you want to create - databases for more than one language. + databases for more than one language. - ``--command``: used when you create a database for one or more compiled languages, - omit if the only languages requested are Python and JavaScript. - This specifies the build commands needed to invoke the compiler. + omit if the only languages requested are Python and JavaScript. + This specifies the build commands needed to invoke the compiler. Commands are run from the current folder, or ``--source-root`` if specified. If you don't include a ``--command``, CodeQL will attempt to - detect the build system automatically, using a built-in autobuilder. -- ``--no-run-unnecessary-builds``: used with ``--db-cluster`` to suppress the build - command for languages where the CodeQL CLI does not need to monitor the build + detect the build system automatically, using a built-in autobuilder. +- ``--no-run-unnecessary-builds``: used with ``--db-cluster`` to suppress the build + command for languages where the CodeQL CLI does not need to monitor the build (for example, Python and JavaScript/TypeScript). You can specify extractor options to customize the behavior of extractors that create CodeQL databases. For more information, see ":doc:`Extractor options `." For full details of all the options you can use when creating databases, -see the `database create reference documentation <../manual/database-create>`__. +see the `database create reference documentation <../manual/database-create>`__. Progress and results -------------------- @@ -117,7 +117,7 @@ extract both JavaScript and TypeScript files:: Here, we have specified a ``--source-root`` path, which is the location where database creation is executed, but is not necessarily the checkout root of the -codebase. +codebase. By default, files in ``node_modules`` and ``bower_components`` directories are not extracted. @@ -127,7 +127,7 @@ Python When creating databases for Python you must ensure: - You have the all of the required versions of Python installed. -- You have access to the `pip `__ +- You have access to the `pip `__ packaging management system and can install any packages that the codebase depends on. - You have installed the `virtualenv `__ pip module. @@ -143,14 +143,14 @@ generating a new Python database at ``/python-database``. Ruby ~~~~ -Creating databases for Ruby requires no additional dependencies. +Creating databases for Ruby requires no additional dependencies. In the command line you must specify ``--language=ruby``. For example:: codeql database create --language=ruby --source-root /ruby-database Here, we have specified a ``--source-root`` path, which is the location where database creation is executed, but is not necessarily the checkout root of the -codebase. +codebase. Creating databases for compiled languages ----------------------------------------- @@ -179,11 +179,11 @@ build steps, you may need to explicitly define each step in the command line. .. pull-quote:: Creating databases for Go - + For Go, install the Go toolchain (version 1.11 or later) and, if there are dependencies, the appropriate dependency manager (such as `dep `__). - + The Go autobuilder attempts to automatically detect code written in Go in a repository, and only runs build scripts in an attempt to fetch dependencies. To force CodeQL to limit extraction to the files compiled by your build script, set the environment variable @@ -194,7 +194,7 @@ Specifying build commands ~~~~~~~~~~~~~~~~~~~~~~~~~ The following examples are designed to give you an idea of some of the build -commands that you can specify for compiled languages. +commands that you can specify for compiled languages. .. pull-quote:: Important @@ -210,11 +210,10 @@ commands that you can specify for compiled languages. - C# project built using ``dotnet build``:: - For C# projects using either `dotnet build` or `msbuild`, you should specify `/p:UseSharedCompilation=false` - in the build command. It is also a good idea to add `/t:rebuild` to ensure that all code will be built (code - that is not built will not be included in the CodeQL database): + It is a good idea to add `/t:rebuild` to ensure that all code will be built, or do a + prior `dotnet clean` (code that is not built will not be included in the CodeQL database): - codeql database create csharp-database --language=csharp --command='dotnet build /p:UseSharedCompilation=false /t:rebuild' + codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild' - Go project built using the ``CODEQL_EXTRACTOR_GO_BUILD_TRACING=on`` environment variable:: @@ -260,7 +259,7 @@ commands that you can specify for compiled languages. - Project built using a custom build script:: codeql database create new-database --language= --command='./scripts/build.sh' - + This command runs a custom script that contains all of the commands required to build the project. @@ -279,7 +278,7 @@ You must specify: - ````: a path to the new database to be created. This directory will be created when you execute the command---you cannot specify an existing - directory. + directory. - ``--begin-tracing``: creates scripts that can be used to set up an environment in which build commands will be traced. You may specify other options for the ``codeql database init`` command as normal. @@ -349,8 +348,7 @@ The following example shows how you could use indirect build tracing in an Azure - task: VSBuild@1 inputs: solution: '**/*.sln' - # Disable MSBuild shared compilation for C# builds. - msbuildArgs: /p:OutDir=$(Build.ArtifactStagingDirectory) /p:UseSharedCompilation=false + msbuildArgs: /p:OutDir=$(Build.ArtifactStagingDirectory) platform: Any CPU configuration: Release # Execute a clean build, in order to remove any existing build artifacts prior to the build. @@ -388,14 +386,10 @@ Obtaining databases from LGTM.com CodeQL. For each project on LGTM.com, you can download an archived CodeQL database corresponding to the most recently analyzed revision of the code. These databases can also be analyzed using the CodeQL CLI or used with the CodeQL -extension for Visual Studio Code. +extension for Visual Studio Code. .. include:: ../reusables/download-lgtm-database.rst -Before running an analysis, unzip the databases and try :doc:`upgrading ` the -unzipped databases to ensure they are compatible with your local copy of the -CodeQL queries and libraries. - .. pull-quote:: Note diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index ceaa104f4d0..1e212755367 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -4,7 +4,7 @@ Creating CodeQL query suites ============================ CodeQL query suites provide a way of selecting queries, based on their -filename, location on disk or in a QL pack, or metadata properties. +filename, location on disk or in a CodeQL pack, or metadata properties. Create query suites for the queries that you want to frequently use in your CodeQL analyses. @@ -18,8 +18,8 @@ suite definition have been executed, the result is a set of selected queries. .. pull-quote:: Note - Any custom queries that you want to add to a query suite must be in a :doc:`QL - pack ` and contain the correct query metadata. + Any custom queries that you want to add to a query suite must be in a :doc:`CodeQL + pack ` and contain the correct query metadata. For more information, see ":doc:`Using custom queries with the CodeQL CLI `." @@ -35,7 +35,7 @@ queries using: - query: - The argument must be one or more file paths, relative to the QL pack containing + The argument must be one or more file paths, relative to the CodeQL pack containing the suite definition. - A ``queries`` instruction---tells CodeQL to recursively scan a directory @@ -43,22 +43,30 @@ queries using: - queries: - The path of the directory must be relative to the root of the QL pack that + The path of the directory must be relative to the root of the CodeQL pack that contains the suite definition file. To find the queries relative to a - different QL pack, add a ``from`` field:: + different CodeQL pack, add a ``from`` field:: - queries: from: + version: ^x.y.z + + The ``version`` field is optional and specifies a range of compatible versions of this CodeQL pack. + If you don't specify a version, then the most recent version of the pack is used. - A ``qlpack`` instruction---tells CodeQL to resolve queries in the default suite of the - named QL pack:: + named CodeQL pack:: - qlpack: + version: ^x.y.z The default suite of a query pack includes a recommended set of queries inside of that query pack. Not all query packs have a default suite. If the given query pack does not define a default suite, the `qlpack` instruction will resolve to all of the queries within the pack. + The ``version`` field is optional and specifies a range of compatible versions of this CodeQL pack. + If you don't specify a version, then the most recent version of the pack is used. + .. pull-quote:: Note When pathnames appear in query suite definitions, they must always @@ -68,7 +76,7 @@ queries using: You must add at least one ``query``, ``queries``, or ``qlpack`` instruction to your suite definition, otherwise no queries will be selected. If the suite contains no further instructions, all the queries found from the list of files, -in the given directory, or in the named QL pack are selected. If there are further +in the given directory, or in the named CodeQL pack are selected. If there are further filtering instructions, only queries that match the constraints imposed by those instructions will be selected. @@ -117,7 +125,7 @@ In addition to metadata tags, the keys in the constraint block can also be: - ``query filename``---matches on the last path component of the query file name. - ``query path``---matches on the path to the query file relative to its - enclosing QL pack. + enclosing CodeQL pack. - ``tags contain``---one of the given match strings must match one of the space-separated components of the value of the ``@tags`` metadata property. - ``tags contain all``---each of the given match strings must match one of the @@ -127,7 +135,7 @@ Examples ~~~~~~~~ To define a suite that selects all queries in the default suite of the -``codeql/cpp-queries`` QL pack, and then refines them to only include +``codeql/cpp-queries`` CodeQL pack, and then refines them to only include security queries, use:: - qlpack: codeql/cpp-queries @@ -153,7 +161,7 @@ recommendation``, use:: problem.severity: recommendation To create a suite that selects all queries with ``@tag security`` and -``@problem.severity high`` or ``very-high`` from the ``codeql/cpp-queries`` QL pack, +``@problem.severity high`` or ``very-high`` from the ``codeql/cpp-queries`` CodeQL pack, use:: - queries: . @@ -174,12 +182,16 @@ Existing query suite definitions can be reused by specifying: - import: - The path to the imported suite must be relative to the QL pack containing the + The path to the imported suite must be relative to the CodeQL pack containing the current suite definition. If the imported query suite is in a different QL pack you can use:: - import: from: + version: ^x.y.z + + The ``version`` field is optional and specifies a range of compatible versions of this CodeQL pack. + If you don't specify a version, then the most recent version of the pack is used. Queries added using an ``import`` instruction can be filtered using subsequent ``exclude`` instructions. @@ -200,6 +212,8 @@ Existing query suite definitions can be reused by specifying: instruction, but takes a full suite definition as the argument, rather than the path to a ``.qls`` file on disk. +To see what queries are included in a query suite, you can run the ``codeql resolve queries my-suite.qls`` command. + Example ~~~~~~~ @@ -216,28 +230,27 @@ following in a file called ``reusable-instructions.yml``:: - high - very-high -Add ``reusable-instructions.yml`` to the same QL pack as your current query -suite (for example, ``my-custom-queries``). Apply the reusable instructions -to the queries in your current suite using:: - - - qlpack: my-custom-queries - - apply: reusable-instructions.yml - -To apply the same conditions to a different suite or directory within the same -QL pack, create a new definition and change (or replace) the ``qlpack`` -instruction. For example:: +Add ``reusable-instructions.yml`` to the same CodeQL pack as your current query +suite. Then, in one or more query suites, use the ``apply`` instruction to apply +the reusable instructions to the current suite. For example:: - queries: queries/cpp/custom - apply: reusable-instructions.yml +This will filter the queries in ``queries/cpp/custom`` to only include those that match the reusable conditions. + You can also create a suite definition using ``reusable-instructions.yml`` on -queries in a different QL pack. If the ``.qls`` file is in the same QL pack as +queries in a different CodeQL pack. If the ``.qls`` file is in the same CodeQL pack as the queries, you can add a ``from`` field immediately after the ``apply`` instruction:: - - qlpack: my-other-custom-queries + # load queries from the default suite of my-org/my-other-custom-queries + - qlpack: my-org/my-other-custom-queries + + # apply the reusable instructions from the my-org/my-custom-instructions CodeQL pack - apply: reusable-instructions.yml - from: + from: my-org/my-custom-instructions + version: ^1.2.3 # optional Naming a query suite -------------------- @@ -255,20 +268,20 @@ directory. For more information, see "`Specifying well-known query suites Saving a query suite -------------------- -Save your query suite in a file with a ``.qls`` extension and add it to a QL -pack. For more information, see ":ref:`About QL packs `." +Save your query suite in a file with a ``.qls`` extension and add it to a CodeQL +pack. For more information, see ":ref:`About CodeQL packs `." Specifying well-known query suites ---------------------------------- -You can use QL packs to declare directories that contain "well-known" query +You can use CodeQL packs to declare directories that contain "well-known" query suites. You can use "well-known" query suites on the command line by referring to their file name, without providing their full path. This gives you a simple way of specifying a -set of queries, without needing to search inside QL packs and distributions. +set of queries, without needing to search inside CodeQL packs and distributions. To declare a directory that contains "well-known" query suites, add the directory -to the ``suites`` property in the ``qlpack.yml`` file at the root of your QL pack. -For more information, see ":ref:`About QL packs `." +to the ``suites`` property in the ``qlpack.yml`` file at the root of your CodeQL pack. +For more information, see ":ref:`About CodeQL packs `." Using query suites with CodeQL ------------------------------ @@ -288,7 +301,7 @@ JavaScript, visit https://github.com/github/codeql/tree/main/javascript/ql/src/codeql-suites. These suite definitions apply reusable filter patterns to the queries -located in the standard QL packs for each supported language. For more +located in the standard CodeQL packs for each supported language. For more information, see the `suite-helpers `__ in the CodeQL repository. diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index f859f07cb7c..0fd8e6b8fa0 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -23,11 +23,11 @@ and 4 are slightly different---for further details, see the sections labeled **Information for macOS "Catalina" (or newer) users**. If you are using macOS on Apple Silicon (e.g. Apple M1), ensure that the `Xcode command-line developer tools `__ and `Rosetta 2 -`__ are installed. +`__ are installed. .. pull-quote:: Note - The CodeQL CLI is currently not compatible with non-glibc Linux + The CodeQL CLI is currently not compatible with non-glibc Linux distributions such as (muslc-based) Alpine Linux. For information about installing the CodeQL CLI in a CI system to create results @@ -47,7 +47,7 @@ Conditions `__. .. pull-quote:: Important - There are several different versions of the CLI available to download, depending + There are different versions of the CLI available to download, depending on your use case: - If you want to use the most up to date CodeQL tools and features, download the @@ -202,8 +202,6 @@ CLI that you will extract in step 4. If you use git on the command line, you can clone and rename the repository in a single step by running ``git clone git@github.com:github/codeql.git codeql-repo`` in the ``codeql-home`` folder. -For Go analysis, run ``codeql-repo/go/scripts/install-deps.sh`` to install its dependencies. - .. pull-quote:: Note The CodeQL libraries and queries for Go analysis used to live in a @@ -213,10 +211,10 @@ For Go analysis, run ``codeql-repo/go/scripts/install-deps.sh`` to install its d For more information, see the `Relocation announcement `__. -Within this repository, the queries and libraries are organized into QL -packs. Along with the queries themselves, QL packs contain important metadata +Within this repository, the queries and libraries are organized into CodeQL +packs. Along with the queries themselves, CodeQL packs contain important metadata that tells the CodeQL CLI how to process the query files. For more information, -see ":doc:`About QL packs `." +see ":doc:`About CodeQL packs `." .. pull-quote:: Important @@ -232,10 +230,7 @@ see ":doc:`About QL packs `." may need to be upgraded before you can analyze them. - For the most up to date CodeQL queries, check out the ``main`` branch. - This branch represents the very latest version of CodeQL's analysis. Even - databases created using the most recent version of the CLI may have to be - upgraded before you can analyze them. For more information, see - ":doc:`Upgrading CodeQL databases `." + This branch represents the very latest version of CodeQL's analysis. - For the queries used in a particular LGTM Enterprise release, check out the branch tagged with the relevant release number. For example, the branch @@ -245,7 +240,7 @@ see ":doc:`About QL packs `." `__ in the LGTM admin help. -4. Extract the zip archive +1. Extract the zip archive ~~~~~~~~~~~~~~~~~~~~~~~~~~ For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier) @@ -271,8 +266,8 @@ up to create and analyze databases: - Run ``codeql resolve languages`` to show which languages are available for database creation. This will list the languages supported by default in your CodeQL CLI package. -- Run ``codeql resolve qlpacks`` to show which QL packs the CLI can find. This - will display the names of all the QL packs directly available to the CodeQL CLI. +- Run ``codeql resolve qlpacks`` to show which CodeQL packs the CLI can find. This + will display the names of all the CodeQL packs directly available to the CodeQL CLI. This should include: - Query packs for each supported language, for example, ``codeql/{language}-queries``. diff --git a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst index 985ca2659f3..3aa61e2b7fe 100644 --- a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst +++ b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst @@ -60,12 +60,13 @@ To analyze a CodeQL database with a CodeQL pack, run the following command: :: - codeql database analyze /@x.x.x + codeql database analyze /@x.x.x: - ````: the CodeQL database to be analyzed. - ````: the name of the GitHub organization that the pack is published to. - ````: the name for the pack that you are using. - ``@x.x.x``: an optional version number. If omitted, the latest version will be used. +- ``:``: an optional path to a query, directory, or query suite. If omitted, the pack's default query suite will be used. The ``analyze`` command will run the default suite of any specified CodeQL packs. You can specify multiple CodeQL packs to be used for analyzing a CodeQL database. For example: diff --git a/docs/codeql/codeql-cli/query-reference-files.rst b/docs/codeql/codeql-cli/query-reference-files.rst index f19996aae29..ea1624e3982 100644 --- a/docs/codeql/codeql-cli/query-reference-files.rst +++ b/docs/codeql/codeql-cli/query-reference-files.rst @@ -10,10 +10,10 @@ to run a query that's not part of a test directory. There are two ways to specify queries that you want to run as tests: #. Use a query reference file to specify the location of a query to test. - This is useful when you create tests for alert and path queries that - are intended to identify problems in real codebases. You might create + This is useful when you create tests for alert and path queries that + are intended to identify problems in real codebases. You might create several directories of test code, each focusing on different - aspects of the query. Then you would add a query reference file to + aspects of the query. Then you would add a query reference file to each directory of test code, to specify the query to test. #. Add the query directly to a directory of tests. These is typically useful when you're writing queries explicitly to test the behavior @@ -25,22 +25,24 @@ Defining a query reference file Each query reference file, ``.qlref``, contains a single line that defines where to find one query. The location must be defined relative -to the root of the QL pack that contains the query. -Usually, this is a QL pack specified by the ``libraryPathDependencies`` for the test pack. +to the root of the CodeQL pack that contains the query. +Usually, this is either the CodeQL pack that contains the ``.qlref``, a CodeQL pack +specified in the ``dependencies`` block for the test pack, or a transitive dependency of +the CodeQL pack. You should use forward slashes in the path on all operating -systems to ensure compatibility between systems. +systems to ensure compatibility between systems. Example -^^^^^^^^ +^^^^^^^ A query reference file to test a JavaScript alert query: `DeadAngularJSEventListener.qlref `__ -The `QL pack `__ -for the ``javascript/ql/test`` directory defines the ``codeql-javascript`` queries as +The ```qlpack.yml`` file `__ +for the CodeQL pack at ``javascript/ql/test`` defines ``codeql/javascript-queries`` as a dependency. So the query reference file defines the location of the query relative -to the ``codeql-javascript`` QL pack:: +to the ``codeql/javascript-queries`` CodeQL pack:: AngularJS/DeadAngularJSEventListener.ql diff --git a/docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst b/docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst index f0b3571feb8..1aef971bea3 100644 --- a/docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst +++ b/docs/codeql/codeql-cli/specifying-command-options-in-a-codeql-configuration-file.rst @@ -8,15 +8,15 @@ configuration file. You can specify CodeQL CLI command options in two ways: -- Directly in the command line, using the appropriate flag. +- Directly in the command line, using the appropriate flag. - In a configuration (or ``config``) file that CodeQL scans for relevant options each time a command is executed. For options that are likely to change each time you execute a command, specifying the value on the command line is the most convenient way of passing the information to CodeQL. Saving options in a ``config`` file is a good way to -specify options you use frequently. -It's also a good way to add custom QL packs that you use regularly to your search path. +specify options you use frequently. +It's also a good way to add custom CodeQL packs that you use regularly to your search path. Using a CodeQL configuration file --------------------------------- @@ -39,7 +39,7 @@ To apply the same options to more than one command you can: .. pull-quote:: Note - + - ``config`` files only accept spaces between between option flags and values---CodeQL will throw an error if you use ``=`` to specify an option value. - If you specify an option in the command line, this overrides the ``config`` @@ -66,7 +66,7 @@ Examples --ram 4096 --threads 4 -- To globally specify a directory for CodeQL to scan for QL packs (which is not a +- To globally specify a directory for CodeQL to scan for CodeQL packs (which is not a sibling of the installation directory), use:: --search-path diff --git a/docs/codeql/codeql-cli/testing-custom-queries.rst b/docs/codeql/codeql-cli/testing-custom-queries.rst index 7f347de8b1c..f6c7f2d32f7 100644 --- a/docs/codeql/codeql-cli/testing-custom-queries.rst +++ b/docs/codeql/codeql-cli/testing-custom-queries.rst @@ -13,10 +13,10 @@ on the query and the expected results until the actual results and the expected results exactly match. This topic shows you how to create test files and execute tests on them using the ``test run`` subcommand. -Setting up a test QL pack for custom queries --------------------------------------------- +Setting up a test CodeQL pack for custom queries +------------------------------------------------ -All CodeQL tests must be stored in a special "test" QL pack. +All CodeQL tests must be stored in a special "test" CodeQL pack. That is, a directory for test files with a ``qlpack.yml`` file that defines: @@ -24,22 +24,25 @@ file that defines: name: version: 0.0.0 - libraryPathDependencies: + dependencies: + : "*" extractor: -The ``libraryPathDependencies`` value specifies the CodeQL queries to test. -The ``extractor`` defines which language the CLI will use -to create test databases from the code files stored in this QL pack. -For more information, see ":doc:`About QL packs `." +The ``dependencies`` value specifies the CodeQL packs containing queries to test. +Typically, these packs will be resolved from source, and so it is not necessary +to specify a fixed version of the pack. +The ``extractor`` defines which language the CLI will use +to create test databases from the code files stored in this CodeQL pack. +For more information, see ":doc:`About CodeQL packs `." -You may find it useful to look at the way query tests are organized in the -`CodeQL repository `__. -Each language has a ``src`` directory, ``ql//ql/src``, -that contains libraries and queries for analyzing codebases. -Alongside the ``src`` directory, -there's a ``test`` directory with tests for these libraries and queries. +You may find it useful to look at the way query tests are organized in the +`CodeQL repository `__. +Each language has a ``src`` directory, ``ql//ql/src``, +that contains libraries and queries for analyzing codebases. +Alongside the ``src`` directory, there is a ``test`` directory with tests for +these libraries and queries. -Each ``test`` directory is configured as a test QL pack with two subdirectories: +Each ``test`` directory is configured as a test CodeQL pack with two subdirectories: - ``query-tests`` a series of subdirectories with tests for queries stored in the ``src`` directory. Each subdirectory contains test code and a QL reference file that specifies the query to test. @@ -49,18 +52,18 @@ Each ``test`` directory is configured as a test QL pack with two subdirectories: Setting up the test files for a query ------------------------------------- -For each query you want to test, you should create a sub-directory in the test QL pack. +For each query you want to test, you should create a sub-directory in the test CodeQL pack. Then add the following files to the subdirectory before you run the test command: - A query reference file (``.qlref`` file) defining the location of the query to test. - The location is defined relative to the root of the QL pack that contains the - query. Usually, this is a QL pack specified by the - ``libraryPathDependencies`` for the test pack. + The location is defined relative to the root of the CodeQL pack that contains the + query. Usually, this is a CodeQL pack specified in the + ``dependencies`` block of the test pack. For more information, see ":doc:`Query reference files `." - You don't need to add a query reference file if the query you want to + You do not need to add a query reference file if the query you want to test is stored in the test directory, - but it's generally good practice to store queries separately from tests. + but it is generally good practice to store queries separately from tests. The only exception is unit tests for QL libraries, which tend to be stored in test packs, separate from queries that generate alerts or paths. @@ -68,15 +71,13 @@ Then add the following files to the subdirectory before you run the test command should consist of one or more files containing examples of the code the query is designed to identify. -You can also define the results you expect to see when you run the query against +You can also define the results you expect to see when you run the query against the example code, by creating a file with the extension ``.expected``. Alternatively, you can leave the test command to create the ``.expected`` file -for you. (If you're using CodeQL CLI 2.0.2--2.0.6, you need to create an -``.expected`` file otherwise the command will fail to find your test query. -You can create an empty ``.expected`` file to workaround this limitation.) +for you. For an example showing how to create and test a query, see the `example -<#example>`__ below. +<#example>`__ below. .. pull-quote:: Important @@ -86,14 +87,14 @@ For an example showing how to create and test a query, see the `example it must have the same base name as the corresponding ``.expected`` file. For example, if the query is ``MyJavaQuery.ql``, the expected results file must be ``MyJavaQuery.expected``. - + If you want to specify a ``.qlref`` file in the command, it must have the same base name as the corresponding ``.expected`` file, but the query itself - may have a different name. + may have a different name. The names of the example code files don't have to be consistent with the other test files. All example code files found next to the ``.qlref`` (or ``.ql``) - file and in any subdirectories will be used to create a test database. + file and in any subdirectories will be used to create a test database. Therefore, for simplicity, we recommend you don't save test files in directories that are ancestors of each other. @@ -108,10 +109,10 @@ The ```` argument can be one or more of the following: - Path to a ``.ql`` file. - Path to a ``.qlref`` file that references a ``.ql`` file. -- Path to a directory that will be searched recursively for ``.ql`` and +- Path to a directory that will be searched recursively for ``.ql`` and ``.qlref`` files. -You can also specify: +You can also specify: - .. include:: ../reusables/threads-query-execution.rst @@ -123,7 +124,7 @@ Example The following example shows you how to set up a test for a query that searches Java code for ``if`` statements that have empty ``then`` blocks. It includes -steps to add the custom query and corresponding test files to separate QL packs +steps to add the custom query and corresponding test files to separate CodeQL packs outside your checkout of the CodeQL repository. This ensures when you update the CodeQL libraries, or check out a different branch, you won't overwrite your custom queries and tests. @@ -144,36 +145,36 @@ Prepare a query and test files #. Save the query to a file named ``EmptyThen.ql`` in a directory with your other custom queries. For example, - ``custom-queries/java/queries/EmptyThen.ql``. - -#. If you haven't already added your custom queries to a QL pack, - create a QL pack now. For example, if your custom Java queries + ``custom-queries/java/queries/EmptyThen.ql``. + +#. If you haven't already added your custom queries to a CodeQL pack, + create a CodeQL pack now. For example, if your custom Java queries are stored in ``custom-queries/java/queries``, add a ``qlpack.yml`` file with the following contents to ``custom-queries/java/queries``: .. code-block:: yaml name: my-custom-queries - version: 0.0.0 - libraryPathDependencies: codeql-java + dependencies: + codeql/java-queries: "*" - For more information about QL packs, see ":doc:`About QL packs - `." + For more information about CodeQL packs, see ":doc:`About CodeQL packs + `." -#. Create a QL pack for your Java tests by adding a ``qlpack.yml`` file +#. Create a CodeQL pack for your Java tests by adding a ``qlpack.yml`` file with the following contents to ``custom-queries/java/tests``, - updating ``libraryPathDependencies`` to match the name of your QL pack of custom queries: + updating the ``dependencies`` to match the name of your CodeQL pack of custom queries: .. include:: ../reusables/test-qlpack.rst #. Within the Java test pack, create a directory to contain the test files associated with ``EmptyThen.ql``. - For example, ``custom-queries/java/tests/EmptyThen``. + For example, ``custom-queries/java/tests/EmptyThen``. -#. In the new directory, create ``EmptyThen.qlref`` to define the location of ``EmptyThen.ql``. +#. In the new directory, create ``EmptyThen.qlref`` to define the location of ``EmptyThen.ql``. The path to the query must be specified relative to the root of - the QL pack that contains the query. In this case, the query is in the - top level directory of the QL pack named ``my-custom-queries``, + the CodeQL pack that contains the query. In this case, the query is in the + top level directory of the CodeQL pack named ``my-custom-queries``, which is declared as a dependency for ``my-query-tests``. Therefore, ``EmptyThen.qlref`` should simply contain ``EmptyThen.ql``. @@ -191,7 +192,7 @@ Prepare a query and test files System.out.println("Empty argument"); } } - + public void good(String arg) { if (arg.isEmpty()) { System.out.println("Empty argument"); @@ -211,8 +212,8 @@ When the test runs it: #. Extracts a CodeQL database from the ``.java`` files stored in the ``EmptyThen`` directory. #. Compiles the query referenced by the ``EmptyThen.qlref`` file. - If this step fails, it's because the CLI can't find your custom QL pack. - Re-run the command and specify the location of your custom QL pack, for example: + If this step fails, it's because the CLI can't find your custom CodeQL pack. + Re-run the command and specify the location of your custom CodeQL pack, for example: ``codeql test run --search-path=java java/tests/EmptyThen`` @@ -234,14 +235,14 @@ CodeQL generates the following files in the ``EmptyThen`` directory: When tests complete successfully, this database is deleted in a housekeeping step. You can override this step by running ``test run`` with the ``--keep-databases`` option. -In this case, the failure was expected and is easy to fix. +In this case, the failure was expected and is easy to fix. If you open the ``EmptyThen.actual`` file, you can see the results of the test: .. code-block:: none - + | Test.java:3:5:3:22 | stmt | This if statement has an empty then. | -This file contains a table, with a column for the location of the result, +This file contains a table, with a column for the location of the result, along with separate columns for each part of the ``select`` clause the query outputs. Since the results are what we expected, we can update the file extension to define this as the expected result for this test (``EmptyThen.expected``). @@ -252,17 +253,17 @@ If you rerun the test now, the output will be similar but it will finish by repo If the results of the query change, for example, if you revise the ``select`` statement for the query, the test will fail. For failed results, the CLI output includes a unified diff of the ``EmptyThen.expected`` and ``EmptyThen.actual`` files. -This information may be sufficient to debug trivial test failures. +This information may be sufficient to debug trivial test failures. For failures that are harder to debug, you can import ``EmptyThen.testproj`` into CodeQL for VS Code, execute ``EmptyThen.ql``, and view the results in the ``Test.java`` example code. For more information, see ":ref:`Analyzing your projects `" in the CodeQL for VS Code -help. +help. Further reading --------------- - ":ref:`CodeQL queries `" -- ":ref:`Testing CodeQL queries in Visual Studio Code `" \ No newline at end of file +- ":ref:`Testing CodeQL queries in Visual Studio Code `" diff --git a/docs/codeql/codeql-cli/testing-query-help-files.rst b/docs/codeql/codeql-cli/testing-query-help-files.rst index 26cea264043..d00420d71e9 100644 --- a/docs/codeql/codeql-cli/testing-query-help-files.rst +++ b/docs/codeql/codeql-cli/testing-query-help-files.rst @@ -3,7 +3,7 @@ Testing query help files ======================== -Test query help files by rendering them as markdown to ensure they are valid +Test query help files by rendering them as markdown to ensure they are valid before uploading them to the CodeQL repository or using them in code scanning. Query help is documentation that accompanies a query to explain how the query works, @@ -12,46 +12,46 @@ It is good practice to write query help for all new queries. For more informatio see `Contributing to CodeQL `__ in the CodeQL repository. -The CodeQL CLI includes a command to test query help and render the content as -markdown, so that you can easily preview the content in your IDE. Use the command to validate -query help files before uploading them to the CodeQL repository or sharing them with other users. -From CodeQL CLI 2.7.1 onwards, you can also include the markdown-rendered query help in SARIF files -generated during CodeQL analyses so that the query help can be displayed in the code scanning UI. -For more information, see +The CodeQL CLI includes a command to test query help and render the content as +markdown, so that you can easily preview the content in your IDE. Use the command to validate +query help files before uploading them to the CodeQL repository or sharing them with other users. +From CodeQL CLI 2.7.1 onwards, you can also include the markdown-rendered query help in SARIF files +generated during CodeQL analyses so that the query help can be displayed in the code scanning UI. +For more information, see ":ref:`Analyzing databases with the CodeQL CLI `." Prerequisites ------------- -- The query help (``.qhelp``) file must have an accompanying query (``.ql``) file with +- The query help (``.qhelp``) file must have an accompanying query (``.ql``) file with an identical base name. - The query help file should follow the standard structure and style for query help documentation. - For more information, see the `Query help style guide `__ - in the CodeQL repository. + For more information, see the `Query help style guide `__ + in the CodeQL repository. Running ``codeql generate query-help`` -------------------------------------- You can test query help files by running the following command:: - codeql generate query-help --format= [--output=] + codeql generate query-help --format= [--output=] where ```` is one of: - the path to a ``.qhelp`` file. - the path to a ``.ql`` file. - the path to a directory containing queries and query help files. -- the path to a query suite, or the name of a well-known query suite for a QL pack. +- the path to a query suite, or the name of a well-known query suite for a CodeQL pack. For more information, see "`Creating CodeQL query suites `__." -You must specify a ``--format`` option, which defines how the query help is rendered. -Currently, you must specify ``markdown`` to render the query help as markdown. +You must specify a ``--format`` option, which defines how the query help is rendered. +Currently, you must specify ``markdown`` to render the query help as markdown. The ``--output`` option defines a file path where the rendered query help will be saved. -- For directories containing ``.qhelp`` files or a query suites - defining one or more ``.qhelp`` files, you must specify an ``--output`` directory. - Filenames within the output directory will be derived from the ``.qhelp`` file names. +- For directories containing ``.qhelp`` files or a query suites + defining one or more ``.qhelp`` files, you must specify an ``--output`` directory. + Filenames within the output directory will be derived from the ``.qhelp`` file names. - For single ``.qhelp`` or ``.ql`` files, you may specify an ``--output`` option. If you don't specify an output path, the rendered query help is written to ``stdout``. @@ -63,15 +63,15 @@ see the `generate query-help reference documentation Results ------- -When you run the command, CodeQL attempts to render +When you run the command, CodeQL attempts to render each ``.qhelp`` file that has an accompanying ``.ql`` file. For single files, the rendered -content will be printed to ``stdout`` if you don't specify an ``--output`` option. For all other -use cases, the rendered content is saved to the specified output path. +content will be printed to ``stdout`` if you don't specify an ``--output`` option. For all other +use cases, the rendered content is saved to the specified output path. By default, the CodeQL CLI will print a warning message if: - Any of the query help is invalid, along with a description of the invalid query help elements -- Any ``.qhelp`` files specified in the command don't have the same base name +- Any ``.qhelp`` files specified in the command don't have the same base name as an accompanying ``.ql`` file - Any ``.ql`` files specified in the command don't have the same base name as an accompanying ``.qhelp`` file diff --git a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst b/docs/codeql/codeql-cli/upgrading-codeql-databases.rst deleted file mode 100644 index 334a7501392..00000000000 --- a/docs/codeql/codeql-cli/upgrading-codeql-databases.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _upgrading-codeql-databases: - -Upgrading CodeQL databases -========================== - -As the CodeQL CLI tools and queries evolve, you may find that some of your -CodeQL databases become out of date. You must upgrade out-of-date databases -before you can analyze them. - -Databases become out of date when: - -- For databases created using the CodeQL CLI, the version of CLI tools used to - create them is older than your copy of the CodeQL queries. -- For databases downloaded from LGTM.com, the CodeQL tools used by LGTM.com to create - that revision of the code are older than your copy of the CodeQL queries. - -If you have a local checkout of the ``github/codeql`` repository, please note that -the ``main`` branch of the CodeQL queries is updated more often than both the -CLI and LGTM.com, so databases are most likely to become out of date if you use -the queries on this branch. For more information about the different versions of -the CodeQL queries, see ":ref:`Getting started with the CodeQL CLI `." - -Out-of-date databases must be upgraded before they can be analyzed. This topic -shows you how to upgrade a CodeQL database using the ``database upgrade`` -subcommand. - -Prerequisites -------------- - -Archived databases downloaded from LGTM.com must be unzipped before they are -upgraded. - -Running ``codeql database upgrade`` ------------------------------------ - -CodeQL databases are upgraded by running the following command:: - - codeql database upgrade - -where ````, the path to the CodeQL database you -want to upgrade, must be specified. - -For full details of all the options you can use when upgrading databases, -see the "`database upgrade <../manual/database-upgrade>`__" reference documentation. - -Progress and results --------------------- - -When you execute the ``database upgrade`` command, CodeQL identifies the version -of the :ref:`schema ` associated with the database. From -there, it works out what (if anything) is required to make the database work -with your queries and libraries. It will rewrite the database, if necessary, or -make no changes if the database is already compatible (or if it finds no -information about how to perform an upgrade). Once a database has been upgraded -it cannot be downgraded for use with older versions of the CodeQL products. diff --git a/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst index 8208cd59a56..0af320f9bb5 100644 --- a/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/using-custom-queries-with-the-codeql-cli.rst @@ -54,23 +54,20 @@ Packaging custom QL queries .. include:: ../reusables/beta-note-package-management.rst -When you write your own queries, you should save them in a custom QL pack -directory. When you are ready to share your queries with other users, you can publish the pack as a CodeQL pack to GitHub Packages - the GitHub Container registry. +When you write your own queries with the intention to share them with others, you should +save them in a custom CodeQL pack. You can publish the pack as a CodeQL pack to GitHub +Packages - the GitHub Container registry. For further information see +":ref:`About CodeQL packs `." -QL packs organize the files used in CodeQL analysis and can store queries, +CodeQL packs organize the files used in CodeQL analysis and can store queries, library files, query suites, and important metadata. Their root directory must contain a file named ``qlpack.yml``. Your custom queries should be saved in the -QL pack root, or its subdirectories. +CodeQL pack root, or its subdirectories. -For each QL pack, the ``qlpack.yml`` file includes information that tells CodeQL +For each CodeQL pack, the ``qlpack.yml`` file includes information that tells the CodeQL CLI how to compile the queries, which other CodeQL packs and libraries the pack depends on, and where to find query suite definitions. For more information -about what to include in this file, see ":ref:`About QL packs `." - -CodeQL packages are used to create, share, depend on, and run CodeQL queries and -libraries. You can publish your own CodeQL packages and download ones created by -others via the the Container registry. For further information see -":ref:`About CodeQL packs `." +about what to include in this file, see ":ref:`About CodeQL packs `." Contributing to the CodeQL repository ------------------------------------- diff --git a/docs/codeql/codeql-cli/using-the-codeql-cli.rst b/docs/codeql/codeql-cli/using-the-codeql-cli.rst index 7b67af59c6a..4d5ea6be7a0 100644 --- a/docs/codeql/codeql-cli/using-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/using-the-codeql-cli.rst @@ -7,7 +7,7 @@ Using the CodeQL CLI See the following links to learn how to get set up and run CodeQL commands: -- :doc:`About the CodeQL CLI `: Software +- :doc:`About the CodeQL CLI `: Software developers and security researchers can secure their code using the CodeQL CLI. - :doc:`Getting started with the CodeQL CLI @@ -17,19 +17,15 @@ See the following links to learn how to get set up and run CodeQL commands: - :doc:`Creating CodeQL databases `: Create relational representations of source code that can be queried like any other database. - + - :doc:`Extractor options - `: Set options for the + `: Set options for the behavior of extractors that create CodeQL databases. - :doc:`Analyzing CodeQL databases with the CodeQL CLI `: Analyze your code using queries written in a specially-designed, object-oriented query language. -- :doc:`Upgrading CodeQL databases - `: Upgrade your databases so - that they can be analyzed using the most up to date CodeQL products. - - :doc:`Using custom queries with the CodeQL CLI `: Use custom queries to extend your analysis or highlight errors that are specific to a particular codebase. @@ -42,7 +38,7 @@ See the following links to learn how to get set up and run CodeQL commands: your analysis. - :doc:`Testing query help files `: - Test query help files by rendering them as markdown to ensure they are valid + Test query help files by rendering them as markdown to ensure they are valid before adding them to the CodeQL repository or using them in code scanning. - :doc:`Creating and working with CodeQL packs `: @@ -51,7 +47,7 @@ See the following links to learn how to get set up and run CodeQL commands: - :doc:`Publishing and using CodeQL packs `: Publish your own or use others CodeQL packs for code scanning. -- :doc:`Specifying command options in a CodeQL configuration file `: +- :doc:`Specifying command options in a CodeQL configuration file `: You can save default or frequently used options for your commands in a per-user configuration file. .. toctree:: @@ -63,7 +59,6 @@ See the following links to learn how to get set up and run CodeQL commands: creating-codeql-databases extractor-options analyzing-databases-with-the-codeql-cli - upgrading-codeql-databases using-custom-queries-with-the-codeql-cli creating-codeql-query-suites testing-custom-queries diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index 71f72223620..b23ddacf157 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -19,7 +19,7 @@ To analyze a project, you need to add a :ref:`CodeQL database ` .. image:: ../images/codeql-for-visual-studio-code/choose-database.png :width: 350 :alt: Choose a database to analyze - + For more information about obtaining a local database, see below. #. Once you've chosen a database, it is displayed in the Databases view. To see the menu options for interacting with a database, right-click an entry in the list. You can select multiple databases using **Ctrl/Cmd+click**. @@ -27,7 +27,7 @@ To analyze a project, you need to add a :ref:`CodeQL database ` Obtaining a local database ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you have a CodeQL database saved locally, as an unarchived folder or as a ZIP file, you can add it to Visual Studio Code. There are several ways to obtain a local CodeQL database. +If you have a CodeQL database saved locally, as an unarchived folder or as a ZIP file, you can add it to Visual Studio Code. There are several ways to obtain a local CodeQL database. - To create a database with the CodeQL CLI, see ":ref:`Creating CodeQL databases `." @@ -36,14 +36,14 @@ If you have a CodeQL database saved locally, as an unarchived folder or as a ZIP - To analyze a test database, add a ``.testproj`` folder to the Databases view. Test databases (that is, folders with a ``.testproj`` extension) are generated when you run regression tests on custom queries using the :ref:`CodeQL CLI `. If a query fails a regression test, you may want to analyze the test database in Visual Studio Code to debug the failure. - - For more information about running query tests, see ":ref:`Testing custom queries `" in the CodeQL CLI help. + + For more information about running query tests, see ":ref:`Testing custom queries `" in the CodeQL CLI help. Running a query ------------------------ The `CodeQL repository `__ on GitHub contains lots of example queries. -If you have that folder (or a different QL pack) available in your workspace, you can access existing queries under ``/ql/src/``, for example ``java/ql/src/Likely Bugs``. +If you have that folder (or a different CodeQL pack) available in your workspace, you can access existing queries under ``/ql/src/``, for example ``java/ql/src/Likely Bugs``. #. Open a query (``.ql``) file. It is displayed in the editor, with IntelliSense features such as syntax highlighting and autocomplete suggestions. #. Right-click in the query window and select **CodeQL: Run Query**. (Alternatively, run the command from the Command Palette.) @@ -77,7 +77,7 @@ To run the query, use **CodeQL: Run Query**. You can see all quick queries that you've run in the current session in the Query History view. Click an entry to see the exact text of the quick query that produced the results. -Once you're happy with your quick query, you should save it in a QL pack so you can access it later. For more information, see ":ref:`About QL packs `." +Once you're happy with your quick query, you should save it in a CodeQL pack so you can access it later. For more information, see ":ref:`About CodeQL packs `." .. _running-a-specific-part-of-a-query-or-library: @@ -87,7 +87,7 @@ Running a specific part of a query or library This is helpful if you're debugging a query or library and you want to locate the part that is wrong. Instead of using **CodeQL: Run Query** to run the whole query (the :ref:`select clause ` and any :ref:`query predicates `), you can use **CodeQL: Quick Evaluation** to run a specific part of a ``.ql`` or ``.qll`` file. -**CodeQL: Quick Evaluation** evaluates a code snippet (instead of the whole query) and displays results of that selection in the Results view. +**CodeQL: Quick Evaluation** evaluates a code snippet (instead of the whole query) and displays results of that selection in the Results view. Possible targets for quick evaluation include: - Selecting the name of a CodeQL entity (such as a :ref:`class ` or :ref:`predicate `) to evaluate that entity. 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 b4969ce785d..1c762348a9d 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 @@ -110,7 +110,7 @@ For example, to make a custom CodeQL folder called ``my-custom-cpp-pack`` depend version: 0.0.0 libraryPathDependencies: codeql/cpp-all -For more information about why you need to add a ``qlpack.yml`` file, see ":ref:`About QL packs `." +For more information about why you need to add a ``qlpack.yml`` file, see ":ref:`About CodeQL packs `." Further reading ---------------- diff --git a/docs/codeql/codeql-overview/codeql-glossary.rst b/docs/codeql/codeql-overview/codeql-glossary.rst index 0acc7bd25f1..3770cab7921 100644 --- a/docs/codeql/codeql-overview/codeql-glossary.rst +++ b/docs/codeql/codeql-overview/codeql-glossary.rst @@ -5,7 +5,7 @@ CodeQL glossary =============== -An overview of the technical terms and concepts in CodeQL. +An overview of the technical terms and concepts in CodeQL. .. _bqrs-file: @@ -26,11 +26,11 @@ exported as a variety of different formats, including SARIF. CodeQL database --------------- -A database (or CodeQL database) is a directory containing: +A database (or CodeQL database) is a directory containing: - queryable data, extracted from the code. - a source reference, for displaying query results directly in the code. -- query results. +- query results. - log files generated during database creation, query execution, and other operations. @@ -39,15 +39,15 @@ A database (or CodeQL database) is a directory containing: DIL --- -DIL stands for Datalog Intermediary Language. It is an intermediate -representation between QL and relation algebra (RA) that is generated -during query compilation. DIL is useful for advanced users as an aid -for debugging query performance. +DIL stands for Datalog Intermediary Language. It is an intermediate +representation between QL and relation algebra (RA) that is generated +during query compilation. DIL is useful for advanced users as an aid +for debugging query performance. The DIL format may change without warning between CLI releases. -When you specify the ``--dump-dil`` option for ``codeql query compile``, CodeQL -prints DIL to standard output for the queries it compiles. You can also -view results in DIL format when you run queries in VS Code. +When you specify the ``--dump-dil`` option for ``codeql query compile``, CodeQL +prints DIL to standard output for the queries it compiles. You can also +view results in DIL format when you run queries in VS Code. For more information, see ":ref:`Analyzing your projects `" in the CodeQL for VS Code help. .. _extractor: @@ -56,7 +56,7 @@ Extractor --------- An extractor is a tool that produces the relational data and source -reference for each input file, from which a CodeQL database can be built. +reference for each input file, from which a CodeQL database can be built. .. _codeql-database-schema: @@ -67,7 +67,7 @@ A QL database schema is a file describing the column types and extensional relations that make up a raw QL dataset. It is a text file with the ``.dbscheme`` extension. -The extractor and core QL pack for a language each declare the database +The extractor and core CodeQL pack for a language each declare the database schema that they use. This defines the database layout they create or expect. When you create a CodeQL database, the extractor copies its schema into the database. The CLI uses this to check whether the @@ -83,16 +83,16 @@ There is currently no public-facing specification for the syntax of schemas. -------------- ``.qlo`` files are optionally generated during query compilation. -If you specify the ``--dump-qlo`` option for ``codeql query compile``, +If you specify the ``--dump-qlo`` option for ``codeql query compile``, CodeQL writes ``.qlo`` files for the queries it compiles. They can be used -as an aid for debugging and performance tuning for advanced users. +as an aid for debugging and performance tuning for advanced users. -``.qlo`` is a binary format that represents a compiled -and optimized query in terms of relational algebra (RA) or the -intermediate :ref:`DIL ` format. ``.qlo`` files can be expanded to -readable text using ``codeql query decompile``. +``.qlo`` is a binary format that represents a compiled +and optimized query in terms of relational algebra (RA) or the +intermediate :ref:`DIL ` format. ``.qlo`` files can be expanded to +readable text using ``codeql query decompile``. -The exact details of the ``.qlo`` format may change without warning between CLI releases. +The exact details of the ``.qlo`` format may change without warning between CLI releases. .. _sarif-file: @@ -101,22 +101,22 @@ SARIF file Static analysis results interchange format (SARIF) is an output format used for sharing static analysis results. For more information, see ":ref:`SARIF -output `." +output `." .. _source-reference: Source reference ---------------- -A source reference is a mechanism that allows the retrieval of the -contents of a source file, given an absolute filename at which that file +A source reference is a mechanism that allows the retrieval of the +contents of a source file, given an absolute filename at which that file resided during extraction. Specific examples include: -- A source archive directory, within which the requested absolute +- A source archive directory, within which the requested absolute filename maps to a UTF8-encoded file. -- A source archive, typically in ZIP format, which contains the UTF8-encoded +- A source archive, typically in ZIP format, which contains the UTF8-encoded content of all source files. -- A source archive repository, typically in ``git`` format, typically bare, +- A source archive repository, typically in ``git`` format, typically bare, which contains the UTF8-encoded content of all source files. Source references are typically included in CodeQL databases. @@ -126,7 +126,7 @@ Source references are typically included in CodeQL databases. TRAP file --------- -A TRAP file is a UTF-8 encoded file generated by a CodeQL extractor +A TRAP file is a UTF-8 encoded file generated by a CodeQL extractor with the extension ``.trap``. To save space, they are usually archived. They contain the information that, when interpreted relative to a QL database schema, is used to create a QL dataset. diff --git a/docs/codeql/ql-language-reference/ql-language-specification.rst b/docs/codeql/ql-language-reference/ql-language-specification.rst index 46d0123d6d4..ea90ebbf843 100644 --- a/docs/codeql/ql-language-reference/ql-language-specification.rst +++ b/docs/codeql/ql-language-reference/ql-language-specification.rst @@ -68,7 +68,7 @@ contain a single top-level tag named of the active database schema (for example, ````). -A ``qlpack.yml`` file defines a :ref:`QL pack `. +A ``qlpack.yml`` file defines a :ref:`CodeQL pack `. The content of a ``qlpack.yml`` file is described in the CodeQL CLI documentation. If both a ``queries.xml`` and a ``qlpack.yml`` exist in the same @@ -77,16 +77,16 @@ exist for compatibility with older tooling). The CodeQL CLI and newer tools based on it (such as, GitHub code scanning and the CodeQL extension for Visual Studio Code) -construct a library path using QL packs. For each QL pack -added to the library path, the QL packs named in its +construct a library path using CodeQL packs. For each CodeQL pack +added to the library path, the CodeQL packs named in its ``libraryPathDependencies`` will be subsequently added to the library path, and the process continues until all packs have been resolved. The actual library path consists of the root directories of -the selected QL packs. This process depends on a mechanism for finding -QL packs by pack name, as described in the :ref:`CodeQL CLI documentation `. +the selected CodeQL packs. This process depends on a mechanism for finding +CodeQL packs by pack name, as described in the :ref:`CodeQL CLI documentation `. When the query directory contains a ``queries.xml`` file but no -``qlpack.yml``, the QL pack resolution behaves as if it defines a QL +``qlpack.yml``, the CodeQL pack resolution behaves as if it defines a QL pack with no name and a single library path dependency named ``legacy-libraries-LANGUAGE`` where ``LANGUAGE`` is taken from ``queries.xml``. The ``github/codeql`` repository provides packs with @@ -94,7 +94,7 @@ names following this pattern, which themselves depend on the actual CodeQL libraries for each language. When the query directory contains neither a ``queries.xml`` nor -``qlpack.yml`` file, it is considered to be a QL pack with no name and +``qlpack.yml`` file, it is considered to be a CodeQL pack with no name and no library dependencies. This causes the library path to consist of *only* the query directory itself. This is not generally useful, but it suffices for running toy examples of QL code that don't diff --git a/docs/codeql/reusables/test-qlpack.rst b/docs/codeql/reusables/test-qlpack.rst index fe2fc5f4199..6ba9760248c 100644 --- a/docs/codeql/reusables/test-qlpack.rst +++ b/docs/codeql/reusables/test-qlpack.rst @@ -1,15 +1,9 @@ .. code-block:: yaml - name: my-query-tests - version: 0.0.0 - libraryPathDependencies: my-custom-queries + name: my-github-user/my-query-tests + dependencies: + my-github-user/my-custom-queries: ^1.2.3 extractor: java tests: . -This ``qlpack.yml`` file states that ``my-query-tests`` depends on -``my-custom-queries``. It also declares that the CLI should use the -Java ``extractor`` when creating test databases. -Supported from CLI 2.1.0 onward, the ``tests: .`` line declares -that all ``.ql`` files in the pack should be -run as tests when ``codeql test run`` is run with the -``--strict-test-discovery`` option. +This ``qlpack.yml`` file states that ``my-github-user/my-query-tests`` depends on ``my-github-user/my-custom-queries`` at a version greater than or equal to 1.2.3 and less than 2.0.0. It also declares that the CLI should use the Java ``extractor`` when creating test databases. The ``tests: .`` line declares that all ``.ql`` files in the pack should be run as tests when ``codeql test run`` is run with the ``--strict-test-discovery`` option. Typically, test packs do not contain a ``version`` property. This prevents you from accidentally publishing them. diff --git a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst index be5bca75622..61d81bf6f3e 100644 --- a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst +++ b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst @@ -3,7 +3,7 @@ About CodeQL queries #################### -CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. +CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. Overview ******** @@ -13,7 +13,7 @@ CodeQL includes queries to find the most relevant and interesting problems for e - **Alert queries**: queries that highlight issues in specific locations in your code. - **Path queries**: queries that describe the flow of information between a source and a sink in your code. -You can add custom queries to :doc:`QL packs <../codeql-cli/about-ql-packs>` to analyze your projects with "`Code scanning `__", use them to analyze a database with the ":ref:`CodeQL CLI `," or you can contribute to the standard CodeQL queries in our `open source repository on GitHub `__. +You can add custom queries to :doc:`CodeQL packs <../codeql-cli/about-codeql-packs>` to analyze your projects with "`Code scanning `__", use them to analyze a database with the ":ref:`CodeQL CLI `," or you can contribute to the standard CodeQL queries in our `open source repository on GitHub `__. This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages in the ":ref:`CodeQL language guides `," and detailed technical information about QL in the ":ref:`QL language reference `." For more information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. From 361dba17deb66127d6910893d645feca84c90e5d Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Wed, 7 Sep 2022 15:08:29 -0700 Subject: [PATCH 05/27] Add information about the `registries` block in `codeql-workspace.yml` --- docs/codeql/codeql-cli/about-codeql-workspaces.rst | 7 ++++++- .../codeql-cli/publishing-and-using-codeql-packs.rst | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/about-codeql-workspaces.rst b/docs/codeql/codeql-cli/about-codeql-workspaces.rst index 3f27672d502..bab102d7ff6 100644 --- a/docs/codeql/codeql-cli/about-codeql-workspaces.rst +++ b/docs/codeql/codeql-cli/about-codeql-workspaces.rst @@ -14,10 +14,11 @@ In most cases, you should store the CodeQL workspace and the CodeQL packs contai The ``codeql-workspace.yml`` file --------------------------------- -A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally an ``ignore`` block. +A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally ``ignore``, and ``registries`` blocks. * The ``provide`` block contains a list of glob patterns that define the CodeQL packs that are available in the workspace. * The ``ignore`` block contains a list of glob patterns that define CodeQL packs that are not available in the workspace. +* The ``registries`` block contains a list of GHES URLs and package patterns that control which container registry is used for publishing CodeQL packs. For more information, see :ref:`Working with CodeQL packs on GitHub Enterprise Server `. Each entry in the ``provide`` or ``ignore`` section must map to the location of a ``qlpack.yml`` file. All glob patterns are defined relative to the directory that contains the workspace file. For a list of patterns accepted in this file, see" `@actions/glob `__ . @@ -30,6 +31,10 @@ For example, the following ``codeql-workspace.yml`` file defines a workspace tha ignore: - "*/codeql-packs/**/experimental/**/qlpack.yml" + registries: + - packages: '*' + url: https://containers.GHE_HOSTNAME/v2/ + To verify that your ``codeql-workspace.yml`` file includes the CodeQL packs that you expect, run the ``codeql pack ls`` command in the same directory as your workspace. The result of the command is a list of all CodeQL packs in the workspace. .. _source-dependencies: diff --git a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst index 3aa61e2b7fe..88d57059ea4 100644 --- a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst +++ b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst @@ -74,6 +74,8 @@ The ``analyze`` command will run the default suite of any specified CodeQL packs codeql analyze / / +.. _working-with-codeql-packs-on-ghes: + Working with CodeQL packs on GitHub Enterprise Server ----------------------------------------------------- @@ -91,13 +93,17 @@ For example, the following ``qlconfig.yml`` file associates all packs with the C .. code-block:: yaml registries: - - packages: 'codeql/*' + - packages: + - 'codeql/*' + - 'other-org/*' url: https://ghcr.io/v2/ - packages: '*' url: https://containers.GHE_HOSTNAME/v2/ The CodeQL CLI will determine which registry to use for a given package name by finding the first item in the ``registries`` list with a ``packages`` property that matches that package name. -This means that you'll generally want to define the most specific package name patterns first. +This means that you'll generally want to define the most specific package name patterns first. The ``packages`` property may be a single package name, a glob pattern, or a YAML list of package names and glob patterns. + +The ``registries`` list can also be placed inside of a ``codeql-workspace.yml`` file. Doing so will allow you to fix the registries list for a specific workspace, so that it can be shared amongst other CodeQL users of the workspace. The ``registries`` list in the ``codeql-workspace.yml`` will be merged with and take precedence over the list in the global ``qlconfig.yml``. For more information about ``codeql-workspace.yml``, see :ref:`About CodeQL workspaces `. You can now use ``codeql pack publish``, ``codeql pack download``, and ``codeql database analyze`` to manage packs on GitHub Enterprise Server. From abdc79b009274e9e9215b25e6226fd1c410d59a3 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Fri, 9 Sep 2022 08:27:55 -0700 Subject: [PATCH 06/27] Update the example `codeql-workspace.yml` Add a better example for `registries`. --- docs/codeql/codeql-cli/about-codeql-workspaces.rst | 7 +++++-- .../codeql-cli/publishing-and-using-codeql-packs.rst | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/about-codeql-workspaces.rst b/docs/codeql/codeql-cli/about-codeql-workspaces.rst index bab102d7ff6..f5b477ec2c0 100644 --- a/docs/codeql/codeql-cli/about-codeql-workspaces.rst +++ b/docs/codeql/codeql-cli/about-codeql-workspaces.rst @@ -14,7 +14,7 @@ In most cases, you should store the CodeQL workspace and the CodeQL packs contai The ``codeql-workspace.yml`` file --------------------------------- -A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally ``ignore``, and ``registries`` blocks. +A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file contains a ``provide`` block, and optionally ``ignore`` and ``registries`` blocks. * The ``provide`` block contains a list of glob patterns that define the CodeQL packs that are available in the workspace. * The ``ignore`` block contains a list of glob patterns that define CodeQL packs that are not available in the workspace. @@ -22,7 +22,7 @@ A CodeQL workspace is defined by a ``codeql-workspace.yml`` yaml file. This file Each entry in the ``provide`` or ``ignore`` section must map to the location of a ``qlpack.yml`` file. All glob patterns are defined relative to the directory that contains the workspace file. For a list of patterns accepted in this file, see" `@actions/glob `__ . -For example, the following ``codeql-workspace.yml`` file defines a workspace that contains all the CodeQL packs recursively found in the ``codeql-packs`` directory, except for the packs in the ``experimental`` directory: +For example, the following ``codeql-workspace.yml`` file defines a workspace that contains all the CodeQL packs recursively found in the ``codeql-packs`` directory, except for the packs in the ``experimental`` directory. The ``registries`` block specifies that ``codeql/*`` packs should be downloaded from https://ghcr.io/v2/, which is GitHub's default container registry. All other packs should be downloaded from and published to the regsitry at ``GHE_HOSTNAME``. .. code-block:: yaml @@ -32,6 +32,9 @@ For example, the following ``codeql-workspace.yml`` file defines a workspace tha - "*/codeql-packs/**/experimental/**/qlpack.yml" registries: + - packages: 'codeql/*' + url: https://ghcr.io/v2/ + - packages: '*' url: https://containers.GHE_HOSTNAME/v2/ diff --git a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst index 88d57059ea4..a91bc570768 100644 --- a/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst +++ b/docs/codeql/codeql-cli/publishing-and-using-codeql-packs.rst @@ -103,7 +103,7 @@ For example, the following ``qlconfig.yml`` file associates all packs with the C The CodeQL CLI will determine which registry to use for a given package name by finding the first item in the ``registries`` list with a ``packages`` property that matches that package name. This means that you'll generally want to define the most specific package name patterns first. The ``packages`` property may be a single package name, a glob pattern, or a YAML list of package names and glob patterns. -The ``registries`` list can also be placed inside of a ``codeql-workspace.yml`` file. Doing so will allow you to fix the registries list for a specific workspace, so that it can be shared amongst other CodeQL users of the workspace. The ``registries`` list in the ``codeql-workspace.yml`` will be merged with and take precedence over the list in the global ``qlconfig.yml``. For more information about ``codeql-workspace.yml``, see :ref:`About CodeQL workspaces `. +The ``registries`` list can also be placed inside of a ``codeql-workspace.yml`` file. Doing so will allow you to define the registries to be used within a specific workspace, so that it can be shared amongst other CodeQL users of the workspace. The ``registries`` list in the ``codeql-workspace.yml`` will be merged with and take precedence over the list in the global ``qlconfig.yml``. For more information about ``codeql-workspace.yml``, see :ref:`About CodeQL workspaces `. You can now use ``codeql pack publish``, ``codeql pack download``, and ``codeql database analyze`` to manage packs on GitHub Enterprise Server. From a9202b5c374ecf18fc91e925b68f2f5d9929d1d8 Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Mon, 12 Sep 2022 13:07:32 -0700 Subject: [PATCH 07/27] Tweak the query suites documentation - Add examples to filter on `@id` - Add examples that include regexes - Add examples that include both lists and single elements - Add some `import` examples - Remove mention of `eval` since it is not a user-facing instruction --- .../creating-codeql-query-suites.rst | 88 ++++++++++++++++--- 1 file changed, 76 insertions(+), 12 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index 1e212755367..a99cd4bbfa3 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -118,8 +118,10 @@ typically a query metadata property. The value can be: To match a constraint, a metadata value must match one of the strings or regular expressions. When there is more than one metadata key, each key must be matched. -For more information about query metadata properties, see ":ref:`Metadata for CodeQL queries -`." +The standard metadata keys available to match on are: ``description``, ``id``, ``kind``, +``name``, ``tags``, ``precision``, ``problem.severity``, and ``security-severity``. +For more information about query metadata properties, see +":ref:`Metadata for CodeQL queries `." In addition to metadata tags, the keys in the constraint block can also be: @@ -131,8 +133,36 @@ In addition to metadata tags, the keys in the constraint block can also be: - ``tags contain all``---each of the given match strings must match one of the components of the ``@tags`` metadata property. -Examples -~~~~~~~~ +Filtering Examples +~~~~~~~~~~~~~~~~~~ + +A common use case is to create a query suite that runs all queries in a CodeQL pack, +except for a few that are known to be problematic. The following three query suite +definitions are semantically identical: + +Matches all queries in ``codeql/cpp-queries``, except for the two queries with either given ``id``:: + + - qlpack: codeql/cpp-queries + - exclude: + id: + - cpp/cleartext-transmission + - cpp/cleartext-storage-file + +As above, but splits the matching into two ``exclude`` instructions:: + + - qlpack: codeql/cpp-queries + - exclude: + id: cpp/cleartext-transmission + - exclude: + id: cpp/cleartext-storage-file + +As above, but uses a regular expression to match the ``id`` (assuming +that the regular expression matches exactly the previous queries):: + + - qlpack: codeql/cpp-queries + - exclude: + id: + - /^cpp\/cleartext-.*/ To define a suite that selects all queries in the default suite of the ``codeql/cpp-queries`` CodeQL pack, and then refines them to only include @@ -150,6 +180,15 @@ and ``@precision high`` from the ``my-custom-queries`` directory, use:: kind: problem precision: very-high +Note that the following query suite definition is not equivalent. This definition will select +queries that are ``@kind problem`` *or* are ``@precision very-high``:: + + - queries: my-custom-queries + - include: + kind: problem + - include: + precision: very-high + To create a suite that selects all queries with ``@kind problem`` from the ``my-custom-queries`` directory except those with ``@problem.severity recommendation``, use:: @@ -172,6 +211,13 @@ use:: - high - very-high +.. pull-quote:: + + Tip + + You can use the ``codeql resolve queries /path/to/suite.qls`` command to see + which queries are selected by a query suite definition. + Reusing existing query suite definitions ----------------------------------------- @@ -208,14 +254,8 @@ Existing query suite definitions can be reused by specifying: conditions, saved in a ``.yml`` file, to multiple query definitions. For more information, see the `example <#example>`__ below. -- An ``eval`` instruction---performs the same function as an ``import`` - instruction, but takes a full suite definition as the argument, rather than the - path to a ``.qls`` file on disk. - -To see what queries are included in a query suite, you can run the ``codeql resolve queries my-suite.qls`` command. - -Example -~~~~~~~ +Reusability Examples +~~~~~~~~~~~~~~~~~~~~ To use the same conditions in multiple query suite definitions, create a separate ``.yml`` file containing your instructions. For example, save the @@ -252,6 +292,30 @@ instruction:: from: my-org/my-custom-instructions version: ^1.2.3 # optional +A common use case an ``import`` instruction is to apply a further filter to queries from another +query suite. For example, this suite will further filter the ``cpp-security-and-quality`` suite +and exclude ``low`` and ``medium`` precision queries:: + + - import: codeql-suites/cpp-security-and-quality.qls + from: codeql/cpp-queries + - exclude: + precision: + - low + - medium + +If you want to ``include`` queries imported from another suite, the syntax is a little different:: + + - import: codeql-suites/cpp-security-and-quality.qls + from: codeql/cpp-queries + - exclude: {} + - include: + precision: + - very-high + - high + +Notice the empty ``exclude`` instruction. This is required to ensure that the subsequent ``include`` +instruction is able to filter queries from the imported suite. + Naming a query suite -------------------- From 68f0505c395ca967e66f3f179d8c266638f32e0b Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Mon, 12 Sep 2022 14:49:41 -0700 Subject: [PATCH 08/27] Apply suggestions from code review --- .../creating-codeql-query-suites.rst | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index a99cd4bbfa3..c615d880aa0 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -119,7 +119,7 @@ typically a query metadata property. The value can be: To match a constraint, a metadata value must match one of the strings or regular expressions. When there is more than one metadata key, each key must be matched. The standard metadata keys available to match on are: ``description``, ``id``, ``kind``, -``name``, ``tags``, ``precision``, ``problem.severity``, and ``security-severity``. +``name``, ``tags``, ``precision``, and ``problem.severity``. For more information about query metadata properties, see ":ref:`Metadata for CodeQL queries `." @@ -133,14 +133,16 @@ In addition to metadata tags, the keys in the constraint block can also be: - ``tags contain all``---each of the given match strings must match one of the components of the ``@tags`` metadata property. -Filtering Examples -~~~~~~~~~~~~~~~~~~ +Examples of filtering which queries are run +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A common use case is to create a query suite that runs all queries in a CodeQL pack, -except for a few that are known to be problematic. The following three query suite -definitions are semantically identical: +except for a few specific queries that the user does not want to run. In general, we +recommend filtering on the query ``id``, which is a unique and stable identifier for +each query. The following three query suite definitions are semantically identical and +filter by the query ``id``: -Matches all queries in ``codeql/cpp-queries``, except for the two queries with either given ``id``:: +Matches all queries in the default suite of ``codeql/cpp-queries``, except for the two queries with either given ``id``:: - qlpack: codeql/cpp-queries - exclude: @@ -180,8 +182,9 @@ and ``@precision high`` from the ``my-custom-queries`` directory, use:: kind: problem precision: very-high -Note that the following query suite definition is not equivalent. This definition will select -queries that are ``@kind problem`` *or* are ``@precision very-high``:: +Note that the following query suite definition is not equivalent to the above +definition. This definition will select queries that are ``@kind problem`` *or* +are ``@precision very-high``:: - queries: my-custom-queries - include: @@ -216,7 +219,9 @@ use:: Tip You can use the ``codeql resolve queries /path/to/suite.qls`` command to see - which queries are selected by a query suite definition. + which queries are selected by a query suite definition. For more information, + see the `resolve queries <../../codeql-cli/manual/resolve-queries>`__ + reference documentation. Reusing existing query suite definitions ----------------------------------------- @@ -292,7 +297,7 @@ instruction:: from: my-org/my-custom-instructions version: ^1.2.3 # optional -A common use case an ``import`` instruction is to apply a further filter to queries from another +A common use case for an ``import`` instruction is to apply a further filter to queries from another query suite. For example, this suite will further filter the ``cpp-security-and-quality`` suite and exclude ``low`` and ``medium`` precision queries:: From 3c1f67d7de5f8ddfe155b74913e9927e8fb7919d Mon Sep 17 00:00:00 2001 From: Andrew Eisenberg Date: Wed, 14 Sep 2022 07:15:23 -0700 Subject: [PATCH 09/27] Apply suggestions from code review Co-authored-by: Felicity Chapman --- .../codeql/codeql-cli/creating-codeql-query-suites.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst index c615d880aa0..c65e1c42ad4 100644 --- a/docs/codeql/codeql-cli/creating-codeql-query-suites.rst +++ b/docs/codeql/codeql-cli/creating-codeql-query-suites.rst @@ -142,7 +142,7 @@ recommend filtering on the query ``id``, which is a unique and stable identifier each query. The following three query suite definitions are semantically identical and filter by the query ``id``: -Matches all queries in the default suite of ``codeql/cpp-queries``, except for the two queries with either given ``id``:: +This filter matches all the queries in the default suite of ``codeql/cpp-queries``, except for the two queries with the excluded identifiers:: - qlpack: codeql/cpp-queries - exclude: @@ -150,7 +150,7 @@ Matches all queries in the default suite of ``codeql/cpp-queries``, except for t - cpp/cleartext-transmission - cpp/cleartext-storage-file -As above, but splits the matching into two ``exclude`` instructions:: +In this example, a separate ``exclude`` instruction is used for each query:: - qlpack: codeql/cpp-queries - exclude: @@ -158,8 +158,7 @@ As above, but splits the matching into two ``exclude`` instructions:: - exclude: id: cpp/cleartext-storage-file -As above, but uses a regular expression to match the ``id`` (assuming -that the regular expression matches exactly the previous queries):: +In this example, a regular expression excludes the same two queries. It would also exclude any future queries added to the suite with identifiers that begin: ``cpp/cleartext-``:: - qlpack: codeql/cpp-queries - exclude: @@ -182,8 +181,7 @@ and ``@precision high`` from the ``my-custom-queries`` directory, use:: kind: problem precision: very-high -Note that the following query suite definition is not equivalent to the above -definition. This definition will select queries that are ``@kind problem`` *or* +Note that the following query suite definition behaves differently from the definition above. This definition selects queries that are ``@kind problem`` *or* are ``@precision very-high``:: - queries: my-custom-queries From c17af8c3543cf934c0292d9affa9918c25af2ffc Mon Sep 17 00:00:00 2001 From: james Date: Fri, 2 Sep 2022 10:36:02 +0100 Subject: [PATCH 10/27] update info about downloading dbs in vs code --- .../analyzing-your-projects.rst | 4 +--- .../customizing-settings.rst | 2 +- .../setting-up-codeql-in-visual-studio-code.rst | 16 +--------------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index b23ddacf157..2b4e26b405a 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -14,7 +14,7 @@ To analyze a project, you need to add a :ref:`CodeQL database ` #. Open the CodeQL Databases view in the sidebar. -#. Hover over the **Databases** title bar and click the appropriate icon to add your database. You can add a database from a local ZIP archive or folder, from a public URL, or from a project slug or URL on LGTM.com. +#. Hover over the **Databases** title bar and click the appropriate icon to add your database. You can add a database from a local ZIP archive or folder, from a public URL, or from a project slug on GitHub.com. .. image:: ../images/codeql-for-visual-studio-code/choose-database.png :width: 350 @@ -31,8 +31,6 @@ If you have a CodeQL database saved locally, as an unarchived folder or as a ZIP - To create a database with the CodeQL CLI, see ":ref:`Creating CodeQL databases `." -- .. include:: ../reusables/download-lgtm-database.rst - - To analyze a test database, add a ``.testproj`` folder to the Databases view. Test databases (that is, folders with a ``.testproj`` extension) are generated when you run regression tests on custom queries using the :ref:`CodeQL CLI `. If a query fails a regression test, you may want to analyze the test database in Visual Studio Code to debug the failure. diff --git a/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst b/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst index 940a8a0c50c..8899bc97bc7 100644 --- a/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst +++ b/docs/codeql/codeql-for-visual-studio-code/customizing-settings.rst @@ -28,7 +28,7 @@ Editing settings Choosing a version of the CodeQL CLI -------------------------------------- -The CodeQL extension uses the CodeQL CLI to run commands. If you already have the CLI installed and added to your ``PATH``, the extension uses that version. This might be the case if you create your own CodeQL databases instead of downloading them from LGTM.com. Otherwise, the extension automatically manages access to the executable of the CLI for you. For more information about creating databases, see ":ref:`Creating CodeQL databases `" in the CLI help. +The CodeQL extension uses the CodeQL CLI to run commands. If you already have the CLI installed and added to your ``PATH``, the extension uses that version. This might be the case if you create your own CodeQL databases instead of downloading them from GitHub.com. Otherwise, the extension automatically manages access to the executable of the CLI for you. For more information about creating databases, see ":ref:`Creating CodeQL databases `" in the CLI help. To override the default behavior and use a different CLI, you can specify the CodeQL CLI **Executable Path**. 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 1c762348a9d..5592992373b 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 @@ -28,7 +28,7 @@ Configuring access to the CodeQL CLI The extension uses the CodeQL CLI to compile and run queries. -If you already have the CLI installed and added to your ``PATH``, the extension uses that version. This might be the case if you create your own CodeQL databases instead of downloading them from LGTM.com. For more information, see ":ref:`CodeQL CLI `." +If you already have the CLI installed and added to your ``PATH``, the extension uses that version. This might be the case if you create your own CodeQL databases instead of downloading them from GitHub.com. For more information, see ":ref:`CodeQL CLI `." Otherwise, the extension automatically manages access to the executable of the CLI for you. This ensures that the CLI is compatible with the CodeQL extension. You can also check for updates with the **CodeQL: Check for CLI Updates** command. @@ -57,20 +57,6 @@ There are two ways to do this: For CLI users there is a third option: If you have followed the instructions in ":ref:`Getting started with the CodeQL CLI `" to create a CodeQL directory (for example ``codeql-home``) containing the CodeQL libraries, you can open this directory in VS Code. This also gives the extension access to the CodeQL libraries. -.. container:: toggle - - .. container:: name - - **Click to show information for LGTM Enterprise users** - - Your local version of the CodeQL queries and libraries should match your version of LGTM Enterprise. For example, if you - use LGTM Enterprise 1.27, then you should clone the ``1.27.0`` branch of the `starter workspace `__ (or the appropriate ``1.27.x`` branch, corresponding to each maintenance release). - - This ensures that the queries and libraries you write in VS Code also work in the query console on LGTM Enterprise. - - If you prefer to add the CodeQL queries and libraries to an :ref:`existing workspace ` instead of the starter workspace, then you should - clone the appropriate branch of the `CodeQL repository `__ and add it to your workspace. - .. _starter-workspace: Using the starter workspace From 64ea959c59f7691d0ed55c6482e003b33895e707 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 2 Sep 2022 10:43:36 +0100 Subject: [PATCH 11/27] new screenshot --- .../choose-database.png | Bin 58515 -> 112731 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/codeql/images/codeql-for-visual-studio-code/choose-database.png b/docs/codeql/images/codeql-for-visual-studio-code/choose-database.png index 71ca5d6b4c3512bcdc641be0a14043c108a320a5..58287111cc162e7ed95e8e59ecbfc84e55d8b187 100644 GIT binary patch literal 112731 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
FSR4dalV%}_BZmvXwt2~Feg0LpIX@c>uIG^ zK>6vI$PqEBsLC%l# z0|ms;U}F2@5^cblX4tvz=*u7RpcBf6CSwS&P&9Qw2-zGDFq^*I3?eZ z^ZNFVB~Js9E3uzs_{Ho*;(|`MzjeHFWB$@Hgs* zv8llU(@<=%a@Iy+BQ{8`?G(9Fz$bWa(7mLQE^h3zHA5I*Bl$<#Qeh2|jTP?Nlu_kS zOY&F}{|f4NV?9ai8NfwqwUS?+?zhxbInInSTBy~9j=IJ7;;WSho8fm-(nm9EOXwTl z{VL$SjmCNHBK?HNdqHH@CMKUx_q*=*!w*0tg|_hnl{SbeM)IF`;}1v)ud#eF5l7^hV5&gXkbBnn60(GChOi= zExT_0rQ_l^6>jjw^G*slpzMGEuubkheFA%U21UtB3*NOWoSIDgc0hScGo7Q z<;0VfHXEU5p7Atdi@8Uf)cS&`mqTe3I_(Ygw*=qe(Xah>%kuC{+{r?-Cip>Ik1xKA zvH{39rsq?YnY96?YBbZQ(52=h>q)=jtBj`jVOC>&jnIKsQc1_<79-(Kc#2_UiLiZ* zjrXeWekGxCPU7&|0Bz8+icysq6E8^t*$=EtKxOli9XK_3FAcG;7DY-o*nE|KjW3GX z*?m^kzq`qAkzyFLsl-4Wp z5>&t&r$4Zk1BT%0z~bB_-szP4JETz7eN}B)R|>)JoxchuL!aGqeXb^4-F5GqREsG@ zKB{;$U52M5RxLwBMMQr-K@(K*n+`_ne=NzP7HHJJV6v6-1eCFTbJVqFzwiC&Be|xd z{AL`-lO?oeATpoGDXn6x+nlLiSx<4GrL1!KyGPrLp^w$fI2{ylF8zg8H+f?zN73o$ zaUH1<8^j5&%plrX#O$#f$z98@rV9pDxT(zn1#P5g|A)B?o*`t*31skz6eYxP5dq&3 zP4_ps&?jo2G$wKZnw67ifM>zc*P(alzSKUm^#VEP5#;lD7sX(em-p{a6{QZ#(i zJ@sOkoTO_&)#xSb>yPRM;_oNrHLyI8=|SeAmfZlbpbeU2#v8-(RugU@zEw7eO!YDs zysars!Mg;m3~v-Vn5O8;HbUxYB~LDvj)=eDu&A}L=~ksPy{0x?)_g!`evE5sub;}5 z_#E|_Zk6gpA=Pm@DeWgZu41+T8yjP1TM^|ylM$qn3~GY#wV+Q=qiz|NyV=0Yy)1Y` ztPeWq74}7bE(F%u@-_?(Xbt35ez_7-j`{`?(lpjXHmRjHJk-6|pwHy;lk?A0+}K>| znMdm5yP6MRJQdL8L+q7&IT~#^w`!>itbUx6I2_l?zImc1WV#5wYnqyV2fLQ-}8Y4M!>-Ir8$mhKxWo z;VA!1%WDmdCE0e*^v`d3?qlS|E*Y-iHE=iX2|bFsnmhY>;8Y$7;tktL)9}Pva8;aM zSiF!L%X~JWbHRh9&*|?FOc_f}V_>qonB$olQBR0)u-NvyZ6W`YPpD&7IwN<%Yg?ph zm8c%4E`J;$_~qN1i0w=vXm@w56j{&nxS*5FK6)q+)x#`*$+a0IxVl^ms)p!}#i)CAYjRKAx)ppNsOJ8W#as~aDEjq0$EA(kXLOD25S`5xzoE@1jzUD4TN~*K zjIiO)Jdv03OfZE{3xX*LfWju$Dyn@#K&`_YN3<*T%{mhErSVt7Il4JzD4%Z$D`qkJ zOFZH78z3T*mBI%1o&1@OC!cZaeFekhkIuV`K`F96jtV(ST+&~KPw0Z%=k<(v4?3r# zxo9LhH6}x-r!t#Rcz@ERCMh8Wy)}HDNTo(3Sl;s(`J{Ha?f4VG<$Pw9p<8$a>9ju5 zQAz%xdPeRaiikm_eORF}KPcGo?UZvB+%t2b8P900^mL?yg*?#Y*K>Ph7XusU5vrJ= zRmAVs8)pr4a3dOsw7^%`?_wEnV)U46@M)S^*>=;vM^5t>S!Jb0C!Va6TVWb$|98fmS|M-PI)l=?Q^vK15 zy;ftc7Y;dfMq>Q~Gb6!*EsThOP$s{3*RDad~Nv=`0WQ z(96OE@t0^BIxF=}(r8;jNzhBN;~2T(+V^# zD{#;NSB`jD3WSkVRhTxn5ta~pcv`~zb0u+nzeQT)7Ht{R+s!QRmq}fQQD8s6vDgav z1Wsm{^Vyp?wy1t!VH)e1 z+>0aC$ITLXQ4!4>Dsspl1;tvZ>M9UEmrNRkvSc+Al4d*9Az_2XV2fl)1>rg7X-)89 z^U1SOan;uETp=HH1`>?@_%!Af^KQ9a5CnACSsI6QLsRpzEC`bG1E}mxvYOu({q3d5 zGkVxafW7ypz((9HF7Y=Lg1+iFSORLZUQL-JI`z-yqN-0)LSur)T5At`qpL;*!{dbu z>E2*qB6z9ktHz2=w45IT-w%3r)Ht`pPJ8eqUf%x5B;~eg6{Y(<^jfmmn3agWGneDq z^`tjo_sMv)Um?wuxy9R}l0WJeVu7N|=1(U4>r~I&BY|Td;yyGWVJb_N?>mOKO+ym>~IW zrFdpC-hGJ22b(7wcb9DtL$YCeH0>oUX()c84t+yexMfX}lLMN*fIgAYH6)LgyDE3m z(|DyAFu;1%5K+wh%@^?>?TCu$-ge(#4Lo#OtI0=OWfrV@pPOZ`n;2G-BKdmUDBhwOJInA)aZUL@87x4{rox3 z**Rm^H$R{E>$Uw+!uudB{3DGpfvrHnud{Nxw#h}*QQCcw!DsUdCM1~%o#`5SK07Ei zWJGl`?y66JF!i#?!F0LGmmN|b{j5)7OL|v;QnJ;yNr3G~Uoz>Qc~x%lT?YTLhHN*U z;dA9aA**7x{j7nAfz(!4jn$xAS~1z$s%xXKBKnGkAkl+@x~1C4y`?8s(*($?aJbrvo8Whz^qwmIq?C}; z^=T>;ge^Ok>PVZ$-4~YctYyr(FmCjkOTWpv$u*Z_D@-^>4zaZr%@>n&`Z^UH%RN8I zc@s?kMzF;OmJ&jNy;5(tM+e2TP-+K(sa|tGJs>{9Xmjps{~b-qW|blARjnXK;Bh~i zAwVw!1dR1Daoixwp)|8(t&Qtq@=6qCSzGUtu(tF>49)4pw0dAT>*uA4h`LlngUJ%% z_tjbEo>Ix5_tAW-EIWfi=iS(v;hr&^ z1^sAVbI3K(1>eMV5l53nz74%K#yqLXjyCsRNjJX{oW##nz%0iEXES61rE!y}kr$Rh z(H6UWh(`J=(J(kgq_J@BT|MjL5rHhQ(x|mZsT@T`R7cE|K{qwEQVZ$9p`-8_+FA_Ax^m8BBW{vWW6m(A;%!KU=#+%q!iN>fbcIjn_b z(!Vby>RqYHjbRZ4-_59``Z_s)3A(fY8iTZoOM+37K(8fBCU%4hYWMQh8hI;rVCxP} z7^l%U;jRf`A%_+fYyn%P48sz?O1Lh@S3Pi`tUNx66%lDI^CZ1iVnZ1iAIcs(m>0Bj zd&?^Eg4+#Ed^3ua_@$uxU&f*A#s%kYpB%C%oaY&WMw}9Aqo*?O=#Q9iHfWcp^8%P; zs(I-}G0D$Z51Guk=P>ie;qndj6$Rf#9pCxi`^c`zH|YP!wFBLFo>@RGQdKDl@mpbx zw$ff$InOyC%5*Sh*}!x6XQKTo%WV$!9_7BiMVpAWmLp}swL1g6qa}Sfu~LPyfTN z83G*Jz+8nFY!hVm)kF)@)x(l*pc^v^4sL2mY}RMdp)uwQPjVPeLBEEQ0meb+0e@cd zwyj?UyXlm`4t904J~xCzydVV-;ju=xmfYPlFo~=LAttO*D>F9^(*{N48__yuyl#+y zPr}8|fS?ims+AS>-NB#9@4v`NV@V?1^fT2(2wln*5mx~a-8hH9xNxkI7=Bm&F6tcf zuh2YYEd=uvC0Ybcqd~LlvDIxw;&r^HQAv1=`m;lHVfH{msZ~ej53kXyFVskm0@M|r zBIQ^24&|)y?V$E%KjmO1ORSNZAkbhaK20KbVyI$Pr^2=SSlst)Zlj#?=CjY`1OC2b z^;8~N9sHnDO{j=HuKoN(tK_})iLs6ga@BV;+qM0q!>8i}IV$fPzS(#j`alaaomck1 zUW>ft_dF64XvQOZc`yC${I`F9NZ;!17N4L4rLHA%KAdyGAw4XL{LuM65FT&B^b#ny zsl>4%k7-G^whL*%v6XLgj5oSg(}&Zf?&;T1;_PW4CzL~PR|rO)!fU$hHfc{p%Vn9* zILc*;2^m)SLf4Gro|NAG@4U9Durd3)-{Bg{Y}-FtCG>TlIb^IW0R`_Pd~y%THPS8> z0y3S#A~Fae-@|8Y?gCYBz87O{(^j`VSdO@C3rwIvbA{gt@2NJ}7bEC{(^@IU`d8Eo zBp0uNw&s(*PyE2q4KkbHU`I}Q65?Ah0oF`}JFsBjRS`Wfq#gfM3Z=4_IAD~5Xu290 zPmjByNlxITee=55!Lo6Eg!|$uYBXnx*0*b*#__n?d|#*z9hV-t@g4kDhk4leg}7j4 zoIPCIs(Fnu#X>%75vJ?o7@aBtes8$bsBg^kmNN_iQEUj0y@o48+&+&!De|yKp=q*D z;z8|#yH9|v?gFXihi$`#jfo6P=XjBI{xk%m;8cJ~0B8riL3eLDJ~bE_3ks~`d>RT9 zN=_22#34hMRH#SFYwb)}M_-?R7TOm!5C#27f7|%J2)J$OdPCf#w58si6D?{JJ1-hw zpg*>t*=r=C*jc?jTv=}As@+=|oj`x~e#jOl6*C7{n1p=4G?~7Q6qYtO5dch<`S$qDmG7UsJK0!LmYlV+*7@n5Cl) zkQyq8%S5mDA+Jl!qeg*0FWCuqT9+TkN|+Psc=4GlO!fZ8LV*>pr0=^WnG(!*`%~UO zF7WU1R*R$Amv71pUAqLUta|PR8L&^46lnRS9|h_F1WK0&MaH zC0p`lV^r48lRVHLb$MJl>jg$6vxX2l_o!l-B^f_V|0$h}XC`&3)1ATT;gZ(_UU1pK zs8cn0KiOUx7p6@1IrRrT$3y$kCSL z#&PAi#_$tEqTSj{F-3%Br+#zfgyb0j*w(dsWAB$@UmgE`_Z&kp8`!ZxsksVr7~Urj zgQMM<59>4jvtD)=adh2q;vI$JfW!S4`nCA(#hZ<+(29*I<6GVLwr z#44-|B)F1Z^xL2Fs{?NO;;58(|4RQC(;s6|}DkNf)a z+ZWEz0T{h>CAbQaeT4CNqeimEB%*(C{oz-c0!?BObSUh|#?U1pyh6$;!MeiYE>mEklkLlgyzL@?n zcLDTRvtu8uE#~@sw}NGa6cwP{$?_0)2d}*{;@;UMQ?!ZO%grft=9j=el)B_s6mPZ8 ztwE4WIYj7OO(X(3VIWRMTnxlJB!&+{YXS`wxbGeN;L2(HOuY}l+3VbSmm4HtZ)|K> z`fMwqp4Om`4A`!sSK=%-Wms||`dM#FB1+4pmM-5=MR1#BoYcpY@YA7gf5zGI2NRDp zI%_ZR-8*>>$+@dr748dTdqL=2{N4$GE1pb^-_H97D+)|n3<*j`=~YX;#U@LJibB~% zKH)}xx*y59I&mpmr>_9fy{LcJVSbQ}bGv##TchgYnGw1u; z!3IK`ZPu|lYP3a(M94~OzuN`>ylHUjBqr|ab-e7i84BqOzoQ_U1jN4t&n^>ZL5&fH zgDmH}mbjjigoM!#1yBqnx4$hCdrG4GX5jBlQzXx^7Q zUyqDJC4`r5;Qb`Lgu2erw{#u|RcAQaMnlKlK2fwYeUY8OFr?}8>7O_hC$oUZ?le}g zX&KO-M^P>D6l3kk#Ok)Y?YXDQj2kc24cYS^#OI+DW6o>dF!w9cM)CCFc>3(=tXcOB zYSIrlXGo&2$s-;vV;>s9Gj7>VR&{oWGf|(Dt^bx>9<{Wx`hdWJQ+*uAg`!}-S9Fm%d7P-aEi6*P8T1!h#iDTj%%dC^&MA{ zrH%O_jM84S+|_PmE5NV>c9|%ZV*83p-7^rzDz!3z0j{Y3JQ*R|)%%P?WC4HErZ)~kKM%!5K+1PJTPOA1iXfF`mnTxTanZs3F#u^ku{vl_=Bteg3 z)a3FAdfJ7z1~jaUx;xh-H@bqGb)JIhDaEmw*YgLmO_qA|WtzhT#HDHb85j_)uGkxw zMezqq+bhXoOHSKYkwIVXzeU&T>3YQOg~Bfmq=>fsn%*+5wzj0&YQ}GjcHV^w9%kQK zWLD6)3O*bvKV**MnFMX2%_`*|4Y18u-pUXQ~-Z$`kj~OAYw%EQO z-NRbl752JR-Jasw7MvT}H8eqa6oN_F5dH}QVMJ&M+b5lL@vIKOr6*xT&@1ecPGL0F zwesC|LV9?lBa%!2QmSW>LPdAdM;iaK-w(!*;@W-NhkHg#wd3VcSe_;FYSE|!!6UjY z-;7dJx=1JJk?ZX0f|6bQb!BX=YTb{*-SoqDrGzS#tNoUlyEGsEu{n^{M2GA%AzjB- z=?C!^qz`x_GJdizraHy>6W7LybwYF==euBn+!QjES`T3D#^ zGT2^U`E7%U&fOR-YtG!1JE7U>ok$Tgp8#=1i=`nXIWfV~UlYij3Khhct>6N@+kI)# zBi>xkpHYF=LZ|ZVkTyP%t$yZ> zp~bc_?}~W%1s&)1T%vAt`~JE$iL}Iwtd$)$J+g96{Yh#n?N>Q2hw#y72_qVYxDzGo z1j36q4o~Bz!M9y~3gm+Lbe3qel(v^|)$m8$Gmj5g?zzveTWy41av4jzpLeC6&DIX9 z?kUVf1a3j^Go*DVk@?EwLgy~GYz>!gruAC~ome?9G(Jr-exO=XYSwr{X{7LhqcGgl z@G;-w=j{!b(N0YtCX6s1yC@$-?5UNYb?g3flI#)+t4Z>332IQejIw9^S46r`u>Vfe zL1CO$hMazx2S%;He*6Bv^S?AXN&t*x8V%#m<;7d4ltS;f#g*J))q(A2jws?QQSM{B^Ie!xDUCf z+0Bl!|EC1CW7~Nra##k``dB{GEz)fN(2K~qTo;CAVE99m&x1oYxvh= zH8SJ(m{_D{!t%IYq6u>oZC=dCJ~AFf1Va8 zBI1s{^asdvzxxQXVVJ*1;KnSbZ@#ue1QDcC-W=iX&(Sty4D`=Ic;b=KBOXuF=o`HI z??>Y_S9g~?&Kgf5{cj%xlPPdn8-O8&fQeJoo3V!yUE7CJ&BV?43wJ_Ej5o)p&OlQHkr4s{>-(QTC#Vf$y7b(!3fooE@w3IjU z-UIjz!I?)}=&x%IxKCHsfXvwvd++HOYqX(*u+Pyiztlzn^6VrJ3i7RF68;MwuTq0K zCY>mU1m_LOMQJi+#pg3s+|o`=kNEXjn5D3Z{U%Kr;aa@_Nvn?Gt;qEL5wCG22*IIU zRPU_*wnq9r z*xS?nB~TADb9{mj9wf3v-a~Nv{%}l)PsBlCJ&ikyFyh5;(dxIm6LM6}kzw>@VFJWY zV}6s8<-e2CEiA&ON$Objd7DQ|!4}u9iJ}v&y$xb|3gD;XQ5E?}y8mt#&Guah;gv#AHcdZybdy@7P>te)OHoZcP5 zU;X)bgJg^wafh0eN3i8&$NctZ1wX_?p;ic!2fH+9CNZXW;ys(B46TZzL2xdeC=Yl- z{BKVlke4V9)|!q2;>-c5s~@DRqi0;Ntr!uafWTs|M_Lh~7~#Vg(SY$vPc*d!$VzKb z2Z+OTSV{I|%uU^b6&3 zKIGr#Z7%hr0KQq5_Bu8JB2YctbP z7fF1mt%8q>-oz~&CF12)jad7EQ}T$y9I{wpp#QTfi@L*RVw16Mg_tqU4qDEc7FZ9m z2~@BZ4r?f6?Fqd<)8p{<6u}nY?lLuV@RFUufQ>ZD2De)=^QCjKplkCe0-@qG%W|kL z5W;+nRGQdAvG+fXJz%Kw&d}zt z;^T@yV=|^z@fWFrdGC__uabx4lWI4sY;bZLRY&|qp)p}}>)btwQ5~c}*g=A7CiXeC zEfX!pVA7!N+8(=^{!_hMeFQhT3=zueTVsS15X638$yEf5fRtBgc|^|P`6mc|?QXl$X`o+*Y?xK`Gnqqw$YyRxre84+HJ}m5)-0jWiSyxl1Z_{tlkMf;0hY zON5qNc3o2rQL-bKQZ)XxLJ!yLm!^l+!iugvi+4Bxy2hJ}_Z6hVD4*IO7y&FMF;V-U zoa_BRFlcVYyI3lNQgVC=COrCZg#Yj@Um!ABkmQ9qBS~9!zQNXtjK zE^5H4CJfi22fElc`MI3w0O&AI@>s{XUT=nfMrd^NebMLD8Tef1D|dBm1w`D*ypx$C z0gCq#fc_3Y{ztqwN6PW&iT_;UMUIxdX~f_CXiQzd(ant<7Mpw{^=+_mwmv742ETRC z7lGBql^zNp7eO|CX+ZkDBvcAF!ycFJKM7vN|0H<7 z$k6f#QP-0RoveO(L?XAn03R^+YcyWc&=l|-Acq!W>8Fj_12Z5@$dx^W7{S@O+n7?= z@t@##0E=g$p8Y>X-OK-=I@^9USadg-ZS&gu0RMP zj}5C9d&yPY@uxdo6xX*ZB38B+8Crc0v=`wLMpY#dp~bFRx2Bisi*WpY%Uys6Ql^@W z;s9od24R5sCuedxds482&G3Na_g6;sDDMtn!oMitivRQ4PXk94r@#S~oAC2;~M zPLNd~eKQ~N^%}#?VyWMD*wpKhPXTQ~Vj#f=z-PG6xnh8^@2L+`kVEV_AD{rg0`A7) z{lQ^UZb8Vc*No%$mY4sbZtl1J??2wG_=mp87u4VV%kwW@0-zja??1er-hTn$ej)QN z=ZP?Yo)crr1|B#Y)Q}Md&{jm}N#Z@Y=A-`G9)5*L0ON=#W<~EX{0C)qTt;@Vz*^>X zpESjISJfF2p?0{FioyOL^*_+?^#Ou_$oc2D0Aqv}M)n@qgM>8!!Yqz{m2z^0an-3^ zOMcYhulWBlir9d8=Kmw1u9E$=ZF}MzmZ(D78u#?~J@3TE{}}8j+#KJlt6u4?ye;mC z-8uvwA$5A{I{+=E?coIg zfSIhEW%rU$@kg}PhhU|ju;0RBa`A~`#z%x5dAg32b7itn{bZfpxdLO2!e9HC5|=J| zBMNuUlMJ+pVc#!-|NnXC@DE^2|7xNgF99cq*DsgNsUI{Om^o3lkfX|@%7aL264&nc z*It>);d%vt9~jZ-!Q;Th-mSR*j7?T?YgGgwZU+v>cx-m|FUVwZy=bd0W!U?Mb|SNJ zIzG9;bi3ypolGoFevf1-rt>Bm+@U^Z?s!q7iI}s-Qoq|3_PMO|Iysx@;Ywcr5OY9} zef3AHVC>)er~D5oEr~i{+|q;I>vWt|$OF>HF^d(8^54Y&1yo-WI^X`7)9r0@+V4*k z!S;IK{eUg7P_M*;tn2(p!D0$@;-IVYedu)g4T{4-aQdxS8c{!~;VW$bvGS=S96S9t zn->AxR0q3>Jm~A*C0S*$PdR6r)H2t_#@6Ve@1Zv%fWa5)*^sS$mim?qf4J-ywGZPm zGrJSCNQZ~M0|sv# zU@JGZ+n_>QyW<78GqPv_s2?E2`)4&A^a8vSbs5|=qFJ_>b)US3U4hR9Fl-@W6-gNx zxSCr|{z53vm#7B$!9B6_l|#PJV31NETYDLywdbmse`QJwa|l(9`a=# z0&w+{FTgUMM`g;sjsEZXGypg??%___3BXp6@H*w{<9b!N>keGnv@js;xL;<++o@-j zamBy*&ML#tc@V0_W=mjgN)DEG6c}49=dDl9TF9V3-;nqtq4pp7BamCjvRYhPw{QdY zXbpsUE3jDrUK>E2U=>PvK;42`c-O(pYVn=u0wJ~Cah1NNKVoe9Dg0-%k{YEe-m)DAVfHfn=28>aK9vq&R}CfDYWc| z!b2Y!w1;I{d~!GS0XUxbLov(rTcD=K9(lF)|HD6p{jIbL764$#Dz*++*nZJaFDJEQ zdDJ0>*M50gVSK%@YUg2ioSLuN@a+2VmagVnz(&$JZYWZ%yd**9k$?`i7!M>$U9q~M z+?wu>9`0w$L7*<^-^4%oUjlwW`CbBy)EnVf)gMv0CPe9TvUlo351OToMBLkFUB0+U zBe0zoZINVPX;T0~72saXA=A7xVh6Q*!cnxp#Rmb_XbC`MG{XH8E<+0V{sIR{BT(7c zwvhYZzpdwsHo*!aK9@fLPv`z9Ae^9>D)Qc|`N{Qa22ha+{)^9*n41Q+dv6WSm>c_g zNU@sN1_2!T*EzhA=KZgwz*7Mp_4fWh6nk#ohFbNUXn8xA) z?)uaZ_H3Jr-}pu}!nFP?h^VNa?UHIXT{)W;fHNFs@H^#pI%$GEfH*lD zKi%&g4VnO2q$wX+i&>#L8@(XZa7b_CA*_oJCD!IfW|a#%@1XYh|dJ{hc+ z5>QioNgo3+D167uR@bAMOrtmNmsa)HamZqRxH#!me7{*ERb|H0FlLvYN$`mm; zWVaj^<-qFa4iMT2NNAyNjU{D3i3qj*fffC$3w$WA=E#YHWRDobpVw+fE+sl-#1NM9U^vNY(L$PCx@L(`OZR0`MsxpTr?wv%j?Qqhv>g$mp_B*^Uy;`)Lx)Pa^R2fcL^7n zw~`3%gr$o`iFeZ)38)KJ^~_V)f0_ffnqcH&#P-hsbO5vQD#Ynq|BN)A6Ani(JODSd7T2d<|jl355DOs zaZY1PV_gp{rmcH(+Ra-8S^#yAVK*PcR{1#fciOl$M3x<^@5eFCQ=2|-YYVC40g z%?SU8wYvExm;Nb_xAiZ!u%{|cwncrvhaWJvu%%MPO~imQoOTm6^;xgnVhrUez|Qu6 zIoIJHN(%#zwt@msn(=i@zG~d-952<;-ubO=$$sWWf&^}(oB)#K*#+hDU!p^I^FUY& z$+jKZO4}Uc#(G0?=>`4f%;7Km$H(2l?rr*84}PFh3aC<8@IL?gd&3F8aXNz8I}AHf zF{w6^9YS5Z=t%4@wcj)Kk!*k$L?w1+w#qNS4e*_gJc9DO@;s@E4>|wf!I&evmmnTn zRvfO2!-+`~U$$#aH5;%mZl!EgxO;WEqd{Sg2LCqY2gj7md)k|}eVzMh<#3g=>Xd@Y zn2b_F!rri!L64`yBOCkEJ)C4LagO1m4^M}inRN4u!t1I~)R7hcB@l4iw`Ei!n+ZOh zZ=bZDt)2?I_5wo&wMPb;ckEd1B}{%O8UOkq<@;>H@L`XI{dg}D3%`95@OO?lE0u)K z({8;LNOqrp9(sjF;Sv;lPFwaZQjg5IvP zVzyAvkRPTdsP|g1U|+=Z!=9p0%;#qmzdo&T4^2Q``NctwBa}1OS_-MJZFH|FdS`B9 z=i0ZPfJL2=mU(w8I)ek>AO0@XMB{X*3`*uHw9|(>v|pK9p(|(*IJ=eTr@H=K>!?U+ z{dv04E3dd>VE>$vFA`HY?BSozZl{xUq1AD{CRbKNWZm$4`9R1gzB=UOxOr({S5cb* zN5^hI41YFpc)Grvx@FyG=PLc{96;jmB0qZ&dzIO^F;j0Qqx?|=% zu=#9iJlV5|Ah@eGAiq_rY26ntOFntUTwAsawLhf}vOIZl*Wj(c*X&EReWukv6jpOL z?A1u_pu6QHfB|I}irM?UTcCvOtEMsfj!v9bGp$AZ5%!XZR5X1N~PRjd#w!8h85aS;D?%5~T>W0S4!SeM@;%K0ci~D#}#1*|i8K1m*ne z=l#E{b!mKLfADiprcz-Wib3Zq&Lyo9iHistGc|VftAiEqL9xh$r~TNWx?S79M=GAm zY8UOifadwLFe`r3Gk&E~&XvzI~>P3D#0YU#m!QjwYXcnvJ=$#>Q0T?ySiHJM^pCG!Ht9hXRum& zg~*c|XKWHlobqJ$x8O!S)USeGP5q*?ig%XigJnv{Hl6I5S?zYKki<8)&C;tZ6qGY< z0~i*O3Z}8VGs=3?yc$b9WPu+e&<7f9@Y78^OM4U-+a=IT^=pGZmD?03lqZs@%q9V@ z;6X1&q^6v&l}=WtjMvQm&Xh&Oz*oPLcK#myPaGkk?fFW%ZCto2{ie;WGV#JzhSq*7 zerSb);F9BA<(X4c58{Ve3pdc3`$O^i0iTnDck#g5r|Wcgx;JO?&&qEB{PCCz*pqHT z2Vw8;Q>C*6T_8*r-)i0}d(Rabn&x8Ckj^@VzU(+Z{Ha1_VysnFzW;P} zG1>9@tNWaLSGT-(EVqJ|p}jM4%P1oBX1AnI?Zu0!R}MnTds~#>?dIBJ-f|uY%%1QA zYMb-9b2feA@1OsEC-xf*DtxeB-WT#}r$hroDEr-9fGz<)23f8oKLMgP?CrN0okpX3 zY)}^i2FpWEFufMi=%rGtECQ_aBvd@8@0l!T7}19MrXsLn&Fy#3N0R@0nUzQbgX(WbGLht_>Titaok{j3*RtjXvg1&rW zREgb{qZs!y1flO($7T&xd?w~|E{3EWSwWbL5!AxdMVEEyw3@eUC;c=Y*oH!fdD-4Y ze%0q?t8t?U=GVIzjpdeBOM~qmhwY;idD3zM3bYAi^}C0NxI9I#i^KseN`;@od*^IH zx^^Cw)p0=;Lm^QqrG zCGR@*J2o}nSxGM@-`W@~@)e4lVfjAATcn|I>Jc7fjA(`}i?3J#l?DK{9Y8K{lw4TM^M8Nx#y;NZK&XfK7H>7n3f0NCTu zap!I&EfbV1KI1VX=1%_LO^$m@QLx$*AnAKL5z2_$5@@O1c4ha|4kfQrS%@RoHNOy~ z*usmEol^S4Asz=M(PYS=v=yvjeByOP<7J1%-{3I= zsqUEcS6|pD*&esPS|V-~^kmy(*l$r{c-0i2{pZMNDP~Q#m-}m9w(Y zRBWOOH4tL)^njk@41}aLH(IKAeFA~ABzkiKncN5T&n^^a*WKSE7jDw#2Y z=O);|(vJuf83qhZIk*v@56F!F$k@32j?yD5PkKB~`{kElaS2BN$0g}E+-gK-06`IS zSmgGoJGV;paQJbbqNX5bVLbDi{lK8Wf^su#VN~97-XwMJTtXz9;na*dleVC*%CD=*MasoH9_r<`OqqUrSLfMv+jD zvdr!S&&wHzhUDB%I}rr<&o7tUQ$Px$Q(1n9^6yYEZ8;`7ko%)B`>rwmUY;m;nv{P2 zpmaH{XIhM{HPalc)^)b0sY9E5-E>_lVwH`BeZg>WLA_T~kap}&x@|WX)8H#Qc0>OS z@;-a_(B!JcMIJ#&MwP@dd1bN1t%Z&SmXpB%GdF_bwD}VgVU*Qw!HaMH45goL(Tf~`-(0CvU-VimNie;^)FCgK)Az2c zeZP)7*m2nlk@HL|=ct3@b?FT_?Ne|_G7(trU!u%@<0q$A>$7VqPR8_Fjl0`c>!5zz zUgMOJC^9J)i_i6lrDglN=iprCbcRIw&^3+<9PhYb{!M{R@N>NhVC5t}d!>&t?;`m~ z`$P5}sHxs0(DCS3K;V;w<4!ClL(QkF*PbhFW)__<7gYRr2YmCPEvk@8m(eFxk{O9F zngrZ-gP0((@U%A17--&*%G zIRK0Ur8n1p`jdBEG2NU8n4{L8huyeoZC+D$%!tHQ2!S7 zEo+Mmyic@s9TQt$o;4kO3r^c*b$rR5abFgFb?kt11wfK%+`AY>8&w~&PTz#axnLq!gHR0jSdFPd|7HJ>w9OpsFa!VQ-UTAABB+1=dEk<3efTU zm3#Pg2tXuWUBw$*srqx&qZMWDN%YyWy-b83vK+I7`myS9Dzz|f8|F~aB9CxVX|#Sj zy+w2U>ttD*7w;-OYC?l?%DBG(teA7K46&(W3t0pkYsr!X z&`D~zDxLP<|LZ7ii6gTc)K)9rE%qz5lSF(SrxlYQIs7H4k&Gkm1+3DVx22~7@4G&o zkOqtZZ8*E)c1GOt)Rhp6s*I?NzCe%e5|J(r!rrt*#~sDg+wz)jtqil3@*~6yiW8={ z#C$g@_TD9!K!BXU|NbO9xslK=sFfeb=T3ih5ASFCkQl@O(-r*>!{`?qM-9lXc;*j^ zo?b2{T3ch>K1_Ec=3{6Yf%*K9#GU%^mIS2?njK|^VFbsxpUYq8HUEb;RgEAw2LU`v z{`q7${Tq#UhSFS@m&bX5kS;0oNZWsi+O&KveF+d~3;Y$&cLaUZ+i#V=i_?y1YRwWn zi&T9uTFiOfMQfNtIAdRCDcPppbr%^J@7ZhizQ=_DFNDdk_N&pS?pQ|+xmQ(tPrXd< z_WLBIwa^QlF;$*FG%At7z4!6s=so(a)~?0)P2$4Yh;d7Ft^;`UsCJk)qz(u;rRT&E ziJ_v$zzS1p+qRy&g2=-z9>^7;WTWEv(BT+cdEIio@v7+uFKTy^hcoJrP0%8v+A}Ln zfsZGzshp(lY-kcK)Bn5=-y0Q09gy73!9H~S`t?}zDm3`Kz(>IVh<)PuaTF2XmlWW# zJn*wmPSMmU+O@RDcFp>0vYO}|n{LSo;p;lA6hpeZ2YLvN=A?V+*N%)!l>RmBmvy9g0(`DvgmbF0wbVe7?dPaWP!q;&~yT~aCNqQz9S$yFJ zHBvL{?L)oarjUg}(E-H>IoAe9??hHYr=i);x1dxpQs5(F>@5rM9=mJ*xOpCmTle^b z7cj~U5-Jt=3HXrkDZZWscgLxut@lDnKt+oAfyh!Xu)zV9Wlm7=q-5ytp!A3Cv0rcA z&HvQDqkZJi;ae^2@rGvbhp_In4dc1HL*>j^wblufNLfC+fNy zphA)0H-eP(E5LTSQipJysfl(u?&|9Lji%E29(5Kmjm185ViKy=F|#E$W;j3)!fwT6 zTjWdG#3dB|PSSPkz6=2gypEx<`0Vm6e}Teb;NwZGyJ`!_Uq)5v?uc(!Wl6yCn-V6o z)mngNzJ+lFva_t{Y|<}*jGf7aNr7p6_c8C{*Uv%09AVcB=1Y>qnrGtFduqEX53~@Z zw$|3~Q^@fiO;>P8tMF?!XC&GbC4|g9>kK@HlwINJw})2g8DDJa-VG`HwMe!MA6UwN`2vfW^KQQVgz4?U@mQ%s+pE0m=ON1<9>NNa21&`? z&LFxi9noriXMae_^BVR2dpHpnz4wPJ~bCPBv0}Xn|#Ll-wMWhgqkle44hy zuj4^JH?s6EQoFfO@WXW-ygA8!$R(qsAqo8LcZzE_{bh9woUkE{Tx^LtJz09trxGTl zCfC18;&UVHkx89?hSLOeys+V)Cn^Hr-IBU*#ilsvbU2Vqj7Za9&p5iCD6at5nK}^? z)Dw3QC0YqC9mT&vMB8zyHwmL-L-^> zk6XSZG}wAS2$0ggno}XU47$s&fss_pCE6H0)h^Lpx@Hx0U1{3LWMubh<&5TK7vW*!6H9t1CeuwNJ6?(|b`V4L`U zdYAUiW{OGYT2BG(GTdN9QxCg{93?jx1jhS+d{j}hXLbHR?a z;yX%qt*=F>!V$+s-YHr$c>85{+yGN0D%XBS8IgE&LPtGN?zHTDAN|g5Zp@&=o3O9u zZ4Ht5$vo|c{u_20Qmlj~PHiv@`zbneKzJB2!^A*8>pY7eHl`I3Ckz)XIZu=iGX))~ zY>@XW6QLqB2tJ^v1boQs&Q1!hSEFj&He>1O69f3qsUFf=g3Y1imTWD}jx4Y+=I6lg z2QiK<1a5YA8Lkd1D3r<_Ehyc+XJklk(v6yYm2`gBuptNMdXZC+E0>=g%tsqC5K&+3 z>vzq%wAB23ZRtG4f|dw%`VD;6hVEDKuxi8Kjkhk~cUzXL$mK~s9!I$&-z|w*^_4k3 zQSQrVa_2cvn}0J;;W!hW?U?a6$epq?M>dF6$UBY4o)v7dx3Xd&1d_Le_WIuYlw#Pj zun{`6ooRGxXZ~^U8w>`~?qqX+ms(6~r42(x3QwPV)Ld#S5kAtqde7fw`d<6{dqf;@ zV;4<5ih_yg$+yA>0vSkA+7}iIRnuHT;=uYfmC-Zlo@Zp)`My&LlN|JJyX36qF*(Af zR(6_aQ~~kKCQF0XyMR-zFc^cS;WSZ4uLt%m)Blqux%1g~h*h%fVI4i2(Sa;6p8G=8 zl*(K$hQE%iG8G%2z#|7cF@NmbKTYkANIGO7VeWu?1d`sZ9yQuHO zMo9(2*IIQ?E;#QtCl6=9uV)0b8Dg}s!<^cqU5HQ`&w!s{xF9+TE27ys@POP3F_Ags zyax*Yv$Q)Y!qn=n#Ky^!AI5GH~Hy zmwcRR0yX|c%A*G>u^+3iA$S{vt79)eC=(D6?a2LWF#fzijXX+$6URNCz}Y<;giaYa zoGr4?*pUL7rXqUXA|Efzcgb2|pzvJE&cudYGlr+z^h4(e?Q-Gy^tV2U)MRwvZ&LnJ5KiCuG zTP8$=)&3!c6QhK7W>XHeE@Ob?r$!Mu4H+r*K+6xVO{)a?-(DV1R&1^K?oW_HSBr)2 zf?DUydqYcGq}yfGygvfJ3;(&imKdfkRQENf4M3{~e-|FIq=$DUvL(Xf1s1nrsAL}U z=(rLTDUwONl1NZ;0{KJ2a-!L$1@fOY8le*U%p_+fo>@D@i!DBbvAjx5#nN{l?{*qc zg&ms9_=&=wXFXXt6iy;R1a%fIa^H2>#tyFZ~AKtaMc`uL!%wKKt6tFc-vR04ziJ3?#Xg0?VLh6 z#7Io^;79Nfh2DBiH0VMq+ia!CUiNyVXCW~=T__LL|K>g737HZC#*>OWY`Vq4^v;OP zf{54mI^ATw^$D7{r^8ojo50{j2Lb0sJ&H^lv_&b3(w3UF_l~_<1ho=7 z_735f_x<_apU-{&{_;n1o$Gp?9OpXcyq?e3!#6svxo~Npxq&DS4tXl!d=VR$f#ZTnFWk1?TkC{ zJFM8mt7DyQz8 z0@FP8q)l;GIXB-QLX0oALU6S)&Sv?qtobm7w$Z8kRgT85k47q5V_;*9&15QVlZnGk zL9ztSlB7E`8*_kyT^Ik`Z1KNv4TsRp-W*4VixFl3!<-Ah8|wv_8RYQA9> zTgePdaotB-FD~w=A03fPtDybbx^hT@ZPcsujRK&;byfob)PMuV-jZ>)plDawFWk)d z4ghAJt9Qf;AwpT!q7*@=wO_+zY5LS8LZ-oT1naZ*cA3tN_YZgBbD|k=1JVG;x5le-WjC>|V?HD8uX*GC89LUihpY}g zT}7{?G*ZNK(gZIiIG{yTqtOP-BDiRFy;(8KNeXt~aiX~o`gE*>H@HAXu7gM^Zl(VFOiBs<@b#~QEsh|8S zP%K1=zKqb1(Dt56N@b5>Ysm!sV*ZEX^^(e@F%8i>^0>aq$)75@Ps-iSSdTq)r=Y^% zL+#IPW&CY_Mf$%hMiW~zlAgIVZoqC`M`8cb#PvW)xVXQM)C`0CzE zkOV12B~K8^9tGx0e>&-=irc~9jCiTiwyU<&v|eXXNkQ5wlXe0Ywe@p61l-zAd}QVLK%qm|NOv?No<@bRDVfWxnTsnC z>J&ev3fe_2fPMXeWqrGTgfqbo_29Vxo!4PoEWvwzkaT(D&CZvKXd-L1*{Qr9E}q<3 zRleS<<*J@8=@ao}tK>CLGRwq$fFU*-7B_!{h4TRtppU6XWa{p`zDf)^IiZSa&@ zz_fAEU^8;ceui0&(2_Ez+zh%r`SpC3C=IIQWGWA#5gmP=bS8D9k9o>T_z*+)o3Qw1 zBJoeipgl0ov-q!mvOf-Y{Ub6<@HH5qQFr#?R}k|_VK-Fp)gmgNb=s%w?;5!yt zgP&P52gciq&%N}@srGqG?i_K4CX#q{eT&!Qu|+f9Zgzlo*>>pp-*fG0;Wnv$pV7PN zHRfHEprD<`ZB2r!qhdDcBU;_0s!gkO1`W;YS>{O13bNaG7qISq20;b^M7!rC&!rhs zLj|4Lqk~Tn-Ezs=_(iMw(FxK|M$<*`jgUE}=9gm1Vy$l2`YXmO!?A@Z4x611!5%I{ zBTHQblqY%2#;5ev-S2N`lyrqBguKwRcYR{^9hA`E36jAn=7Z5T&0%d(f?0fT z?K~MmFzbjZqMb~mDlF?6Tl2&9Z!Q&L`?=O*$c5jH|E>kl53#1|d+w&Vt{QeDF)4}J zM$#QewmT!cb&WIcvs|87ugraoj(<*Xvc7@bgxboF<;@2qxzp7xN0xdvDXc?i;~Pjn z;cSo{T2&7uH_%L+e_dcXHs0BK-DzVUxT2;dRm}?6nDb>i*-yfQSA7;keI!L}?!kZh z^4@@4AjqBV5?p2d!x871Y93N);@(428`hj9ZAhol_;EsT*0OnmuhhK=9T7<8+=>V6 z4yDaK>Sp-zoX2x)e~Zu0cJFekewaG>CSQ&pwHM@m6@9dwdrJ%w`ZPU>S4AfSEFF30 zMIk#2n1j%iFx+kH(^QEq<#*@yYJXUt&|Li3Na780=7ht)*Y-}-x1On2zm*|&JHv%SJfsqcVG6I!A*KNm zMU~pwrmox)c zo21q0M+Mg8zoiB39p1Z0u5L>6{*SXjW*cipB!%qJ?@zx#5_KhJR4lfI>fAAM3B6wg zntZY4$-cK(&lsKLUYnR4eZ_0e>sdyXl0IpJ{zDZD`76Uv?0Jfw1DiR<0JH(g>ql0m&ql zy-JhWbY=aq)6f?TzGY)|H+MFSU8=Pe-X)>)u1~&&HbYqEzKHp-<^e9PklV(poqVpK zlQ+a<%wd0ju}Cn02U-0Ry*-X>^}Wx~!D442c8r~?cMy^mvy*gKm=*^nHf*ztHOy2* zB9!OaAk^CQV&)*esxa$V@|4(n_9|OWVJyIn5uhMa6b81#PMTod3rIRFFAu;Ib zG*krOa>`0|cV&ni4h6{K5l|7?1C>@3y?>BJtij%6y@KmtI=a;j&22%9j$EV#I zFFsRH2fB~I!jj%@l5HVdu2hA6K8Z_tkFq0F;fREv&g##oNp*7DXu_>M*z1?37Bok_Nzg9$Z3zQE_C7PNDQO>P!lb==`wVrF+`g_KqDMCUWj z+>0&ZbxtV`V`Gbp31@0MT0p2=2v z#cOJ)y6OQM&kR?R4VF8wDevp1R=+4N-+S#RZ_Xr^x9e9opi8W|xIj6p zjR6Qw+V%m$s2+({Tu_<(RY2fs;{0LSmG^$c0H_*&rm|>}pET(u5Vt!2bYtB<5qp%3 zzJrL3Akb}!_v8f%b7-R!XPsp?(%UE1FIzwACMqr8I9+}F8I~08FZ$!NyQWGm#4M(t zD%K_ZvKv@mlN&<(mv1BI(Tn2pGpVb-?nJ)H15`JwT5!4Vm4=%frkJM?AG+zHRqq|+f>GWD`wC54Y zdzM+9lYgW<(;*q`Vs{*65eCjK6Y5sUoCyeP84i zwH(fcw4|rm`pA~XC$l(1e{!K*ZjaXZDRlOEzxjcaY?t)w+u?hkq{&zurqI0L@4L_U z-Xz_{_WBkmu)Odae}z3awA^3)HFG1Lej$j7&<&1fYP7+xj1SL#E3}1zr`UpQ^0*DJ zHq99_9O>ff3IA?6-_(zVdocm%-NeUeu?brZjM+ zyV`u__TF*YI@Wq0Z3a#hltS*Rt;j$X+l6@lf|hc5Hk5XLUVm!~RVMT$2WE_@^@)iI z4Smk?=rI`(@XI+)+J)eubWN$0pRa!6?8FW?`HI!tG=9eEsayq2?Sg8NA_si$6)lI}mY!9vHtG5d`ytkCIBZ60w%LzR>plh5-A=-a6pTVS*P zzUFv(K58jXoyD|-v2OW>fb>CCANKBU;UiP^$wvcfBxSY8>!3oJ(;8uD_=VGAauWk$;N9_ujZl`d_v8llD;olNEbiDqeXGKacX((znWLNqQz}+H1pXl z(cD^&vT}PT>V4YL!i6)MNk8iJX_y%BH=y&9!p}tDk#pi@cIRBwhazrCP>>9gEdtT1 zF`a5e*aWKFC2joBl2reywXEcMOw* z$TlO=%LbBZ41Gj`($jn{J(_PMFA3`y2Omi9_s@o?7{3AZ5Fc- zlu`mulKrt-cCI6UOE9YboECjW_^(U;xpieW&8#nu!sOdS$eh7^zAaCk{_HKDc?C)4>y~_)SjKYGlITF2RA$Z z7&Q4;ME~zDR#Jp@I7nLGXBKtb@JvY>igB=C05!|e+wo;QgZowc?#%x0^XSpcCX=|Z zsH6mMASr0Pvb+cv8gXHKT(G)Eqh63+>P)+_nf`B=JtAnPiEveh+x6S^$vZ6Q)AyL! zFN|cfyJlKW*Gvsa-T4_EEU7akv;LnUfC)@6!i@?Z8Uk~FeN(ft1V@)2-Jd#>E}=YM=zk`wpk0Cs}`;hQf>!wEq?Pd3~@ zND&+ri>&s4oBU^Z%u18EIH~M?d$!mU9~by3!S<2c>OwLk2Z4j_c=KAaY5qr#(BqT1 zn5g9TzhZrL826;#;3)o4^jQsy77waff5&I|KZYC{LRcpN^owDoIY;`b{=Pi?eABC# z&1}kp$_BnvtoXkN#SN2I>e=dO)}*)w7HKSwzIe;4I_F^X9CCj8A^}sy1V#TQsTD8&M)Z1h1|1B?AI zCtK^h8&Mc){{yRi97<+w-UoYgv{t%^y*dx%=jTt~ z{bq}+PO|@4D)7W{A1BmVbJE7aX}0Bq&dO}HWRXXjh*v@#lvMOvV174)e$8kc|~$UFz(4QSl7>^`F61NAgmo zZR90x4w5jKjqZ8s#>l`Bq@FT-FY*92Ftzx%*^eddAXr8Ic^$LrR<^s2WYM`Qume7f zb3+B{=E`NcsI!^Y40)huCl=9Y7n5a9sj!<%hkcwjlFf9EIRol!q*+8Wo0YXiWw|Qx zmwKKXes878ZgfHCAc5Ov#6pm@1J`voIIN{Ayc5GLeRB|n2J zf@V#>@hjsvAz^NCRF#SzyJF~q>FYEE))}CQU|hpVJX>oV#w2>qAwU$n31%ZN<5Ss9 z22UHffloJgb7W+MUL^%>-r(`&{9vWK?Vx$H-gB2MRX*@U1K1~W`t3F1NNx|tl7}TJ4%C#;L`IPGzI4eVE`?vQU`^8khjiTkEPd>{ z#X$oFaba(0jBG3OTX2rG8mY>{qc+x`%q5}B3*onv9Jza+WyEJ@w+Fx*f_hfgi8co+~NOtk`q+k)O)1s7+u)il3C>yGpJZ z5%o&DPl(;q9mzl(^Fc80ihN7XXZz*;PDQ(rswjv1PQx>H&_sE`B92J}5Y4cg*^oLW z5UurB4IRsoHh@rEBAbQa$sVAsJ}#}WwZRWyN|V5Ss6n2hd&Y2sssBIxj^v-C;()m) zUpexsrf{|PB>?aVH2nl_U>RulVf6-5<{Oock{dss(!>!>ez)OZ0ORCWf0xf3T^79f zdgRIXNWFT7LKq6Et53gH$e=Ck&^o%2Ha@hvs=_SBwb$?9>(vKDHFAChn1uOvH`xcyzrMIQHtFbmrpUs)wNmMe96>h@}AFN?L>YP99Y(x}!x|`b@y`{JT7So+=K*Qxr05WYQeFBgp*UROZ z5O|=ko98U%7r#+i;Y`|Cwt*XJLudY0tRZ1#c^yt~gOTfU>cHiBg&RB$Tfb@M#wV48 z9lkLw*`XF8<2z+X@!=f8dWntt-hBxBMi z46JUZ%1PTSkGTgB{pYIuI4kY=fdwKg#|Y|t zLIWVjLO3Q;& zxGqR5S8$7ZoSATvdg|?Q<~BVrAprqVy^(XGd96fG>c-BSV#2;ko}PZCsOzxz zs`?Zv;hJssFx|-2ap*MInOo@SO|+y&UFhoF73|uRnO>=`jFRMDpMYQ6KHn>HyCj=N z>D=L+P;R&NA|fd;6=SbIfjU$B?YN~Cq4(1;m(i9I=b0L3+2_|1WpjtcFMr(b`V-Dl zvuK)bgO{JdoAbrLI6o}iz2N}l zV-$gEwG(Av?w5PQ4$Z1Dw$)8}ZQQ_3xn0uD?XcNj$Y&`&(;}Q17@3$&R~rHERJgL& zt+2c`h|B4XJwDNB9NYR3YPXkqch|0uaz%GoMVCSNO? z$G@;A`QO1tW+fGshihq?u@h29^IyDNh?Kz`Hj;v4(D{Mt4q3eu+s-1X7f(hV#^4vB zWthv0F78USo9D#T`;_;WHf8G+m$M|-eFL!U^SP8mu7O-mx*O=Nk`Rqu;_LW3GDRia z`M|MKwWX{3=B)e*>MSIX>{-wpL-!m~Ybta$NqU4l%ofNt+258u;N26U_X!85?QBq`KE?`j-0sGlCcER5 zRfh*fgO*lTe&gx+h1yUjeG2eG@)Zf5N=)WZhefk*D-0NouPGI#03OW}*B90V^+Q!j z;5iSEApF_h>|ZTaV}dmXs1&dDFdIEYk5r?h7|99Q2qSXsmI*@%H9VB$V9!VAPf3*R zV}J1sZT(^TEoNa$rs7!uv62o;|C_mLth|i6-`N|arKQDVDyWne@IEbiq2Nvh0Sp$(n$sDdHH5z0R&v<_2rWh&~}4I^7auXw>fZsgM|-Uh_*Kw}^*fhWuhn(|>-YVRIi z1}^0v*OZ{d=iDSW43T}s3d~zv8(%WJbHlE7XH;Tf+8C>_b(8l}iybMU*wdLwhR?=H zW^KWZn=W#fOY~XEbmb`B)r@x8=}5D{rQjyt-PfRvLK_1Uhu@g*^=IWNg^vdRfj0_S zIV|c#!lsguBJj$#5p|ivtCP11zF=Qpg4=^y8owJs0D%nHVK=xVT7he8;?^QM_*oJg z$mg`1*d83MyR2T@P3e^pe=8w*boi0s5lO`k;zinm+7FxTEE5M=hQ{lHcdB!rZ%)7G zO=?Xs%W4M4%kzve$hC)J-~K-TOfuc{q)JGwxuonM)#Kr(5)F?5=M9fGdKKZ}7{| zB;1VjaZVPxYcN63B6>{!BXW&i6c_)SfgZ15jYy?EdQxRKHtiKcX|t59!Zi^hEy;uH z%aV;(-Z&UVvu97fRy#&{F7)Qo47eT#T?RFPBqNhMgb%pHn8|U@bpuxaY=4sQlwYuU ze~4FzCw0Id`fDMJ7URBj-H7mXB`f^=C2sj`PIJhUb((^;wOAr`e7Em?n;*`wH+f#aB*V`p@r0pB|JFr!zVAM+>Nb^(!R^6{7ikB2 z>-y4CD`Y`=31YCcPlAo7>rc$x9Q0o>V+wrz5an@CzLr$_b7kZ2bn`TB6sAb{jN0KF z()gbAy%}bZnS;Z|{TzF;#dR7l?v6}TRPtvS=K==DPLz|gK+pQy!4bTx(aV)4-d!rB zH|sPmc5@$c7?E(x`)_V=4#RP(AYj;BLa4zK!wZxamvmqV>ZcK=riOqDdq_cxcTJF8 zw@(;_6EGX2yqwhnr(pOQ9^# zooIdgo4OrDgwye0l`cY;$c1Ozijum#(X?fhXw1L5%MIJc6F<@&flY3_-*JK za;x9Ou)ZDg?4IGvo` z)Uv8#T*qfw^x9!8=Jw2b{oeNm~EnU;Nh@?*SYY#FQ=RtJ-nLQz%I*xH${Tm63WDJhn9yGA!rbN7=snr8hn z%4*G~pTHz5`ugja_4b7->~gtCy9V`)~$Ww*Ed41upp=|G9G5 zIPXm#Ex--3z-mY}%|O!kB}`&7#PzV5L^>q9IrWQQimclvABWtA75o76d+I_kV_?XG3Ri`L zkeyjv4{{_+GML#$Us)X_rzQyBQx0`uBU2!dCQh{CBvlq!E&Us{*?(5vUrqXg#3PNA zu2`!bjCjkZ#~B?d6baP>vgfo!dT=fgBp-67k=PApE2j<{nX1bjNjFB;?}n&ia9br| zSI`_mlLXkq>w0%p%xjBrfP1FjAz)ry;-*y_PUNjjc}QP&51(WLv_GbJYj(mnZc51c zE>fQ{I5}2_nh+pzVe!vPsWhbMN%4r(DZgH^*$L8pza+Fk0ej-U{zoB_GhN6zi*TS| zbD`0jhkqjw(-?|rb-*dPm=NDWy8KLZTgT z?{ZdzZ5~R(t*F6rH8;^ROx|*x?uD`f;K9YilPtnJ3Mu9$sy$bh^jzxdb0cD#@Z5KC z&-uaj==HM8aE*yCm+1RFeGZxor?Ph-Sl4Txz813h<)rMep?#h`bNcS#@MHS1K0-c^Nqs~N)i3*#z{jTaojS(+DwU}*l6 zSwayc7JCl(T0Wc|PDxB;V!3m$V(+QK5Rq)ArBxV4=Sb^?C9}!WjLEZc>5H4?3WOAL zbWYV)?#JveCGV}s8oa%`l*oAdAi6er|KwNp(<@ypiAu;9NV&a(t!O$%pM&x(jFMK( z^RL-Jrk$cf2?sNVvka<0J$)wmovUuoT*?w%8^RVD4x9flVZS-UsL1n0_#3_aS-dB! zGpWtOUWt<2?=VfcEsz>OD$88$vuiWFF&2w`Iz16t=pOc6_c&50RVtd*!X?}y*nZD= z_LH*v#Z)3U{!{18B9+_8gh7W7~Qb)Gmr2j_V%eJ>H=lEo=QU0 zLJjeQ6I+GUyc@w^tYd>>3w==sN75G0-((0u(gp}6RX?^OJdrbkFKVCYDj5Bu^2Sz!c1`Xb4qZo{3kXmj zN$JorziH_0vJwHFHxluN5pYzT*qA|9sgk3Hv1}jD?IKJ`1N61A&|cg@bt^i&`&+bJ zJsjz>b={IQJ#m{PeYoNRQVRUIABZ#Dq{qi^+?Qn>Y~*K^NV^|>ok0ts?&IEFxrp7L zVJNn;0_JOD%P7leUJfJ`kwg>NJRh&;k$vY68E2@RU-}(Sc=>#O6wI=}-)`v`Iheh; zx@r?(`7ssCi6WTG=dvQPh`YgF<$ANr-i<2%yV)uMjQ!BzUxho4J$26Vnvh800D`f(0q56$#a<>9(|oD9BT-=3?B@CUeVlkvc@Q>)s@nlk7rs}HzTSS7g{_TV znD}^1ahQBXK78klSTXCc&jlcDqo{cg;RWf?#m3h6a(6j>K}ykA3l=^TR&Ggo40+=t z!MdfgXyvT49ffs{9bH-EMRmjTPV*Ek9~R97&j>A9k7n|b9Z86Z{e_49kV_daSehMh z56$G)IR19Jh3)4E6S!cKoZoWLvt<+#E9@K=)tZSWyT;^Ye%{>kH5$tm)LsbpW6#}Su5PvH zoM4wM`9{Wgx%lkfh>IQv$E69)-Q(RxPv=t-nXti zD0~R59wBk(>NrfAGC7LDtaYP!^zyQ%H=b$`=Dn;jaa7Gg_-kJygqM0q1jOi8@I;A_ zFXfk3JF9p>SJg&pg4T$(6Na7~1YpVvP=1|Hoda=UxX?5Zz=QaJlS$?&`8_r zX8$sgFMic&-lgb+CvM7i5l+gbx>&*$sIaPSo=diwGW_<LMwS(~vGgE6L@og!cqu>$Py z&)A5&vVQ1iZs5k93*ie0SGSbi+2s=n!uGFUjlWF^3%rR5{%PpDzl1|-iTyQFVJ9;U zvVV=Y(n0jvgl3cm|LN@13I!J`5^n?goRch6@*x-xm(lq+92f3&y8VZ?GS!nAm&qlc zs=#}Mw>37!MMx{D3{+CKxp|o7iTFhFJlC1U@==68@LM6Zm#!2%$-{o8!otVfPKa<- z6OSM^oKFPst8a&ok<7eg0GHEc9#~!=vP6Assq|)G1X5ol(GAd^2zuaf6C9F0gM(Z+ z?hO_qkr7%D3gIdYUHHAFL8cOgS1sJ+c|xM2h&?f=0{9F>RW@!hY}M>2*Voi|+eHvN zGmD;WzcMAM5D+z0GqlU!or8y`nX{d_^hbsKU{u74Rhyr_k6tJxfbM9on=mlhqm|nq z*1xNKC#<65OZW(fw=oSlOLDBj0pH~CnIlTuKT}v(gc|qRGs0P?++a#j!H{W)O{#1i zGxXEjWDG>q$Q!+##c009$1hDSbyPz{`1@K?!dIi@t&`hkUMM1CxDA8LQas2^Hn6s5%SrNmUj|?cC(SkeS}ulC&<&|J3f0rM4AMj)GSPCE{R1#l_ybg>hzM~HXHyLc zjabrB%W{TQDK}73cvid}|4Pz5X3D{-=%(J5+Ujb(VW#}6{r~Lx`GHi_G+quNsS?~g zB$uC6xTznQj(`y>O3}|b&EN$|6fdG2y9kuS ziCAIUCP(^%{?TUC*;~=>as!;6gMm=k>|nOLpJ%*= zFG~-<$-Mn`v+LWww>M2nhA=K^ysm9>QAL5$S^g@C`D)5d5I@F|m}^=uXW`Wdu|{B`71gz@rS6c5t`|Kx?5JG(J4veN>joXeY0X0l*;TbVWkH5K=4*1{(Ca-HhM)EFcUz@yl*MhrZ(Q6c_Ry zF92-e(r|ywY-Z32Y_S}PC1RH>0k(qpFor$`qwTAz74NG2+thz)G88>6)h;xW4lP`?Ij=F zU{)<1DIfX74Zr_%8%Tmu%7HmYM9X#O0B2$Z(mZqJcS;dd8HY?2V`(seRa`{-X$e+X z84jv>uPe@EQQ>=^TGjSl#bGt+1=n2{6>5fyEof*6rDb$*00J~!eBXx2Qlm&AWLy&K z=g1QAeMTn>y-072wA^1`N+uR#3?eb+^?0Ayk5g28#CXdbBSKp z|AP*b`>_J`o;zdwA)UVs%uY&;;r>6;50AyKiI(sf>#T=s(d_@ElkJ!w$c#&Gf1O2*m1nLUoM3!ASa?%S$&;jaFHTO>&B;m)SOz0@80c`@S!*^j&+E_v~!`a^i$(0xpuu2a- ze4dk@1i$&-9;mfs)YzXvdKvSKkWFoF6r&+r5QUdb6;Kf??RF@Wa=qR;oTQE!VNlsV zKLJ{7vFwpG!k35JjeM2+k-sw{KI%_Hk5;~3?xGWLULrwLkVJR^fcqQ_``VWhvC z!(^iU=67te*hyTi^qc#|*zuoZD^6v;+$&sL-MRGGXK2_=?VQBeKYE_^%zoLFx+f<0 zD{ft731`KwpaFliuLB`pSuE%pKUEVxOAnD`)Omjgxh(&R5Px;NwZy|EhnYD3u}7R{ zpB;ypFbu#+LR&Jb?@;_qUNsi^f#%7B+I~dJWCbRY4!dT4zMK6miSO#Yrn1GH>A6Ot zpdJ2w8qS)I2Xx;_KK5}%r98i1@w~uQ4?q_&P=%K_WPd4JNf!C21`=F824ZJm*L%Qu25Sse#Nv>-bg*_&k z?u9GmLzWeK2{!z`)0EC=bnXh9%y_JXz%n(?yMe)j6Jv};Np$k0e+bFLzZM7^x-?2oz(Q6~8fq{tH6kSmrV z+Ec$qO4he|e_yt#K$|C?0t|eDx=+X@CJNSb>o{)Yz!F=ePSC&*A3T59PEebU$7)@5 z-;}WVr)pDA@^&F#c}#~k!=8%xQD6y2-8xREUIC0CwqW-Lt9H=UFP zCmF#^Y@tbC$nB@GCCm2YXt8H`H}lr6*T*{f>NL zkH}0?=DQln~1tSXi-pr|d1S%O9IxIq}8Uj7=Hs^k1zT$j*ldgae2JV|6A8SOgvUze6t1W z`0nM{=*kqs7Eu)Tikf7U5%C_#7|urFS)}T*N(jZ=bFT5) zo|7Wn{A!lcJ9dmZ{xMF#tICpx3x~}zB1K4_)tw-Ve@^7u=7yvsR(O)3Mk)teL`Q{Y z>rT^|-qov@T+!;jmtPxULdd)3iIL{$VK?E7?Q-Q$O!IB9tjEvJdVEhFVTT~U&W>OykcH5__lx*aMku{k!G$` z*+UZLp_o(2>XK8EMq93jVcEZCiImIbBD%EQeVLo?HPff$&Z_xE^ST8(*H=y}#PkZD z&_gKqs*?A8G7H#Ql8j_nK8}~UhP=G2rIXna-fOlm>-*X6D}cNe1i2ZFS24=!GK>bO z4v$2yySDcPJEhNBpU$}3)+}}DShY^HTr_;>n7-;);9i zim4qlYN!^jZKTrnLHw6m-81+M-sIufu)hpdLqo$X?ATuj?8RjZVeyt^RMq%Mi#UFK z*P)~N9>UkO4eXw)6qz$qElrS1z5@7`qwL3xuj#e~s;ndGXUc*4?9JdRP75~OQ@bG-2$T-d~Uxz@-hjpjPJNW2<($ zpzk<|n-fkk?@7;)C8j!c{KnO_xv_sFq;yO!Wq!=}CkKLi{xrbbC?nP5fv4J($-Gp} z($^ceR>PQi(MKDLf{w7Gj#QW<;uuYH9GXsO(&Yh@iv zct#z=f{Oz-xDK4u)*n!V_l)l^ogX4Db*J22eH{KrQ~Zy^K+jlCR+3#@{8cUqwd5NL zZ(dJY?2N=Cf>N5er1Q7H=W*3R%-aN>;%cWA6Etz3D_T}scW81ZuKr$%BT2Nc{K;Ot zf__E^kAx-A7^>Vn)Wb%*;v}2Q9>?pV4ou!dbuyC!R;H#~DN6P&G$jpHlDQ3Z5{TB; z*M(e__ak)uQUZMxn-41zcHMqsN|?NPPg3KO3D~9f|kfXpbmXzH=D=?k+>ErSLj-P;4N;gM9Ke;z2VyL{_fju;@)fd;1Y)5m}|8-m4 z1l(=&?kx^TT996%M1KnYSJM}1xQlOiCOE$AKZC2|{WSa!I{{93|BeP{sQ~ahz#Koo zs8qhT8U2^D;_80}mifQrsjn9PE1qmloRFOt&$SlH548N58gg}ZPRXJ0JNwhz)D=$f z9C&+k<-U)rL)v=2zx1=sW5lw23C9$0$5B{XE81lA%EK;?>$oP{_ivm=q*N3{ z+5qX4W&=?{$s3fAZjh4BZ6F{bDJeNn5Rq<13{bkId&G#*jND-Cx$e*R_kDh!=dbJa z;*X2%x{mWWkG;=#NYz<^Xj@JXT|0yWA3AT|=}Ma17E7FP{_huQQCb05E1j-yY-o%C zCM5p=p7#zdtwiVyMFh;yqG4TBWoM~9OzC7}ef^bX3&5~0;;QtyMe3_nXmOxp1F-!4 z-RY|8{S`Se&B#UMF-p1*j=B zBz|YrHQX-`50@jXbfPF%b*h(g1PGPcs*y{y#Y&Xa_~1k9wXlIqz8AALzgi6`d=<#% z5)-@>4K}OD&FA7IsXJ8Ghqd*p#9IRNIn1`aeSPcB`bArlNdke8l*K=h@fmFwB@|W7 z_9Mk4ya`3H)18?_Gvd*(MvGcJ=Wfry(DAY6{=W)=hda-hIvCS(A-l7+ivS;=s$Cy7 zw|tFV&NKgPw;q-H{2n%{1gMJ^o^+Uwt$7cYQ{KCRXGM~}T?rqWz$J8b?`4g`(ay|K z7XzUr8P`|;+`z~C;B24x3$y(m!%}It-Nlzw3csu*2_WF%%zvMM3L2bV#%i@&KH%?h z-*eP4`F;x(V~5smen#?i^BP1uJK zFLs=sF$iVdiX3L0_FXVhN2t74tfGh$MWRI%mQ=* z?IZjY#i!NRJVX@a%&hmSKe65>3}nM|P?CTF3XXYHRMD!h?Jni0f35 zgmI=tP_D?m;^BJg{1-bYgG%0M{+ddAZTHAoz05joxg%=zInvbBK~La41Z8mU@s~j*h16$W$Pp>3pd`5A%%-iA&|3$V7Z(J&W|n4o6ps%9~`{D zp?K255!Y5}(;Y-h3kD1+jCeZIL`Wg_mtSrSf}2!?}&IvU>1Z z{FS9<`DJv(Fd)m(_^?{un&Xzi&H8+!R{ObSA&(`eEA7*vP>;r}U#{}y2>FfXQ6Ag6 zw%o+zetU19uO<_}N##gLu1CClrt%;DF}Y|8$zwcOzbnzeh>07&TU?!-5UiUtFjfQ68|% z`(lJPOl380S!DmKV)VuB*}`x1coAYz2TXX~vo@Hi@#v59&6~D$qUm1y*4LlD)4cRd zOO)jRL%;D%qf!SN(1~BEm|PPpb$Z|_`AHli*xon|cG;ZB^F{-YXFcaP{dT8A8v;+> zwfm0@=KbkoKO3KaO7ilu!|H5+Ia*ws7CxW;qFsZe zio}NHL&?((mrk<53$i4V>VG~q8xx<9isk&iuiLL^eEW1RCg^recU=uiWG7y@O5XuA z<38^9rsTuiX{LkXmpdC06S3S}I_8^arEZ*qukPR6J+qTsOo$Hd61ABgN>C6CUhRst zcT*JfdSs^x>RI{m#Gi+A_tw!3&OKv)w<0ZR2GkyR@r8 zGd*wRW^OC&U(}vG+TP=}+-+o`gfdIb*7gIrm7(C4x9<7Ag_!e`B?wyek^=vMSlFT~0zC6ibJR7c9 zu5trgQtCm|v3?uDsd&T1;<()ndi0udZZhXt=s19~++JF8(UvzUCXRF>KUy|a?i=xN zt@F(%f9>9CjB|llG^Xu=;MPdt^J_$BkC!h_{}@b1eYZZ|Q(FC+o-QIyJeex| zT>kcLqw%cT>}GuS5I|-hf)fjR?B~7RLme67^%90V*MDB03y<|JGex}J`@+ql^nCs5 zb&}Op<#eeBPqO-h;2D0H1ej5z#oGW zwE%{B?eu$0?kdbSg2!}P>_YF{!uJo=TsjQ?Cj}G}rn&z1e7NB-85SJ~S&@9#68EPl z&5%O+SqN;Mw%J!0o{~WOl)&9mE-R(Y@|QQ5p{+yGLrzp%?PiTxH;t$496}f1<3Z?o zc~}xKU!jyNai&qqh{6P!jX#vvC?Z=b_)eyBc+QNc=MH(>dagqjrpNM#yr1jLR9QZK z3Sp7a4hT0n7PS%e|3WK%>v;5(;%+M~-KXTX?iXKdWLyH?#n2_?Ci!NE@>@_EJe=H6 zCkeRYnn_;eT=$vMJ9I%Ba?7)-{qZ$7+sf}|4@EzvB78RDgo%Z*rV=$|nUsB%*xT2q zG5Rnb8(SEP0BYU zs((4tvo|(s_(>gUQlEMck;9VBoyIIJQK6E5mL@)ug8w|_=&YkpJXC(FZBa1+yH#JZ z@nqKm5-sEV;Ra8HdQqq4#p74ErVtm;ki z4W0q}I869!g$yV(J1L11GISMl7MMi(!gnT%Ou_%cWtZVri;-9*`H9tDAoyC#^H07z zx8_?i9U6s2vT-2O^}BQ(!r1m9b_P?oCtmAo0^hW9*ko+a)B1fpc799^Y|Bb?lq2L) zu4xZt`>Q3Cr9lqDK-N1m z)HyB4v+pcMBPVgkm??c=qZ4!)`>aRzfi}C;%KO!>6KmQYJ1R@Gl-rhf(t|2!v+Xwu zBiC!#s!tLQAIKDLOKGu(E)0Ij5#Uz8##v?VFgzqP#m+zF$QAV+tYQdh*L$B}HSF-S z-xl~agro_swo7o@_%idkP^f2z&v>k?&DACD!!;rGuK^*Nv|WDti-NER=!2)s1GGK^ zw4OAtZJ**V&oxO{bSW1)C^$cHY7X#$KPY-SLhZRVvw9pPk4b>ROK(tPkS8`&EzB_zYzI9I=lJA@S9y{dmG)^m7yIm0Nwdq?R9^88j6h6VTh z=M7N915Sxlv)yL~<*~GxDz{>0$Re&rQI(aKp_DRwBx>T+d_kG9N=ACSPl__KU7QUpD5|A?0E`M!bkEbIqUN%hIx6WyiE#BkzU(_s1 z(5!;`*qDd!T=N~jWYhfOOdYkC%>#a{fu|IL(00WtZh&NQ;*>{T-)YYmqRBkJ?s!r8 z$yaPM#=<7;z>ck~`aoB4FEI<#8WRC|ypsUqDfGoXx%$I!yXnIbpe!|JPvD33xI?F( zd?%N-3qDw*ZQQe58%nDDN)5PPJwfYjesINrH|~25mc{BQNj%;{>*$wSa-4A939`xj zJ}J2e7-%Ft<=zRbp~Df$Nl1vqH~JqO|JR&qXMx5<|K;)i1^wg4+&^WV6>9X)5Jay< z_tw&&y|LZ#AxYT}pRapv>p%A)qf-CPy(s`>7dQQ|&_cZp+U;wzfDvlPcXVX|{k<2u z=gT?}6F3O4_l_`Qh3mkuJh(9oH%zv)w9I9_ckkT`HMLA&nq5bMgU?5TFVDrharl$% z&)bGX9_WR$lT(ostP}|?Bwn5Fnp9U*eC<1SEv#Nl!2!c+GY$w<%q%J@nisWqaL5EG z71Gdm+h4wr4_4af52DewdrbSNR(CfPG6~GZ#npc}lqHvR@fS>-cl;L#p<`euknPSW zHY}F{5(fJq8vqAuu-H&?@bYrQ9)--iyy{KjVSd2PP(_fS5ocK(mRh zbeMm~75G=R5qJXq8G!D{PAhg>zfikCJSd-)jm;Suj7uCVWE}(`rZg#qM4u$^0y+;0 zL>>3Fo{g!fy?CLQ&8IgL&$sY)_mM?;XQw+tF_Iy617y3SrPHcu2TQ|uM&_?Qvmk`q z;|riK(f|-^P3q*%uDGmh!rT_1x#x$uwj}!mU7Tv|InNF|)D%SGc29Tb5Ut|~9ikwn z4iERof0CWeA1WLhljOfDwRhW7oiqZAiyTJ*YR`GYn))jxF|n^(N{c`^sYHsa)EWKi z`cSq4Le%eFq(mXZ52*3FM*v*bdVd-n!gc%^q!3Fc;qX!lf3Ov z^7Zg?W7^rj{S5_$bsmI)7~BeKesXthjO*%rHGZBiHhZ*{tI#)H!^Q=+S7=yfI)qD? zIld!`%m23KsiUopuGLYhX_b3A2Ow3l6IK=vkhLD~-;15G9mO?MK(t`vWnB#cyC~TH z4?ME>Bs$nNpI4}(B!(W}wxy$9$jY4PtF{3yvp|NQFd?r84)>jTcV{(6x)05r> z%TrFfzFFOs2ygiqnoZ%!WKQWx`Gj;L>SxOmFDuiBsA1*P`rbS;1Zksz7-sUE*8;}W zWqJB5>FDjD-wJ^Qn<8N1O@gSK>|*ApEqKlvzD2v#{xlfy-J{Enu}emxl?JPrVR-!93H^{i89R8T)E7YnGJHetlEYXF*I!kawn9g4B^2? z>#j!tMA&TkifvO+Mr_0nW2NHbs*o`DN)ZRWx_qQVhHnlYhJ)c!nd% zQ386kTc;?#CS-nIZ!S!PT*!L7dWer*1ns|E^VJf}*TltX@-&z6WvdrRVn6y-mG667&@M_8=j}e9A z%qm!=p#?n1L&$2^ps9A|Gs604L399=yrU~Da8~S{&D1rY%X@I?vg6%HBQx`Edy^Ki zG8sjMR}Nz~ilcAwTR$1!k;@mio=*6#x7{0-{ZWZP$$l^Pc0Ip{qF#RxPG(XN67c8i zN%d64cjX~#t1qNrsytFR3Gtt8FX-*46%)%PAHNysc=ucU=UjQI$FCDr)98>?J4(LvZ!8K zc5dpQ_!58Rh2M{-jcS zoix46qGt6_wxtm%awneF)T45nUkgIoT2JOil*F}v{cbJtEolwPw z#`1-pW&+%0bqSg7Az7X?*VHXYG==*53K{Ufpdclsq`8{f++<&U1G_}{;SVUutBX4t zrx#gnt;9RDI5_LlmSTl?LYjgJ07&*jw3Uv*YpO5U*b?zaZ7q~W`=Xm zk(27%1yx4Hv;7zX_^Kgi+i?iX+7ctzZZrW))+c)KEp^4hu$Ow^G1T_#+sW@$hq|J; z{y(xX+~^B8-p*R>H2OcE`^t_YF9Bzh%s#PD8hN=ht1qgZxtdSC__aNzj!jE}q-d0+cZhHou<0eBszQGDL4Dh1D&IL}a$9Q%gcX=x3-!c4J>1s4yVrjwX(A3f-+ z$i&vjRwXzqL}&G;^?!c;YUCsH^(j)b$$b{l&l=Iv99&!`q-fsY3TrD0_Swb{xBN@U zpL3CaA-Necxjp~O-ioS&**=+xKddi7;aTaq^M@@QD1p;nqqP^IHVe&e^>H+s|aCC0Zm zZNy#7rnp8*Cm4$7irc!b#?z><;WS;Y9mkMgQoon_lgW;z$pxxHm)qy?3x2Gn7_AaOHqkYZ%TPJQ6!l{+f_9@Cx#$1^rZV$5aB9fHdF5XT@Xw|z zYnO44IAyz@P9q8$L1kf5n`{Hlg$+~eHZE$I;G*_{iSIqYd48tdh<6AY~udK5M z2R%Gi&ATD4AU^#*W1-_dYo=n6W0J{rZi2F6z?8q;V$LhJxTxgQ_hrBeliK0SQM~_e zk0e2kzy%$S6Ze2>Bz3$mlXutqN}5Cq&C8uq;h3RL_W~X?tXx8l(0`QqOuz6JCYN$aVQupNe# zW{zpsZg=2rv)(_gz>{1%coPzAhg6PQV;C6;KFJQ1V2E}H=US^sGGMA%xv*}brd(t# z-eN49Y7@T~bil^+=whED<^TfofLRNeX2D7q+&+ekJR~XH9NWIs%GXy zT5XBG*#2FM4^T(9@iV8@p$~!Yqkp;CSpuhJsd+%aeHXpoihg8rD1!;Myg*Jbv zB(=F!#U0|XPfl^?FsNndnPWw|V|!?ngU|cYW4e`z8~cGt$-QIfb-U1{G|K0*+oZi) z%|Hk%FfqO&BV+btD(Qs<2J)KN8@~zPYP#;y5a{@4Yt)*wn3;pAj#94~ue<)P9}apB zvvMgh3NCQ|Fva(|zb{Ryk|iyLtfsTRSx8;(-Br2KV^N2nesFH3 z2j>vUIRGhc40@6N8YD&3)!iWHXTt`nS^5MOQ9E-S{38Qv;>YGNew^)%Vd-%y z)9m^aNQfU&UaVbjs5Lb>KLh)}2geI$&dbNYYI1vf!hghbKn9zj@10%^d?UOXa$Be_ zc)7T^b3OJRet4qT&=c%@!o{eC99kW`OFqk;!id05;eh#ggEfnfPf1xJW8<1vQ=<`h zR+Y8Bl~|Z5MS_suPV=Tjt<<_-76fgLW2BgQJyAE~%}wQJ$+Z*^CAYaeGsU)1(=g{R zgE6(`am#OYe8d@zR~yEAs7EsPUDO9i`*d@Cb|al?WwsmWL+}$<_eEF)2vjkGPx}PU z6hvO)!+j?1)*i};)~8js3}r)E&gKzhJ(OLfxY@N5ryBBrSi{ouGScO)>_e+TchZ2$ zgw;^Of^3w(O!0k2LZswvRhzgO2E8ZQ*Y`#xddc?g z4cor60{X?2afq<_sJ9j$?JF%<6O<~U{B<3fT!QUC_5ohBqxtVDN5Mjt%<{N%$=33Or-C;1z*anoWmmSLRh!1sAzvvQLKro$gX1#mO#Z2ne~txdFBXnR zzMkWgBWUk_>V7K1v2QXR5|3(n8J1B|@)CqBH})6FNhaJ26AQ9h8?o~iP@~r-n7MWLz`2m3H2O!n6lqm5^} z!w?KHBQsL7!2b+7=I6PON1eZb+7Na%)378Cp(1prB1J;kUKzJ$g2t z(iGb`{S0x1wWA7OS$XL8_soZrc1vCV$XHGo<0ztrVQC?kOS^ScTPL=duUfqoZQf^W zYT$COR-8Ur|KhV6*KXnPg#Vh=Kf`AY)nduDMRAqxBBI7D zrL6o}{i*U$T3Nh$3pM6!j>0o^^eXS3W5{;zb~{d{U{i zp9BR^Tuo$%h^Il-AIDdFYVxky3n*MLeA54LdP=otW|2NuNHDR~8fV@UG%UMh>COkt zA*09ZvqDJGd|rx9lM%R~Y}nCC0l2b5j#t;B_U@}RxX5P3-P>Fv`hXYwgDIoCZ5`Sq z2nmxV;4nAO@s0K^kHDD0vIuhor&3_nGd~w=gdM%haS&+5+e+?@&g!41@5pU~6(M*b zcWEQa&{up1C8bX6?^Jg&l(ID`-ZjOCPIQ4z`m1l*Qn4qDXdlyleXuTL#&}xrIE${6 zq!-yIt5R}Rl6*Myn|b#w61OJ_V==z7zq=ybq<#??y-9s{txQMEI0_4=K&K;FKg&s8 zL%zAGlQNx4s=b11#KJ*oM1+@v7h$uIeyyEAayb*erBB&Gnu5r@nO{x&dY8|cAe8%t zQ>>u)YB$ej?XQmGH)2t}L~&AVn#9brInB?7jEz5(K>bx!_qIV(Ijs1%1V_9kPYg{@q(T6pD8ks4{8sB+LO@=keHvMQI?r@@cI zuIl5paQ`mV|7llVK)W(mnfYLy$WLC~*6_U7w!qVwl3X{dYC84%PdZ1Y+6LaQr@DM> zOsNgbucL3Dqk1j#EWgxLyl|9g_Asv0b(GxAGt*4wPRb0W?4mGb?wbnW@#XM8HdaUo zV`=~Gi5cx|es63Pay~HN?dAuIk2TKfH%8)P{h41(_4Yf2bpFm|zw@pJ4%&c#PoB_H zJ+5mAgb9Yu^X3xrw3ql9_b8YpY&yTaWLrB;?@Ue|8;kSFG&a}lrxDGKm|O|dJDeE& zNcOD`N2XSW z5{s|4%7~k4*vj^wu0L8xG)cc8=m1A5CX9iwg6r$X>V*Aa0_tPP)h@F!9s}zuB~IW; zEcd8EQ<28~Cokmz5TYfbxvQMe(d@8yf`sNO1^*zD>*F3bHIk||&fdQ3UUn!KZJ(Vv zXme#BvAZD^C-vHEWTVE6biJB&0A1jct3mw5cH?BC?ktItLw4?AbUE>JIWYxf%6VN1 zd7|3L%2wvg#U<@HNmVHouf(#sOr6HmpL&H%wO$wD$7!s^F|}*IMig+ zmBT_HF3Gmx&k2*x#fxi{b+1Uh!k{J_-R7eU|8QZoDXYcqTJowe{Zw%v$@rwjy-k^v z-cGxzrAHyQr1hSc|62|9)ID^W%uL0Nj2(1+k_tjon-u-rCxoWwgml;4YDBcAkmc@( z%)1~b$!MNyB%dcFwvO-#Z$78uQ&w9)7e6=4Z4fhRE&%cvnI%A#%y!Y=>iz=pZvcwB zE=7`k7V>4uuN}pm^&F*xF{v?8X7KJ)bzo-5!}q<7=`e&}xE9{6=t!Y#ITPe5fy%g%=1zjIA5`NzuV?0T3Tskiz zdK?-B4A_YnOc5urn+guYIT|ORtPLlc$4wHBg0Am0N1{^u+?%7_y`GA;U2mMw!F8PJ zXOb#s-dj}#C!`))ad@gd<@)I{Vc2rQg}EqVho-^YmG^4$Lg!O+jX>r;3)Ld(bLYD8 zWLv{tO*I$hO-z;`0k$;B0H*KImEtsqhqF^MyT3}jo$HT_Z8(T;;BUKUMO|)pxDL0@ zQN4+8To-Vj;eK4$G`SwFXBgrp>EyMPXOkK84)X&NVBD|&pisB}r;ht`MU2{iYU>Ed zFmWhfjwDBrWnQBT@QskTX4UbQ4+O3$ebTP@p_I>s9LbaFpj`g?&T%7pSl>?y3v zZ=5Bof-YdzqT;>dgI(UuB{z;Rnfig+%Fe;xwxsY3`Bc6mYpdY;=5wsEh}$b|odjg( zs|>2>tL4-}(9w>u+}XVKKYUP+0@r0Mw!TyO28yhZeMOUSsx0yb(4B6FOel zD4C6Sk~@0a%)IGpy!n&uaR3X6Qf7bOeGNmuN6P7gndf#kl2{9cJL>!ui5Wtj!l*z2 zh{s%agmjUY>5~__scxfI0X`1byfF%$uHPmWYm7yEEVzmYMr?-f%|sWshLbzLl6iDh z2MU%$_2w#1c`_LxH3ZX>49?tYmC;rujZsdEY}a>2&riZmJ@`sQ!1Kn!sYR%PDo>jDF#}#qC zR2|_g6Fyq=o{UnU+tn=W`gAlt*A1I6ysFJ1L9B%_<_A$4uGzj9L^ZgAgicDl9K|)$ zSr*nT>BNcmT0^p4Op<%q@}rbRTCsoC!No6b`|Qb>XYW`0A6h)FcuBc+7Ym@Jg`xA@ zPul2BbC>)=UR&JR)Uq_^HJVEIkFu+>DGhj(hPYN+^4a&1yww~eu~MnOY!(sZ15HN&>WvbbWTm@ zS=D9$4YpqQ_NT{dz-7zka3-z%i(6$)%CIpevJA6I*bE(hg)*jr`$v1JG(h2c(a ziWdAd$AeoN*VMrHSfkWXONI}b1$t~CgBfXfBP!2Qin*3RVV4J&wH&?w)_aI+gD5ag zMxm_zz>TMNXX1k!-P`wTG+m)LH+7-P`K5t0eU4*1Tz0P#(Vnm1lVnP-GH1deIQP6W z<5ohr?>0tn+vEaXNA{v1#;%G=2vmMRtsGotfuqwLH3JoZgphc+^RGKE-r`@%X{o~9 zxLEL!_%TECQlx&{M<_Qkwf|)IM8bZOw$Elh8R}RDLTi@g8LN zQ@$&Ga?sL)x-K7GPc1W95KSH|uF((m@NoI%3=^yGZ3-v*ffZlx`xs^(LvN>V-VMtZ z)tJGc6@C0tO;%gqnc@=ynYA-Ll< zZd*uzSt*sbb;{X@RC7Rqm8?fbuSrPOXSs@D;<@$ruiFq2rRdZMHMUJQbKWDjr^4~h z!ko-S3pd`i9D9Y7n?ijJ%dI=#QOEDCmX)*|cJ5w#A7uR47-@WtG3(~;=Z>xno=+!P zJw{ujnL%GMk4WU$oGsl+%RzbTRJsq7ug0=@-wZ=9UW(f7U(IUoj++q2z~l6r#U{qG z*KK_*;%dvs-DZbPT~w)l2hyxtcV9Sldzv@y7d&>Oe$OIp4@LE3mnNa}AH&w>FLh-=TW?n&jEaOV!Gb8FYG~;{xdX+hvtc(q z)R=PF2dbaF_Z-Q|!i-2}CVu@>ewa=(dBF=Car+>mu*2@Ec16p*|6=|6n%(JQ2IbR? z{$iE4Mv~EIHEne(es9$qizZG@#{^g`H*3wMiW+|!7MbinDg}+r4=dWzj>MFo##SC~ z*a^LLL?A2NqMcPvV$(V4b{`p);F`j)DU5fRKcyJB6ABB|z=5ZFr{-m@?uCn6`dO`b<=cqsPQ#wVKW$w@98zA99)t8>H1Yy$T1J46JsLCoG}Qdg`C2G@a1#eZ z2cq<~tW0jyDrK`4mV2IT&o1P`rBIawr!B~d+YKl4VQ;jt^RUI7zRweP3f?+XZgy)} z$ip_xZQETkgHKir#vxG!&MrqjYjI2a*A&V_q{mN9pIw@p+BAwrLfaM`y+Hj78!U!< z+LXs!d(P6>by`B+-JwaYDMHs=w!pKZ(_dskoIQ;G*A`1H)-)G_w#X zVk1ph@bWqBkE93lBGjAwq0P!BKk4_d37T@>6-DP+dy-mp-gcy=>OoPXB8s>r23z9N zZm18=cYk$CYj8C~*YfPKE~FwI@R1ld>3f_P7~-<3>TOVS(HL$B(Z1nsKxjJPoqb&IUZ z^G7O(!uom;MS^?Fk1s23dLi(i9!AL{WH2`Aja^E&83c-DE)_1e? zbH2MRv)DJkTCQs;d40!>n|eSMqh20{VcX!1mm&Xy*=}s5e?qIl*+#k&=jqkVRr{)+t4bDyrn{zsTAistg`(h>%txhkKvfsn=ij*=PL`+q_{P7Nws=F!ebRucKpEgG zlq?_GFD<>66iY;|Oz(%S_59`%#*Ee&QuKSZd8$scKxzb$vc9`+S%i@*(yO=4V+9W7I%EI%;oS| zPy@za_UVo?@@d@p1K_Ry-*2u|-nK}JwSynp`vZaP;1tdkP30V+HS(~QY{Mpf;ksmP z(`Az@VMJ+gW)SfA{rZkV#gO2_w_;eD|NkbsmJYY46_k-Xk|6&jbu1e=Luj>EFQ-+- zwJEqmW{#w{b$;qvVWc7pxWx@Q*gA6yjwQhk)@gJw{`Won_$#PG6gdJ?OIFEyb(&c< zQV%K6+qf7;diwmMjaPS9yNr)^01588&uTod zD*o?#J8dRw;_4a0@N4wS1CQLX8g{7}m>_A~r$AwFNd8B4uwxo&zjdHahRw6Ls7m;= zTHYH--{Y_db+c!Zg=vk@O%HP_jA+J`9jkC17d-4eC-8?}^v{S6&LJq~xR~#DXGR?o z2A7ZJGt8-PCD4`yWtRn{neUHnYmgmJ7PBVMJLV)r2q(cpUq{RS zZ>j%V@jK>}zTkwyqfR!^D)o;H$c&#NVS$JJl_ex_OWDiC^P#G=Uy4p|pD?>-s;e#_ z0I8eWw*AYgy>BK9t&mfklo$D1xyF69bd~4w26npVB}oub!Ci>rS~LpPs(rGWuD@rw z)?>Ezrg44mh;cA8*_UtXPGOmltp(Qmwl!WZ;cAbMBH`@&+m8RIQqKe`wnG)uJ2ShA z1ZcVERDV(BH58#-~)YJ8_M7m-v+?q~Jugu>3_3uP})>wMN(nUQ8K11yGO zCf;GR{vB@u2=dT)l<_vLT+cciD8tl>B1K>jI z@FY}28zbbt@f@nKh8UnY)vRuC9&tPagKqRk5K@t~UWeN*N5bv?tK%u<+9An@zaLFZ*@R+!~{0GfmB#>Q$(e9$ZG&9nDw zx)RpazHl9GrNm$)itifyB{P<9?5MYIVf|0GWuUb;%xk@)ef=E$UNU_Na=JRT-t`?} zFQPOaAd6_vQdFG3^hGOEoe+bFkh<`~1r;cfX!=#1F^S;`qxrA{H!Kr-o-9o+_%yKL z$mD}3Y7udM3MIqV3xf7e<69Wes;U>GKZ@qp&M)N_o*0>K)@^y1{ZFI*pMDK4_;-Z zBSbzrA(2g;829K#E7Yxd87~1h)i!^GI=mPLOViTq=xD`C@r{Ok<70?LN2(I{34U@M zhdR9VX+(&}H&zYCFGzJLS_mzA>nluML`X2~!Ohl3+^_|qW`YbP%t4;2GQMIeG}zm_ zM$UJ~zYGT;mq&-I-JsW>9{=|Wyi~lt6Ugn?*f;V;aK_F~_^!JAxXAWIn!ZON8C$;Tf?rjcYY^Ws@xY)R~m9J`X zt!JsiXnvc+D;+ZIAq7#?LBE;eayV%pp>Kv{#AqH-prhUQ&|?NjV(_ZpsXzk2Vr*sQ z;Bby(mmAHJ_mMC>#vQQ?Hu@OX@#PjwyBpJr>egb8epg51c%g+1jj|RW9z%%^%MFgpnPA=8S{4F8SEla#auKVC1 zA6LeP`}$G(TAU0z6M7#4l^_N6pAj>K&>?0$%1|c>lOFh^V)-RFG(`x_U%vmRoEDvw z6q!lOG9&}!5WS1zR7xxWgppcD_>*FL;21Pa&RI?@{y+Qp|8D2y`TuScp(17mSQ>ts zva?6r7V3OI{d-1PC^=qs-!p#&LJO@8QTz4v4XRc5rd?`CH|YEr9xfP;=i@q5eW0y@ zo4q`GFJiGls?B`%UF}u{U)miI`l$D0jTj_5*Q|+AU$Xr`AZ}ddU5a7;*l}THFp`YP zWpu4S`d^)}f<0Djy#P}^TMlrF>E{9?`XpJ&u#X2qfbsxOKg^sBOWZ#w;dQ^}6>zs)}0`%Je` zbO+)6P6~Fk-bC?d|CZ5({m@_Uz|Z;yaRuKQBgg(m4$%@XR7khB6t246S247(kD2ip zHlg4=5H@zgx7$^H3!c^a4ka zY|6ZL*^fvGzQoQTP-v|?Iyh-5qqr~qI5rEJ&gAEBbTpKNSa(z?r?;Xe#9qjgQ{M<%q5A!sU%PDJ0Z3}uxASiNV%ccpfg#;@ak7Rp^44Vvt(2+_k zqxC*zpvX%@h0}yiFBB5ZkR03$yKejlK-?1_>buH8VeB-#SQ1tAkgl>LyUp%`2^ZEDQ z`ydL55&uAlMw(pInh&08B&fIQikEO~df#g9Px)!5a&F{FQgq)$@l@jec@&+QP(B$6 z^-4S!xYzQkI=fCnTzn=AOfOmrSpxq|=k}dMWQ*o*N_o<|va=2u8qnDRLi|pa> ztGydra%eRsSuULs#Z;jw%aCP_M-EAy7XhAzhZCn~_u9uTu78Kqxkjmlh zWKpKgX*BB!;DPiu2+zVt9lny_OxT1JWZjZkZzol=n7<&&BvQoBR)-QhAD9p6)iS1ML18 ziFutScj=*?p3rfsB%DZRx@5?u7eMis!P;-KflFMgZm@+(Tg5eAuEuW%c#-ueNm?fT ze#+2;IDgFzGzy5Eh>qSv;xAPoz0?Q*`+Jx%kMrZv6UlLq@+8BaJ`dixuS+`bxS)Jr2t>3k~VvRSC z$hQG6FSY;O=|aav4K5ezVCItaGfayB3=gP=13`g`i_l=ppT_s@X)EV&?y>7IMijuw zF)g*oO8o~PT#2>h2=~4D&m>}fXH0jvbp-X)SW<}CSG1F(dQ~KYt**=)IS;vEb96#b zC#umPLihp$y7P^lP}n)~3Pl_v@yg4RNE~v~VU(`AUH#E5!cMVX?cEJr)iYq{7JUNQ zBayRcQURE44%8?N_G%^mmoq*>`?bX!o)#_kKyZj;TC2!OUExtbNqG^JK9Mr{fyq3W zNgzAr{}A_HVNI>k7HEoqNZS@bdaxl~LFpxcfQkar1EDAa(t8gOM8qvpl%~=}I)q+A z2|=ZW-g^-URa&SC?Jl?boV(A%eZH^BmzA~VU)KER7;_A7f1!C)S)yL#@#xyCla(P% zs94)!U*>ebrwWk1RD@1sb^1#K(f~IFl)#2hqUEOKiNMIR~F0|j~9LAWpZ-PjPk-Hh&|9H+w(lRv4)&& zv$S%lm%T{Prg#WY+~j}Q?#>z8D4J#j2JQ=_4=m!rO#J=A*u~6@hsy>ky#jHwiUF}@ z^=1or9ku1WFj?m2Fq#M~U+@;dMkmT%O#~ksXZ<-*;>~nt4tKvEveO>{O>b85YYLh? zhFPIkgw>!zbC%f`K4v?wKWbpQ)=u{0E#mWh@*upCjfJURYc zoiwIX`bzX#_<`hf2l=OO*$0G7jrQ(a(L(@&R)WBm8&-$ett(7^- zM-;e1YI{4f5Q%-#QKtJj(N6Ka7OGe@fMsbfP^eyqXD*ZxjdjR7GLz`rmY!A#yP;#7 zKw8jAZt^VL`%qLWSmgFLUzoU04EKwB{7jhD@H$3CA`X-O{`SJt4IW>)oV_>y7Iw7p zoDN+306L=r#~}*>Xg+6poVfzyA>igSXbJ7gJ@$>>3zS#OLiTh#iA}#`PqNq!k~Bw* zMkc=7$x_WTYrhy|kTUtGt_B|_Y&Q${!0}KIO+9`-+gR}y$!W&6h?`1GXFcAk%Qt0u zz0igoj6dssOnn*31_Hn2dc1UBEqVyoe!+0G@fvLZR@NOjb$iCDBS@~?wjYd#tB10a zA7*52uMDoz&-Z~7Ek;8kEjVMLcY3aYxS}D=WL+(-?s>Nynvt!hhbwe1j6^hWO`iC> zu*dA&c~r@$CP$%4Xe(GKf4etB7tvA!&Im~;%?&?!x}72F0dbQ-iwz6i{L>^yFYO8gsY;Iv9mcKJ0e>N`<=`4*%zzLYW`sd^wc%7=F zXu(d=pFx&x-u9*Qht-GTa=rACd>YbHJP$9PT9k=t+rml*RoKPH z+r$8|;Txx|4qO|G-VuYqt2b5UZ`*WgZspq0A{6EL6k}Cl8ZafLA=a%frlYomu5ESJ{NMv@MS5UYnDd0~kTQj#!vIV~T#Qe@ib&u=*TV#Scy)%XZQ^JZvc zhhdA*oHgNjKEbRxMIp0p#mVxirIdt33PuzoLrT-)*QIE_F25ZcznbSnNe;|QAq@<# zT)7g+K)8REct^xGe`EFH?Au|2y+T4~mS;ZCN+I#@)IYhY0aZu(!gra3J)N#(Dw1(& zK%1C?Ujf^F+bTMK^I`j}gFk zZTe==RX}|cGELYyF3+|whU(!QuNJXPZ<2>y=jqT6w4e?p!1lgJLG zeW8~x9}T$<^yIO%W-={(WoT`*h@e}d@_p;90#|`E>cpnrJzg0UD?={P{!y8M7|=n2OSMKCYE!uAWz zW=8MYxVKI{>b>56wj1c7v0zKCE}y%Z$KX04vlAq~X%pa81u^Q==CGq7l47hzOu_7j zIe`(_WeE@BlQ8Y(^s)r?H~aZ-AT$I>d6I$&XESy!6J(tO$`nT6G3)qMpf zuQ08Uo!A{gJ~u>|lOK!glt?I?rF_9unBR;#5#>%xXb}5kA~#}-s`pg1<6n1=F2nZWHl^<*k6M{D??SJ}n37}njj@46MGA8osTY$19;$QR zNZq=DAS5dA%py%0BPx>NjDAKn$sB>C`P?LVy40}SO3_Vq@gpwgo2SOE0VVCbQte&ZkIlY!vuEQ znVN@1;TA+00SD5tg#OrUP%NHHLn1oXxgr|M;3SXceDxOU;^1e8@{BogZa9wbhit<_ z_sT1`z;LaUoQ?c5aVvD|1j%PIL)v3P^TXo znf!~<+FMkDVbc+A)URwB}mP+YYb>d-D{IIx9>>cF&+-=N_WC*71W`C zoWkG-A>m;yt%R$};ClPGP89xnvsR*(t#9uG+{!cYwDl>QLDqT8tJ!8~&TD1S{d(qB zN=0-~E(fC_C`pHr!<%V7D{M&jnq?ICSocARYcwX%xL=pa&u4l;2Rl$v<6JoTW$VE| zl|01+$k5+18+*oOJka@y*mecrK z_EY&~>zOWvxzrCf4@=+i!KTlpZVg@^{=Jg(c?i!NSI-O)N}Q*)&5VLs&U#Eqfv9eP z`oF&d%$GIjj`m>iErbuW~et?ikUSoH|=}BU{-4@L?$PE8F6)F(H8y>1HogB_! zJlIW#2fYN6FpFP6V;$SA_35DKMhNmH3V!B?(}YWk_ZTX3N?WCZ6Z*hKC!jT$rN_Vt zeWr&zRAy93lUjm@@~6#i+jVAEPyp{azBvCIQ0>AZADgbE&gBp!ahwrm$miGB(wvn! z*YS3b8cq0$TM;(ngJoxThIoO#>PJEPu1cp08j373ygi^?GCb$4TtjOQmPXIBL+A&2 zJHv7x_jyx)Rd87EX~vJ=(D+p6AU6>1AMdftA)-Wh7SkH4UW<)CG3zUB?B}US-l;&0 zx^NQ6fb3AUQCfpFjD{c)HQS@c)6;EK1}<`ap_0WZp)fbMJpL-75$ABJ4;d=}^nS>- zJYi+A^*iK>c9#@09ZOOOIuSaJWwKy3936&|AQRp0i8t-RZsuxtKkfFbr8Mc3FG+HdFl(?mq#_;E zG5fhR_UIe=t!O~9R?)mV;V#kMujFlZx5TPAuEx?yG8)jCM*yZYeyAJ=t^|TFIdDi;-crc3P zH)UAt13jg+nG*SibE_I;!B~*HL<*S#-f&X z4DFR~YVcxJ{FZ}m+T)#1V_F04Hg~MosADDWBTeK&@RL+&P=5=gk|}BzG)Fn@>9K&= zpA0o!(4-mGW4#?D7)Fxw+mWg&QpkEl`QUb`-Ou-O46|{K$54=iz&ll6kS%3UH}ss* zYB$kGb61z=ufiy>8)Y1pqfvWOkvt4_b8T-ftzQ4gLFL+1rlhCXa=kB#j=m}tL=w_H zV*Lj~FtFHwklmmn*O$CBePe_cptKz{eUiQqQe*nDZKDPg3PLL1bhHKev$e`se{w2< zkmkj4XMXha3nWV0pfcQy?|TCU1_^kqNjr-!=xn^vq!F$WtZh+9Wn55_*7vf@u3c+f zB^oJQc@;#9r`0q;8#kQ8akVN{Z+~o`yr2jSQG;Iv`Wjt@7_{)*{A@K8w)VTm)uY45 z;-pXydoB(aF^zw;Mw{c{B1850WwIYfL(TFfnBnwt?CVbTQFO7~Slay{+2EwtyTSN4 zIL^&d7hPslEoyGY(~9^^7hRjt2XS*u7j=sOx1f7Hflfd?^Sv_VTKi|)+LVX347&rG z7M>D_DER|>cVYmGxXwIqxJN}jh5!87MM%;IQPH3QoHh33#mxq!#U;^Kv}#sCGmnz97c1`{@@%iYSr zl(i~S!K+$pG;(r@6F$|)A4vBbnYHMK`hHnMY5G!cc+5Vme9O0LUE2NpFDH!9_bHHJh0$IgX=Ywd>grp zpjK8FJ!G8UJPa^Ym@opZdQck;L+aLwqgmTMM~hvKd%0CxJ~=F7WM1xVZOw)iPL(e` z=Up6vj1a8X5o06FtlVqa0LlR@y0_7qzB znc|epJ-qQ+9A{>V7~oi0x~wZ0y*@)0t3uq7bj;n8@pG^$Y5m9uG*Wu<_ARX(dk~pD z;({|!Z^w(~;9N}8GtjY}Hn4d?-E$+_4O~daK-Dx8Kx;tnea9_z8e$D_fOvh2gAG3Qb|YOIH$&7gtCn;T)wY)OezD4@ zA+iLiw4ks4n`U;5XJy{s=_)9;eAo*ly{UI&*8-cxXOyWzrDTl0Z;WM(UTH{1C$UT@ z{P?Yk;dC+a{2IMWlcDGaRwbhdEW0-G*odyx(QC)@7&LFE@)`W-7&O!OLA92vwMkb* zVQT&3O+GxvoLf&KTT}6q*4jdNK4Dp8Oi$j?fcWI;nFb}G* zElkW=u{SSVm53a}IoP?KpKJJYFyyC#wC)?ZZ(NEtoH1R#It6jI(0iK1T=dc}V8*GI z)c_4P&L>{-fa-F9La1ko9gqEG`G$=1jxwRVZ810>Gk;|paQBN!&v z0eZ5;Ga+;2dY$P6Tg#adSsO2{1zGBes{=gq4ouM;Qcwhq!rls<+VT&vN9r+jM!MZ! zGQwDZZWHZE?438=gKgAQsJLK-VE3n)8 zHDNkw7g4qMFoOINXMDK&RT@RP|Gx{KrjMy(($uZVlzjF;Ta(lflxg9|7LF zNN@zr3nGSk(-FNBpu~|-ey*TD$qR1E*^sZ{2n~2>ej!REk;-lDOVnz3)Ah`xuU|A* z($)zx2kOTvvVs}1CV>F|x3TKaW4fWr@LM>E4ZFf=NvVqX*N8)sFKnG_dq)hUc( zkpVx)c<3X>`D(Ii$*Dr+P+BoYNdVpH=sDAaD6p|6y!SzSICQ-CRTr0nnr!|G*0u21 z`-Oe(n@mWf@yM%SGx9r#)Msf8p=EJu;m8wgrM4BSWDZ=h#;Z|H1fTZ}k#IB!<}AL? zfhVNC?qfA4<7r_u((vYK0^Na9c-^2ODqb5V;s~NyilyD;u#JIo^h`V z(pnKr8S5!NVRa;^lzQxbvScFWcX)Uv8Q9NA4siu50eaFhrT@`Q{*5JX zc6bAEr6`x*F-m@kW7lAQ%U1rCq+P_W7a&*Ovr6jCjwpxWe5+--q9A zU^cSBNb_Q{c8cAW9+Qjk0Ik|F{F*!uK#7z*pT?X6apR!ZzL6sHW>Hmr7i23`V@6@a zYw)x;264R3Q}^V0&$Q_oSts^_NxRTdgN*f!r9tmPhgVgEPS;<7ECN~=!s$NTaX7nM zNV&x~BjS0Pz>b~M5ndi^w^_+^AT|kSfuxg>`N;L0>O(MLeEgFH-t4p>V2rxk2!B*#_h z&vE8GWaw3m#Ex+xh-Ah*{&My1P#4%a9}mW(=}}wI+(GB0LXOcaro=Vpo--u+hnrMp_?ROym!SA9sA<7slYo3BXHhJc z@x@=ZG2kVz^s0b;zFc-zB+<)nXX)wdM|ip%Kia!I$GxUtTldG{ETQ_{uNRKNcLZcR z9k_ScMEDDG@x81!`30p|jIt_J2X(numG(okrJh=sEFfr?K1 z?s3U-o#t{%JRbW-jn{&kuAk9QtGtcuIDUfIrIQ(Ly_sDz=#|eAungeX@mZ_Z*2dX& zIrje+4ymYC^yPB5+QU^NLOH|weaRxoQmul>OW zTM7EKkIqen9JnO}W6TIoW^(0RXd;&o?F?r%>PRjCy*}@U@aBr2ExH6UrOPG-_T6Ij zdKMO@+MWyB(WdccLA#17k&W&I^DQMva?wpBkaB`@Y1)G*FDJjUF*Idl>prTZc^y|f zk^BPj4w0XkzK$u{qAc5Zkc7~kOrSv~5SAfxi(beal|~1%2HZ^0DoR*wl}JkkN7Q$#(AU4w_?h7+c)#H;w)z1%bRBC&<&trPK5M`5 z!_w^Md6^Se=vxu}UNNfe%1rn2GO=*!n|sEhmo`DFRITBj_3&N4EtJ75gbuu;XVLEL zvBd-9-=Y!wQBF;y5LuW|qsS#ziR;{YMB^XVU+Z6pE*q;1%e&~Z&+xgRxc*F!K|!w2 z0j||XM7?Oaa#id5x<~9i>H16vM>LI1{R(3Bi?HnvH+t?#rIJtOY`&x)k}ueMbZ41ZgA3W zDsggIs^F)miluI^X>Eer5X2E#z$n2D2;qfx=G-^yU67>gWokrcW$7>4RpZ$aVf|zFr4TDU>WUQDO z)pdi7h+x!BmBFU)NE^92P44L+J)x6{>r>bMvQOqPL)R>6-(6B|`Jih{^ZA@m)!o7) zHKx<$Y#}`InNf2vc4uLs`bvewg~Dql$JzMjRRP&?-zW`(3I>=JvqXcs3+hKsgi0AR zN!OvGU@d#avNl^9H{5J{=g{_uJ+bDll|v?L!=HNHA@f<-^s!_4msg7Ht%jFwoQ!y$ z(+l!D!KF>Cod%uO$MCE>h&q&18}Ly2*^I^&rdzkA(oE3(H2{$f8Ji!EZ9;IOQ?=6{v zo%o5Pw9_x!Pba7y751y9bi@Dr$twtW-oJq9O!P(x_4vt1#KpsJ zRMA0259<0c@Gbr#CV%#swd|MW=4AV0v*WQr8B}al)>?ShG5MYIW7;cme^OeOe^Ocv z>fd(}KKuH=T;pKi206}_k1H_3rX7VZ5dROK()}Dj=hkfCisFLf=02#u{wHq#a-JRX zfnSabYz*;n!*RQx)!zR1%cJ|hWBZj7FwX^_3VU(>`u|IBRSq^SfP=^)PDz@oKsUwL zhjo970)NSDvK&mqIC#4P10# zXMAe}JTEKa`~32M$%>T%z%L6)P64w3al6R&>;L&ON)LuUQqP-Kp90SZykU9rzw~L~ z@*_<^1U6=ym-Wg)B+a}Z{{MZ*U#9??cn45C1jHU&#IzLxkE(r7PXb;(VjdTYW%|m1hijg8d@7?o z3H$u%)2AdHL*qBd=Cpq!wY7)Go#AkxR37MP4Dw zD=#4@dDO;vPHM{6uDU>d=fuUtl6EVXUDbcs7froi!c4j9|2u8fey^0TJtBtyfj;4G z>y2>nf0;(^J4?O4o;5-O7rT-dzK1cj{~;MY_x=Es74HCmjtOLbLb|!R`8S*EZo~1O z3AGEk^n-gidC$=`=I-I`Ucl<&W4YXi4FM1dkYHR$4LWIqo2^SYM5S;Hd%=`^VhZG#o%YW zLHp|gl^?=FQR6i#*EoN#Z+yxVV7KVLqtE{WL?%$r9Zm%LQTMn$yHBez`nf~haC2rB zP-U(B?AQH(lXxlSxScNv)$T-fln>_TF=wKZ3AiWaVsXt}l#5Kr`nLM*+cVPkNm9|i z|1K>CH%8jhF|fFC8D(ji!2qAr{JHG}@Lde3U5$qJH;Q)SEB%5rh~^!{Czw2?E~#Ui zt1dskksTf{;Jz8RtN#|;!=R}}^%=_}HkRj~U*=2Vl#}`#L^08} zar}bAxUc*@eb`%8Sw+g-U)h^#2$E6}O+_(%cROBgR>mRZ-BoK3q9i1gGzYip@Yz~C z?x%gCp~i}Q>j$Q3zP`(b7+cdtcgI=^hPHmUUW|nx^Kyb`FCoh9QVu9be=b;vsmX>UF!DsIS zlCK&HBGGp=rw=xNTKf5HDS7oudAyJ_2_rj0wJi8SPh1-(0Jd+LdBsk36lk=!H-t<< zxl*(etK(1a=JT~eQj`N)qnXDv#^9}JD7-JODxs#%ce_$Bf!UUxX`>q!H2dT4=I`mA z86XS}1;!ChMdDWVMRY}aNI{w~tQ*nIZBFU~q2VL^=&?Isv4S**N#1t7iA5z*oHMiu z6Z4O0>}zItA0);nh-SxVwAL0(FD)679w;VMq@))4Mb4K3t=>_(S_Abw^0s<+iSe@@ zpLI6+rdF;vCer(Dw{1|jO6D(?7I2&t|GhbZe*8AZoM4?rEHkHU2O|R;=qMi^r`rz} z?XewCE#z~Ck?-#E8z%6xZH{lg&^W%hxq30THWMe2)Svy{ufJXDr}G9mxb*Um0nN@o zA^#N%ydq^YcUXuQ;bx&i3fLxA%8SY!5*KwHC}aIrxEUSW7>GPxypNfEm^Rpi-Arym`Q&EclL&(nUdAdw}i?P*W_;E zXnTv<0-*)aM+K(tFD0r1)dfp{tMQa~L%&40+RU<|_MU^%2Y<1@&lL;R?WVV$<4I$B zSP#AxJagQ(51V%Ydlt4HGVTm*p35 zU(m0s>XFy*Y;Ab{-;AfsgEBT2;DoziN!OUKM2$Ccthj2Ad;GGLUpCFU)9f_8>(hXl z2Ahv4@+MQrOYvel1%yHe!V#08`%0+%NtOjTyRnGTA`iP#UHS;@uW(zm8i78<4kG>OBLni%S57~_6C|(4Q@m`439QI=Yg78T)ON| zdz+=YQ7V~8-d)o$fqQMH0p9Z`E^R5_zIrlHUJs=@^ZbaSXQR><|y(8H3%X#LpRsi1hqtN73 zzqf7rF?q{9+%-()aD3jDj%CX(*n6LPKHGt`Td=ir_w__$bc&cB>qoPd%ftU>-#Zwz z^nNyobZ)ju#^;vka~3|j_lEV!)3x_%1=T>lwo%WP-6Qw5=%rv;lb&C`(c6pM`Y8sH zX!PQPRkiu3uYz6 zX165)(=sP&xAnh-0534tx zT?stgE2NLANH(Rlu2!p#9E@+OycoTDRnj^BpsA%6eRjz@`OL#zy}#fHNi-$VgQy#P z1PHHo1w>uHRQ-}GEpYC&`w#O>of5ftykTO~uqSD(H7u#2`0;BBNQ-FE7$4|g9~Y_- zQn$+n2mUIV-a}t9HKf6$%IVk;lbdVF29Pw(ai~wbde%UN|sHzeIfUtyZ^Na!A4g{^1gkt3Xm2cM*IOtAFDw9 z1?-cYzoT-jIsFBT%i;pWu3|BW`^Jxm3N};jEen7mx-`bGR{Sf|$XS5Ke62|k-X&?8 z+RN7w#RBpjGaCD=RaZu6pN=j?8ff#%4451HC*P*%&t!w$SS0BTsN8~BeG1iweQ&N< zn!P&bQjwNpz7=?{PA6N+DzqZ1BG&V>#@kA&I#Bdrk+NvCG|;+2eP`JH_R^Vobnjt* zzhDDxj6Gbw^HmcE=jbnA#Vz*}uD_O@&1SZNz_#6T-CiMg3 z_int4h{&cSw+@fY5A2!I{Z0q+4N*O{Oh9Na#nu~tt4QtC=&jumJ^uch)SJ&Zms*R*;}4zZLGFr4OsAIYOBcy^|ZgKXWa4W9akr@kF=VBuHD zm>rKB+#HSaYs!J9rqN6!D+CDa3lBY*$vD;f*n0|J0wm8$bE+cVpmyy=7^xmMOuvA* zwMZ%eN19>4NiIn-@DBK}@wt-M$w6V=`Dm7zdcTT;c<)k|VOKRR4#u8g+E!CTRKLl| zoY;n;)=WW{#1(=Ox^A1gpynJFSGn&8$Fa!=+lxNE8(lWD9a^+5u~1a{UVyJ)320@O zF@yyjY(AlO)b2E_t7a6oYL{TW==j|*iLUS0FXT#0Q6IJI?aqh{HVPPvGnOnQh%#-k zsWZ1K1%iA<3pxJmg*^=rMd9c&5$1+rw|hxVkF0{FZ&q#k1Xn@Cj>D^CZbMtc$C!WN z+01Pn&*~XHmq(tx@rptv1*7^^yysOKT|_l6G>e4clc#riFr4s5iV!iO*n&L3j5uX+`4CnsmkAga@d1HiPwT&SBAc z^2fpqp>d(@J9CzuVM!trH5YlWtH;eEz%V0G?>nSHZ^8RG2f4Xi1oNz8U^d2rPU<3OkFSYm!eEkj>MSYXb^ zSwQx-ZOGHx1ZlIqEE2_#YdP#L2GYlT?8w>)-@&}Nl|GbZJ!>L*Qd$KKXN@UzIHA&(Gth%<<6rEB?DSJNJ| zS%3#DG!JXDSYi9oa~loj1Ty*x{ut0||K<11*_5sNK3Xr@BsfU}Y@x5fyZWvX~1)!lJby!qU+y>1#%-qQ$guJ|XFbcpyp z*-VV^)Eb|uvLXId?#xvmDHF;IHdNb%@4ftWXknr?r3-e37*-)1NGB0`uV>c#7IdJc zrKOarXL|Q?os+2noRFy@7V<79DJ zjIGUw6@PHEm5%4WT>gG=8ZTwKdP8|^#ZD;r=ReU~wx)-=tuYA2wY$E-_rGp|W^*4s z=QU(H{?2Iutz?PTs4|y#)XQ^1)QOy!Fw9Tr%gH^kXCd`znGsJczpL9grWfTj$W%eG z7u~B1^x7p;-FJIMhzH-?7U~ZG*On-9q}5d0T}rwbx$c`E$d{FYE#aS)Xm;9XmVCA&W z707W-XV5&wBTr`vjeO)y&6#)>UoC$?@4yTbWvUmrsFC9q>ClgZeJ#4-Vj}9lt&)dm_8t#baXuAAqDR0NwT=Wi>3(KPJ}|nW{lkO zug_zwKTMcf4+r~`-vK@-R`9F`RX_bdxt5nAwYN|3;{VR0ED2eDp-pLngEdc2W@rU$;j})+QYyt=F zv3pgt6YPMJ2lX{H+s&$v2)rKm55zm6O|uzWNo7C}fZ${t`IDm)4nd+z_6DaY=!D9_ zu7V{vRT|i>n7&;8Om#eyFF2*mp??0QPP*!6<=_+24401p3#mc;AS9ncCCr?M7Xw*- z8ely(?YkeF{7p?^9yDx3`~rG77+isr4vs&0a#(ZZ2ud36R9+X~^a4Z@V|Dw1lf3A6 zp^rA1%s<$;_h73&uLD{ZbIVHE`I@O$1>~1+bhbocBV)^&4I$*Y*po+=swh2r*3Od|_1H4$&_lvUnRPDhhV&3Tk({3kC^j97OBJ?k4h7_IoCA-;TGaOVR!b zHpBN)Al&gv@b!2_ItfXp;*KV;5VZMlpJzVo>iBrLekqEr>p8V{yc+20lA+aA!!&x% zQW?_iMMiw4D$g9B2#;%Ug2K%=Cgy~82>n-($bADIs}w-WEg&HIgU$rKQ4ZJ!TtX_I zItX$RUF*|gDP_8?fjMy~gFGX1LfcHLl4=!V2s7c41g>;rbH8Bw8Rt5^o{A?_jw?+h zQEna&+yuVQ6pT4PtG8O)8R?_^I8}o-Z9~7i27Hm{qy7Hg-Ysjvqkdz5dqb;{hw>G= z&U3{(hVZTg6M4?NZ7m#k`a=)nC_S3Vgn1<8BW~UoB=P_mBk+Rt<6e_O1~!$AX{<%< z5s&k*vj4+|`p5Q)?-Nj_&bs_3PIn*9M_&3vmfnov*IqbEolwSnSWBN=c@BmWSvKqt zR1cUtgq>J!Y^=T3X6ca%Lvr{5>bqm0^N&D?Tj|F}=}Jqvy4e>!c)Hd)xbVKj-TaZ@ z_ZM#_Ie^^+q=qWvY5vMP{!ziKE%;~{2ac3O8iC5;ekD@=X(Rbb`XV?H+wa;qh9{>x z&jv-ACQ3fMyhAQA%BKsO(@}`mb&?_;y$CR*kRZFj)_q^*653jtm_h#xF=VT!74TC* zm*majMP7KK(3aK!Vo!)CH7O9j**RUjDx7)>C`yl-zU~$WNLVCkf28ktqi30)0cenW zWu8yo)-dYJS6eD0G{&@|*I*^r%*rf%vN?UvFcI&**tH;5Rtj~Cc0~3Y@bpe2ix|h6 zZ36eXg>5mI>#=1&G$sj>ZFvpdyQ;_cZw6HFH1ug1`}U}reibdUd$(zpYuUzs@~;HS zhyqnd)xu2R!lb+{ueoq$6K9W4unb)tRr?jIpZTJ6#rqUydr#c)iSVfxepxcPp1TOb zcndhsKBIo%En##IA=>zKHr#|GT2>mkQMIYmX%!eAyB^t|0F zE!C|cQWu;oV!?y2A`CrGNTGD5Q=}t|T9uyqTc~ET(v`c7MY9Ztk%ZKC!)=zWR2SV` z7rPopm8Y~CCX!O%{mrkaQd4$EqnyUR)DKOc;@+oBw-}vrO}}mvdo0Ppb`dit4p64h zrj)yqHyoGr(|xu*1+ELlQ)B|`hNrZKid0eTe{h##({o28K!?6GCnV~br#(5|pXW!( zW$?D&>an_r1!HQv|?#8jwGe##=#$vAvBIpogx>!e5KH=*d zw9||yAR6QC!ksxBVS}isbeRQ}n`AcHUJa(sj#E6`w zfe~gV>;_P1CGs^f>4lH;7`l#$x;9Hsw%b{~cc&M2p0gRUq?fmJEsg3Aj)}M}2HU@9 zh*D@1SWh?3ZYX}nx_0m8agCaz^LNVBLJ&*6j%4dof6@qw|7z$zha;eQr~rCQB5FP5 zEs8L0Od3Cj&KD5^y@Jn#P*r}Tg)bXcf3{Ingti*y86b5utzb4Kg-+_ssAVhNCRM1M zj9U*ha%{`++%DY*qZhkYi_ZQdF{!TpHm_RqfSh;i zNHW7;%Z-{$Yvg6#j+*z+glXi>P{rZq?(J1xR(6UT=J4XAZ?`{ezwyNC-dAh^NF1{sab}^w$=|du-~<{7MC~Dlh@tD1yz1y zQD>?4J_EH?`*Ne&iX`UBn$iPAV^Rg@$8w&S>Pc-N;lnl(RD5>p7G|G4k*(^yAW6q0 z>&*}_R3+m{V%S&Id|zG z7d_z`n#Ot4nKe2gtc`d)9=48ER7zfnKb%Aj;%^H#JDESH$LoAX6&lE3SeGgdGD?NcPavF zUr{qSmAZBODci^V%a^C~w%=!(r}JzMi!zcF?o-d;egU^W>Hq)r$SF_~#U(S%6bPJl$9;kS2F^4Mp8_FK z;MZZ+RErX`^5C48PhF6>GuGQJOc1A;PKIW>ckTU$7Cf&E!>j97u^sm&F#tGhN>Ho$ zFSdJhnab;WG<0e&EgD~&LS+_EwThU*crw5+ffE*N*PtVs%N5xT6mMVsgQCD?=4R7& z0kdt}u+zb1hn8so7f-kQ`hQfXqI4~W!O}iXL4%N&TYh=8Qq&zY0~$Ght!EEC3d)J|AnG{l>`OW;R@J9c;egr zH{S&qf2_7oAHRvGtNI&=q$ID|J%&F>?>}`l3syi(2>?vXUKw7dP6M&u@;A?!ezP2a z76vV@n0?Dswcur)KAf#($thBZ@39%=%A&m0h|=fk0pfauuD(+rcrSVbfYiq5k3Jp+ z-AlgO{V$IDX9uLhu$)eHV*8tmkS)R5c|gC3VC*Z5FV7tID5C-j=AWTh-T;(4-k|MKo)+@?#IS|$Lv=Cl^4*W^b};;;2Ps;0-84)WDXrP z{wW9>?nYGS+iM(8*r5HqydUUCU8AYSKq}W%|F-X1JsbMll=q$7@RO^9QFZ@r zF@Mh8epI(^G_Qu;t!fJ6lq*9*R{_-7>Q<4$%sJX<#lWMFL0%uA_z+*k%z{;K7aP)Ci%|_woKyKdRt2`6n*&l^62VT!qYcX zrt4&4RJp^y)BsRH!E_9t1e-r>aAIxQ3R}R#cVp=Fm9^L}f8#?J+b%k$Udw7Xes5s( zPaIyHy>rF@3>hLTOkd6Iz;@Mr{{MXL&82W ziRDkf_c^@E2!QzKT7YgJ(hDuC&cPJ6Pa<o*`%OTMNX9l&Ml71eJrudnh%pi$XtqT3F!?PnV3`}5pE z_IXlcvbInuM-0e7)u}zcv-foGg2#ir{OniH49xYF^08xD#X+Yh*GQ2q1)`*uv2g9H z6iiIe_2K!&WnF(}?i*we9_3Dfg6>w{4>eZpLq5|VO65~K-XlnX8&k&x_MMj9DU*|c z7*+qnp!EstI$&YWI~@hgzi9xF@dmJ52l3DYz~^$3*q(4P@$Ie~&X7Dan$|-SS`r;P zjQ`)+wpn=|Pg}6N?HYnzslLYIb`8}M$@QQhdYkp07&^drS)Iwlx^HL^mnuj5)P zE&D772)Ou@q1L(Iyi}!TEex8$HgpmO!Kd)eL^tKwQ!96NTRQ*mOuM_m-MKS6F@=cy&-{iPRC4l_I`dpNv zCY_WtHt^Wbn@EW30MymxlN0QXrV!sXq}tn~2SqH0)*hst`7jKaoHidzeiJ}R3a@YA z4xOgL2lAN^9;a#ZfzLV9ZLZslPFC1^UmyVnp{gfQwSag%6>md|Cx`VTdI6hUoQW;3 zVDaHh2$N2(z}ultJ)aJ~|MPejTrCKe(iG9ZLpjsW^Mwzs33FeEheMl8Por~dUl=0f}NHD{RNw?{_V{B|E! zjT(xOSoXJ5$45>g$|6YOQtwp+<0$Ijub;SR;?hM9`KHjT<1~z%_aR;9M1$hpUe#Z4 z^Mr*d9&M`l*avpF*_?j=995tz@XF9(tXz77wRAR640)CuahYjdBvIXFal7)w%r;S` ztp)Ip6@UJwMXBMpyQfRtekII~DDgkbZiX2m7#V$a`mC1x@z>_}S8tqU3^$lWk@J}A zna;9Zi2_8Cu;P~92#)ixubgdL2=4sbca;^&hX0zeY>A|5o4WWERxtF2l&L*sl(nHA zq;=7am#4M5Cmyg8yFQvZ50vk3JYV&)mSg3u;@$qvqW&NT&2K)2F z|HIXL_%-z{-NQErcqeOK%c-uVRqi1f+vV2Z7LA=qOFP3etO3Y5);Iiu4vh zLFo_z1b+G6=icXi?)wLv&)H{Y?|o)wt(o;_|7U%ptPjfTncc`dj-V5Xu>RV01g7@JIXA2&iGBu|Slu#%LXe-}s;TY>lbeFhy*FTJ9kqsUtH z$#jkZomS22)yM&pq=(j6$eBc3yF|~xB!6ty>T0uGQ8NEu)0Ci&A^%2wGef7`hfa1S z`6l3^bZ+}}%Wf(Emu)>G;Ad?=u5#;-&P(GMiv1lB0s65*3 z+AA6WnpW>_(hq(_ke zax*@7pt}FB@5Nn(`3A>&1()2!T^2hWD7(*QF#o>`Z^|gv6+7&3PSyBTS5ltOqEW`kLCXMkyGUzdk4C6>YU2KBs3| z+$?lg5-cLH+DXsVD_z(+pdlHp4{$YggfUnLqZ5i(aX{9GjkcBmho`AYYAJppwsn)}7hht3w=LE_#;++PDnG;U40;0kFE zD$z89<#Hfc;K&I0>42rVJA3xphiBVuLDig&A3XL$8?PR|nJ8IM{C8|orvs>#f?6%Q zueWNLzl1E%3X@Q}W)D(N=IVYFC_H0DgVbqvUl97Hs(Ol7sv)%xe!JRoNJw*x#?ejj zZ0AKYgP1b&eSFqFzl8XcVZGSg(iW6NP}LO>RF@!%+|U7|_I-DLlZFfR;n~L-%6h0# z+O`7d>HeH`BVv`_WSrApwTH5-p0k!mKP(qspFV@T+RM`8f6mekMsRFc*&}7!D`_(K zikzG&8vd|ux){j6h$Es(yf%IebcdT(_grN?8Rcc{Zh+ksRFrsm+p{9k!c)PYiwFrk?w_4n}g`D_Ngpd?#Wzm=`mZ?k6efjLas}sgcqOhn46n12>Ew{=->SgSzd_ztYt<;(An=3& ztGCM<-$sXA%6Y+;p34v1vu%o}3Y?ycqG|`a3c@4GAEaS!t`0JgBx#3>>`*;cT!YP9 zhvcL*epF+SJ2LkvF^R}KBaUX~Iqm1QyE_bVnc<((C5jnrC zKOdEPRlRmcTl39v4xJACH+$r6wA2-=QU#FxOJ5K$sQ#AbS5U7%2E5lJ$;Wqv8*>!M zHr9MYS;2`JmmgBttEYYy@|=qYAJ?m>6&>dvk^hsl>Huhp9oi705GsRpqH5hv;0N7T zd8(`4S-TTZa{GjyV|7i)hJ)?NwvStdPw8lyR)9`g&Q8Q87ShjfvTxXOV|1(aHZ6EG z@@g-1q1@wg{#tT3bck%;y^Q(ZzkhaH$~J?P$6D2t5S2bW2V12UE|L<}{*uv4n1D%G zYwp|?q=X93)$mhd9aq zv(QJwY+S`^I%#sn?9m7|ZNe`X)27*Os3u+>ibglb_d;7g1N?B{D4o&dYy3V6^|PbA zE3>ezT8{;;@IVd}fSXE45yd1pDgY0W%OcJ8MSnI8`1>7Q(R&>6;=Bf4mTTP}ChGSz_ z`!4_N$?+Or?)=N$Zs6XhVuP-Xn0uqy=lxce%S4j6X7{k|cwru+IJNdvxzRkg)@k5B z!9641SnTHnFp8E|CGu>X!^QA-h6jAvZe5nd$WjWTmDP4tZF{B=cIo=io{G%VXC{QW>p;V{V6;y*Fvk>5X6l37qs>15lINoFAL%j&8pi>x?Wc}Vkd|AW&Do-v{ z+$RLfFc*hMx_883J8SW3qm#_QmM);(d-q1n=^MB7tlqlp5M$NpNCww{TDS?+!;NET zmjs`{fK;}s{0pzlf7`J zPL%KCZ_;GAtPc{PWq9a=j4Y7=aZMtCi25p@%@}TTXch@B0Fi6 z-w2d_-nsV(*%}HNfADImXbSWN&0bOz?(?AoZD!sMB=(i`&=A8d3K!rAir}Ia;w#FO zA4dPqs~~Luiijv^?MaATTOCBy0J7L0Tw=M}HA0WGQ6D*S6ar^fda!7rf&Rvcva1<6#Kk!ooXsBJLk_ypQwyJ1!_>o~ zQw%s>2Vcxh?`zk zssnQ{sOPe8M?q;?EtEnr^r=SB{GSh&fYyVp#nj|l+FLE;NIZg8N|S3fXg9IcwBTCw z)199Lt_Kk}65(yu03e}rZW+sNxh@d}>sM(~Z$W}KpieIth3uW!9WthB?cqS}{#MAw z5z!C0Vs`mfpD6~+0}}uA-xus(sZ`KoW)!D!q92$H{Z(eI#4IQGMCmnB{wM*QA)5a9+i<5q<_a);R?>o zP!2GG!uFm$&{0_$;m*`ArrPBXcL3hau5}%0;d#x0+^q>c=H5fCN54)Blhs6zSW_8kW|78K2CP?;ORG>KPV-Hr;}pf`hQvOO?68XR`L`5 zWjR;TAOBhQw4#;lo$GxvbzntX9TeIjN9qOTSv+lTMPadKARMJR$=DTi8+VAL*v>RYCX@~-k6 zn#ASr*!?#`UKR@dSa3Y(ZzA4U%&~Z=U-mSvOb}*2sRE;X zs6`hUdecROzpSS%u~*9J@VJd&Pq^A=)xNI`|UT6j3;zz(gWG zsHKQmj>_S6p%IjF6*?v}m-^T$BLGL7{BrILV#U>2wkVId)MxOeK3QbdF%{-cvHbw? z3;V7%{mDwMgFb_;jPQu27&Q9qY11Ct9)NS|xLp5JulRfnvJo(U|D}!ccx$inDVI3( z=6=Gp0o!Sm0q7GXLZW=0=64yTgL=ao!w_NUa6%Ik^1 zGtAgx4zv$dYlFSS<%zK$E*7DglM&&GbdQ|>cl~`Lja7DL>#J%dFKr3SYY;j*0eK33bnFdXx8oJ zP2Gt3X@r+xhYowT5K7b^q*K;$(OsC=gFs~MP8I`LWl#~COpV>uKX)TT63ypQHDvR7 zna-&U&Lunx6&zJD4*r)4mAAiKS@Vxf=tpA7iUBfEy%C0O1q{d56KU-T=i7hRoIj_7 zzXLGo%3W=QkDvhnRL)YtuZW-nRt_bPP%mL5u( zQY!iVDFw2wc4pgg;b{gF~SyHpX^MY!a91d5P*u;oZod z!_JJ{Qz59rpHLbCd$pebvp;brJ+|%U#cfRmYPDisfW#C^GYL|zAvqOof~#z9kNR!N z1;O#>?J%^Wue)ZyXSV~|yMRwrsK3~bsJsQTqd8uTo|0XbIO^1oANk<-B2o)(}{kjvS#o!#oW((KkFGY_Hh^UC)=hc9zcoP!4^&n{K0=gyOS z{@Bt2Z=GdDYZU4}xNptdE@x+&X@pC=_Joh#x3fgmxILd~Z9Iq)AM23eucSJ*-8c3K zZ*(?&kNxrQd_X(pF&L#yezZZ0GoX!J+EY_=&R85BnVy&~g&ib^q@jw1^XouuxU4Uh>035H&Ntryx`Xf+^*tIt~F2yQ#TfL5n21)8l1O@h% z)l+Yj4%h~?&4I`MtMWk3Kfk9jo05^jx}Mv{`a31ymR(ejR-c*1jC$ToEMCdqd)+by zKwgGSLe!_#dvnfgR8PGwM7$3R?CICnSTUAuYnhpy-3!JvEyLW%eiujekmv}DUK}M` zx0$Bjesk#f(TdRlRAXH^@cq%HXinuTj+2Gu-kzjHsL`2v;M(_7?*y+&Q=zuw>hDi7 zBM^z&>K0f*PZhIBe9~_IR6K(t3uJ~&6`l+A$A)R`&@Ia`4%fK)7JhTy#Fi>HD24CY zJ9e6Rem{$(t8E#NWnFiUA)nx~=i8s?98&aCX_n1Izq#Px2)$B%bCH_LI+5l1? zvugNOqmCn*y`x$a}#-rJJn51(0Sd%Hhp#Df*k_v6c@i`1((uJjrG z=3LBjShcRvOcredMr{%Bx=;G=?q4c^=ByGP@Q1qhpN6X54bHe~`t-lCPZ+K!lZ+5j z+$RyNr#xPNSCx(2{ic4OGHZ~7d22f9_>hs4azquG)*ns&K5PvBM5@q`_kN-PNz;#K zaM;%zL?^Dgm7}#nwEUFVF7UG+=w0+uhi7|wsa~`d4Ri&4hqOjXn$fSLV8&iJ>B(JC zwri-+N`_04mgT7@XcT~%D!8J!HPSmGHQ=q-Gt%4tP3;r9naNVWvin}(iPGLG$yoGK z<>`Mg78?wuGdu(%5?)G$^Co$Z)}wCi!JrP|r{CA8C_A7lz=sa+f!>Y|@ll>k$L6*S zI8B5JVdky4K>ufn;NRQ&<$5)I?qMvNp9Y$`syeSO%e-!mY4_%S2R)6Hw*FQgeieGv z@#@@{A5EG3CG<(1!O+yE;SrlfPJ5g|1v{pGM1BK>+=l(avlCWs<7i0k}| z2bNAONE7CZl9AAZyaN5JP8?$T&vLSfB5=PJF#~n<;7-0+JFVoE9evDw&u2fJ=|r9dwn>rCDS4Zi~=jSJoJ3rGjJDdaz;ZI z>iN0l)K|sk26oa;Y4$7BcjsrA%m0^`P#zBsztr?~gNJCYyT6hA5906-iVJ)7&o{k7 zu2z3mL#~qczViQHQ1c(qEGq_g)A4^&w=ynLLt5h-T($rEJN|{JeSWBnGwhRD+hjy- z1G(#r`@diLFMAy_{Wss1IaWixO6#Izdpp2@oRFPZO)*8f_yGoYG)pir@6S-vN*;zZ%a3wVgh z0PXtaQF3Qz{4!5x{h4e>&IGG}hR|aBbmAS?v6BB z30<3P5vzt&kNGq1`5tcZb96I!u5(9!CmepBm-Ex-KU?WPTj4$d_pCdv7kYV7S0Nbp z7cjchWfEu#y=gFCly3{|2|oX|Z}ed1_`fWIvo@4q)?;bbeI>AM&q~e%9zyJGbz02? zvVN&y9`nD*`akblxsR8O=zZ{Wwd*_1FUjUqr z;QaF7CtttG2g+kxgBNrEh1|n1fJe}t<11$yGTadbXkRt_*TWzG<;S2*pEHyF9lbGfm{r96M1*#`%|l<7kZg znzVK3uIGbRzdh~_U8Y%{Su~s6ZlPQ-?b=M0S_s9`$eSKstjJ`ty3=%6IBn>qR>kv? zT!qHDGp!8g#H%Ix%wVaQdaO?ZD*}lSt2>Arn>{s`&2f`ICPcm7Wl1Yjq`8Ld!(} z=DI+H(!tjr_({NA!cVppxB2ePH#aGUT{d<4qLus)Zu<8pOL>+X*{iTk-kX;m=x^@J zZ($b)iXqH%a{GmH^)|h~tg{1gD55ys#jt*%gHYN*pwst%^sgIDNCW`$(ev<(bZdV|Z47>}{-YtK3^MCjTF z?wpS=w~Xf*t?BSw4|Nm)$weoZbA0UU&X+xzC@QX}(Mi3Pe_wrrjex;U zcla#=2}Ksc@s4;GRW)sr^KHK{o3yX^k0m?R{t8sAq3~%Dph?5OdgafP%BG|Gd*b%G zrSs((H@Yu>z~fZ~%|p@pFiS+Y02B2bCko`RAx%L5VT+!6B?*wm`=F1scnCjQT-1Sl zL;3`HS6mh_ch&dZ$+@UKzx{@&$53sdcas;F|FRwUr*4Q*7;bzlLcThksrhS8ZO=;9 zo2Hs@c9y63sulYC^v&^7>&vHOmlerOq7-L8yGwyST07WWeBkk-_w6!0*dZ+Qrl?j| z`^-E`+B7WQKZ2v4%8wXZMqwHx-x&F~NLBrH^^lFOGPOR0X!^&g^SGz;v(tp?bW+@n z%f%wz`4)Fasc{a6w(>&?57=bCcQ*z*QITZ}+ww2XOpU>sKjtlN1dD5&wmJ!NyEMQ1 zyV}`!bxn6bnD&#=bT@W6Yp=CaOwmHGWGyUlOa=A3LtjDat;4w?%6Dtw@BZGw1Yugw zo~Roqar~Y_;x$5yr1x6Tq9c3Yt0Mrrzr5IqfAD8Nh0xo{uoA!?vs%TgMY@g`}E2Oi$Fdb_O{s^)UYfI>9guW6V_l$X2a3d zxhh+>#j#ljwXu*-f3Hq{3WjRT_U0MIu5UDF{#Y!2 z{H$qR%Mg3`^GjQ}dMjv%#bV@nALH%kX({ei>tU%1)wb|sDkz9{0720tsoEku4epqI<)6J${z%HA{JLeFKq?a?AnDaJLj=`dt#bP zS-d?V+6a1Ea)2~iaw-^voUxwj3*zU`KH96N2g&wcokrCyc>elEIN#~DrRHC+J^%ya z#){Kn{^}lcG^qtd?e$z7zXZ0Lh?E?hYe`@)11GeQC2=<2dM> zE7Kms(Zr7|3{$xXz^O%fTKn&mhJGm|vQyyogr~L=)ZhNPC_Y89FGHF&(g^`B)^wu7 z+9jo#(T@vdSO|oxJN&I7! z@J+b?FAF%q|s7%}S=S1j({V;~J#$3gqYpDbEcU(TY5#sx1ZMSEC z+xItSn3nsIdoH8ibXJH%2bKVylXr3AEl-hlcb&azn|$l&ZC6q^XV**3i&$qGyc&Hid9an@E|N(# z{=Hx3)0q8op69m3Udkqps+M-k5%K;To)i7=y5$@Bb%!K}7Yq+{348t1y6E4~>m~`X z8rWvc_7Ilm76r73(ui(rWI2A6*P8naPU0LlB?6=zI6I&d!vd0$#f!4OJyzL{;#?t5>XBul#js1H6FyGD ztgyd`MgP@I%!gT?72*2g_h75&BOnA^*t|5?Ekp~dO`uE?kU@U;UpEB#pWktSyj;^( zposbUCnc0fjta0g2cnPzp%1`_XosGfl|-y8<_d+XKfPeLn}e?0vL?I}IpXFMXsdtM zsC9cu#{`VGXGcQ_j+6z{NNk;A?c~@N*z9F8WeB!kBGJvCpJ-?& z#nD&o8K(u@B0Kqt=ZgOPmy<9BAj~M=r&eP+=ghEVEq4{JVtCkOEq4Q@;%EtMl;_LiAn-6w zzaA^*T_#~*;hw>y4Quc+I}#I%I~`FyNoCO=n9ubLOng4!*`L|CP@}2uYy*vmjq0Y_ zUTTL@xn99x#KqGG+hm&`i$6!5!N zseij5xE*@$eE9A4WH6Dj*~MbcYPovgPq{F?IdRpUIxdOVmikJW+1 zR;kHj$S&?0=iPD()Gr_S(lvJMz?xD-$}v9>@j4ZcVx488gp3ZHDpX?CPbIoYqjR1ywkoc+SM;h^NxeKSUXRoBH41$lCr zz-*WV*T8jqp04W!SbQ74`m}F$%9MyuC|&y17*)K)42Vui3SrCUpk2;0-Gx%4F7a4f!Nhr08=UkJJS zh6Sv5Ah0At!GcR9QHE5QMdst-lM@%-vO{c

)`;o~)I6-}KHVMM|0DqM9DTC7XzX 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 I)bh>$0HH%;UjP6A literal 58515 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 b)Sl7Hmup;LzbhV4kdvB{wqlclW#s<=JOCS{ From 3321c52b6c054c18e8a4787eb12cd7e519305b0a Mon Sep 17 00:00:00 2001 From: james Date: Fri, 9 Sep 2022 15:40:10 +0100 Subject: [PATCH 14/27] Add section about using the API to download dbs --- .../codeql-cli/creating-codeql-databases.rst | 18 +++++------- .../getting-started-with-the-codeql-cli.rst | 29 +++---------------- .../analyzing-your-projects.rst | 2 ++ .../reusables/download-github-database.rst | 5 ++++ .../reusables/download-lgtm-database.rst | 6 ---- 5 files changed, 19 insertions(+), 41 deletions(-) create mode 100644 docs/codeql/reusables/download-github-database.rst delete mode 100644 docs/codeql/reusables/download-lgtm-database.rst diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 28d4289694b..d934dd1fbb7 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -379,17 +379,15 @@ The following example shows how you could use indirect build tracing in an Azure # `codeql database analyze` # then `codeql github upload-results` ... -Obtaining databases from LGTM.com ---------------------------------- - -`LGTM.com `__ analyzes thousands of open-source projects using -CodeQL. For each project on LGTM.com, you can download an archived CodeQL -database corresponding to the most recently analyzed revision of the code. These -databases can also be analyzed using the CodeQL CLI or used with the CodeQL -extension for Visual Studio Code. - -.. include:: ../reusables/download-lgtm-database.rst +Obtaining databases from GitHub.com +----------------------------------- +.. include:: ../reusables/download-github-database.rst + +Before running an analysis, unzip the databases and try :doc:`upgrading ` the +unzipped databases to ensure they are compatible with your local copy of the +CodeQL queries and libraries. + .. pull-quote:: Note diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index 0fd8e6b8fa0..976aa302fc6 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -47,22 +47,9 @@ Conditions `__. .. pull-quote:: Important - There are different versions of the CLI available to download, depending - on your use case: - - - If you want to use the most up to date CodeQL tools and features, download the - version tagged ``latest``. - - - If you want to create CodeQL databases to upload to LGTM Enterprise, download - the version that is compatible with the relevant LGTM Enterprise version - number. Compatibility information is included in the description for each - release on the `CodeQL CLI releases page - `__ on GitHub. Using the - correct version of the CLI ensures that your CodeQL databases are - compatible with your version of LGTM Enterprise. For more information, - see `Preparing CodeQL databases to upload to LGTM - `__ - in the LGTM admin help. + There are several different versions of the CLI available to download, depending + on your use case. If you want to use the most up to date CodeQL tools and features, download the + version tagged ``latest``. If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply `download the zip archive @@ -232,15 +219,7 @@ see ":doc:`About CodeQL packs `." - For the most up to date CodeQL queries, check out the ``main`` branch. This branch represents the very latest version of CodeQL's analysis. - - For the queries used in a particular LGTM Enterprise release, check out the - branch tagged with the relevant release number. For example, the branch - tagged ``v1.27.0`` corresponds to LGTM Enterprise 1.27. You must use this - version if you want to upload data to LGTM Enterprise. For further - information, see `Preparing CodeQL databases to upload to LGTM - `__ - in the LGTM admin help. - -1. Extract the zip archive +4. Extract the zip archive ~~~~~~~~~~~~~~~~~~~~~~~~~~ For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier) diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index 2b4e26b405a..6a59754eaa5 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -37,6 +37,8 @@ If you have a CodeQL database saved locally, as an unarchived folder or as a ZIP For more information about running query tests, see ":ref:`Testing custom queries `" in the CodeQL CLI help. +.. include:: ../reusables/download-github-database.rst + Running a query ------------------------ diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst new file mode 100644 index 00000000000..c95482fa6a5 --- /dev/null +++ b/docs/codeql/reusables/download-github-database.rst @@ -0,0 +1,5 @@ +GitHub also stores CodeQL databases for over 200,000 repos on GitHub.com, which you can download using the API. The list of repos is constantly growing and evolving to make sure that it includes the most interesting codebases for security research. + +To download a database from GitHub.com using the `GitHub CLI `__, use the following command:: + + gh api /repos///code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip diff --git a/docs/codeql/reusables/download-lgtm-database.rst b/docs/codeql/reusables/download-lgtm-database.rst deleted file mode 100644 index 11652d6512a..00000000000 --- a/docs/codeql/reusables/download-lgtm-database.rst +++ /dev/null @@ -1,6 +0,0 @@ -To download a database from LGTM.com: - -#. Log in to `LGTM.com `__. -#. Find a project you're interested in and display the Integrations tab (for example, `Apache Kafka `__). -#. Scroll to the **CodeQL databases for local analysis** section at the bottom of the page. -#. Download databases for the languages that you want to explore. \ No newline at end of file From 9b74b8f8b9669e7111d81d9ad278f784eb115de4 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 9 Sep 2022 16:10:35 +0100 Subject: [PATCH 15/27] remove link to deleted file --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index d934dd1fbb7..f9cab8caa90 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -384,9 +384,7 @@ Obtaining databases from GitHub.com .. include:: ../reusables/download-github-database.rst -Before running an analysis, unzip the databases and try :doc:`upgrading ` the -unzipped databases to ensure they are compatible with your local copy of the -CodeQL queries and libraries. +Before running an analysis with the CodeQL CLI, you must unzip the databases. .. pull-quote:: From 60dbfd2b2da419bfa9347a31c6c347815d76dabd Mon Sep 17 00:00:00 2001 From: james Date: Fri, 9 Sep 2022 17:11:54 +0100 Subject: [PATCH 16/27] delete old note that refers to lgtm --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index f9cab8caa90..d2082f56471 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -386,13 +386,6 @@ Obtaining databases from GitHub.com Before running an analysis with the CodeQL CLI, you must unzip the databases. -.. pull-quote:: - - Note - - .. include:: ../reusables/index-files-note.rst - - Further reading --------------- From ff988058323d62b550a1d8ce00fa0292e46f5002 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 9 Sep 2022 17:14:26 +0100 Subject: [PATCH 17/27] delete unused reusable note --- docs/codeql/reusables/index-files-note.rst | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 docs/codeql/reusables/index-files-note.rst diff --git a/docs/codeql/reusables/index-files-note.rst b/docs/codeql/reusables/index-files-note.rst deleted file mode 100644 index aad0637cbe1..00000000000 --- a/docs/codeql/reusables/index-files-note.rst +++ /dev/null @@ -1,8 +0,0 @@ -The CodeQL CLI currently extracts data from additional, external files in a -different way to the legacy QL tools. For example, when you run ``codeql database create`` -the CodeQL CLI extracts data from some relevant XML files for Java and C#, but not -for the other supported languages, such as JavaScript. This means that CodeQL databases -created using the CodeQL CLI may be slightly different from those obtained from LGTM.com or -created using the legacy QL command-line tools. As such, analysis results generated from -databases created using the CodeQL CLI may also differ from those generated from -databases obtained from elsewhere. \ No newline at end of file From efd4853532853b7c3c123baa856c3e48ebcee181 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Mon, 12 Sep 2022 15:53:54 +0100 Subject: [PATCH 18/27] Apply suggestions from code review Co-authored-by: Felicity Chapman --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 4 ++-- docs/codeql/reusables/download-github-database.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index d2082f56471..602cd704c2d 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -379,8 +379,8 @@ The following example shows how you could use indirect build tracing in an Azure # `codeql database analyze` # then `codeql github upload-results` ... -Obtaining databases from GitHub.com ------------------------------------ +Downloading databases from GitHub.com +------------------------------------- .. include:: ../reusables/download-github-database.rst diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst index c95482fa6a5..0b1325fc5fe 100644 --- a/docs/codeql/reusables/download-github-database.rst +++ b/docs/codeql/reusables/download-github-database.rst @@ -1,4 +1,4 @@ -GitHub also stores CodeQL databases for over 200,000 repos on GitHub.com, which you can download using the API. The list of repos is constantly growing and evolving to make sure that it includes the most interesting codebases for security research. +GitHub stores CodeQL databases for over 200,000 repos on GitHub.com, which you can download using the REST API. The list of repos is constantly growing and evolving to make sure that it includes the most interesting codebases for security research. To download a database from GitHub.com using the `GitHub CLI `__, use the following command:: From 72bc7ae20d0e6e6bfebf96780d0531055b43b749 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 13 Sep 2022 13:53:05 +0100 Subject: [PATCH 19/27] address review comments --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 10 +++++++++- .../analyzing-your-projects.rst | 2 +- docs/codeql/reusables/download-github-database.rst | 11 ++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 602cd704c2d..62c0fe8bb5e 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -5,11 +5,17 @@ Creating CodeQL databases Before you analyze your code using CodeQL, you need to create a CodeQL database containing all the data required to run queries on your code. +You can create CodeQL databases yourself using the CodeQL CLI, +or download them from GitHub.com. CodeQL analysis relies on extracting relational data from your code, and using it to build a :ref:`CodeQL database `. CodeQL databases contain all of the important information about a codebase, which can -be analyzed by executing CodeQL queries against it. +be analyzed by executing CodeQL queries against it. GitHub creates and +stores CodeQL databases for a large number of open-source projects. For more information, +see ":ref:`Downloading CodeQL databases from GitHub.com `." + +You can also create CodeQL databases yourself using the CodeQL CLI. Before you generate a CodeQL database, you need to: - Install and set up the CodeQL CLI. For more information, see @@ -379,6 +385,8 @@ The following example shows how you could use indirect build tracing in an Azure # `codeql database analyze` # then `codeql github upload-results` ... +.. _downloading-databases-from-github-com: + Downloading databases from GitHub.com ------------------------------------- diff --git a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst index 6a59754eaa5..89fe41c454e 100644 --- a/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst +++ b/docs/codeql/codeql-for-visual-studio-code/analyzing-your-projects.rst @@ -14,7 +14,7 @@ To analyze a project, you need to add a :ref:`CodeQL database ` #. Open the CodeQL Databases view in the sidebar. -#. Hover over the **Databases** title bar and click the appropriate icon to add your database. You can add a database from a local ZIP archive or folder, from a public URL, or from a project slug on GitHub.com. +#. Hover over the **Databases** title bar and click the appropriate icon to add your database. You can add a database from a local ZIP archive or folder, from a public URL, or from a project's URL on GitHub.com. .. image:: ../images/codeql-for-visual-studio-code/choose-database.png :width: 350 diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst index 0b1325fc5fe..2e4bfd9a58c 100644 --- a/docs/codeql/reusables/download-github-database.rst +++ b/docs/codeql/reusables/download-github-database.rst @@ -1,5 +1,14 @@ GitHub stores CodeQL databases for over 200,000 repos on GitHub.com, which you can download using the REST API. The list of repos is constantly growing and evolving to make sure that it includes the most interesting codebases for security research. -To download a database from GitHub.com using the `GitHub CLI `__, use the following command:: +You can check if a repo has any CodeQL databases available to download using the `/repos///code-scanning/codeql/databases` endpoint. +For example, to check for CodeQL databases using the `GitHub CLI `__ you would run:: + + gh api /repos///code-scanning/codeql/databases/ + +This command will return information about the CodeQL databases that are available for a repository, including the language the database represents, and when the database was last updated. If no CodeQL databases are available, the response will be empty. + +When you have confirmed that a CodeQL database exists for the language you are interested in, you can download it using the following command:: gh api /repos///code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip + +TODO: add link to the REST API docs. \ No newline at end of file From c7ec6fc2c3a06444070a56a7eebc163c8a1b6025 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 13 Sep 2022 14:21:41 +0100 Subject: [PATCH 20/27] mention compatibility with CLI used by GHES --- .../codeql-cli/getting-started-with-the-codeql-cli.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index 976aa302fc6..db8b36ef58f 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -48,8 +48,11 @@ Conditions `__. .. pull-quote:: Important There are several different versions of the CLI available to download, depending - on your use case. If you want to use the most up to date CodeQL tools and features, download the + on your use case: + + * If you want to use the most up to date CodeQL tools and features, download the version tagged ``latest``. + * If you want to generate code scanning data to upload to GitHub Enterprise server, then download the version that is compatible with the CodeQL CLI used in your CI system. For more information, see "`Installing CodeQL CLI in your CI system `__" in the GitHub documentation. If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply `download the zip archive From d18bc13f027ffbada98cb8c0c9cbff99a26fd313 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 13 Sep 2022 14:34:06 +0100 Subject: [PATCH 21/27] fix indentation --- docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index db8b36ef58f..c188c0a9c72 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -50,8 +50,7 @@ Conditions `__. There are several different versions of the CLI available to download, depending on your use case: - * If you want to use the most up to date CodeQL tools and features, download the - version tagged ``latest``. + * If you want to use the most up to date CodeQL tools and features, download the version tagged ``latest``. * If you want to generate code scanning data to upload to GitHub Enterprise server, then download the version that is compatible with the CodeQL CLI used in your CI system. For more information, see "`Installing CodeQL CLI in your CI system `__" in the GitHub documentation. If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply From 8f29c5b8b63d6eca14867cff58a0202e4de2e9fa Mon Sep 17 00:00:00 2001 From: james Date: Tue, 13 Sep 2022 15:01:16 +0100 Subject: [PATCH 22/27] fix broken anchor --- docs/codeql/codeql-cli/creating-codeql-databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-cli/creating-codeql-databases.rst b/docs/codeql/codeql-cli/creating-codeql-databases.rst index 62c0fe8bb5e..5a8e33ffae6 100644 --- a/docs/codeql/codeql-cli/creating-codeql-databases.rst +++ b/docs/codeql/codeql-cli/creating-codeql-databases.rst @@ -385,7 +385,7 @@ The following example shows how you could use indirect build tracing in an Azure # `codeql database analyze` # then `codeql github upload-results` ... -.. _downloading-databases-from-github-com: +.. _downloading-codeql-databases-from-github-com: Downloading databases from GitHub.com ------------------------------------- From 625e18aa05f4b4f7072891bcdb121ef9399a445b Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Tue, 13 Sep 2022 19:22:15 +0100 Subject: [PATCH 23/27] Apply suggestions from code review Co-authored-by: Felicity Chapman --- .../codeql/codeql-cli/getting-started-with-the-codeql-cli.rst | 2 +- docs/codeql/reusables/download-github-database.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index c188c0a9c72..1984b12d6d8 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -51,7 +51,7 @@ Conditions `__. on your use case: * If you want to use the most up to date CodeQL tools and features, download the version tagged ``latest``. - * If you want to generate code scanning data to upload to GitHub Enterprise server, then download the version that is compatible with the CodeQL CLI used in your CI system. For more information, see "`Installing CodeQL CLI in your CI system `__" in the GitHub documentation. + * If you want to generate code scanning data to upload to GitHub Enterprise server, then download the version that is compatible with the CodeQL CLI used in your CI system. For more information, see "`Installing CodeQL CLI in your CI system `__" in the GitHub documentation. If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply `download the zip archive diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst index 2e4bfd9a58c..02d41114da5 100644 --- a/docs/codeql/reusables/download-github-database.rst +++ b/docs/codeql/reusables/download-github-database.rst @@ -1,11 +1,11 @@ GitHub stores CodeQL databases for over 200,000 repos on GitHub.com, which you can download using the REST API. The list of repos is constantly growing and evolving to make sure that it includes the most interesting codebases for security research. -You can check if a repo has any CodeQL databases available to download using the `/repos///code-scanning/codeql/databases` endpoint. +You can check if a repository has any CodeQL databases available for download using the ``/repos///code-scanning/codeql/databases`` endpoint. For example, to check for CodeQL databases using the `GitHub CLI `__ you would run:: gh api /repos///code-scanning/codeql/databases/ -This command will return information about the CodeQL databases that are available for a repository, including the language the database represents, and when the database was last updated. If no CodeQL databases are available, the response will be empty. +This command returns information about any CodeQL databases that are available for a repository, including the language the database represents, and when the database was last updated. If no CodeQL databases are available, the response is empty. When you have confirmed that a CodeQL database exists for the language you are interested in, you can download it using the following command:: From c383701677ecb511ea44ab6026f44edda9e21524 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 14 Sep 2022 08:48:20 +0100 Subject: [PATCH 24/27] add link and remove todo --- docs/codeql/reusables/download-github-database.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/reusables/download-github-database.rst b/docs/codeql/reusables/download-github-database.rst index 02d41114da5..732d4479ba7 100644 --- a/docs/codeql/reusables/download-github-database.rst +++ b/docs/codeql/reusables/download-github-database.rst @@ -11,4 +11,4 @@ When you have confirmed that a CodeQL database exists for the language you are i gh api /repos///code-scanning/codeql/databases/ -H 'Accept: application/zip' > path/to/local/database.zip -TODO: add link to the REST API docs. \ No newline at end of file +For more information, see the documentation for the `Get CodeQL database `__ endpoint in the GitHub REST API documentation. \ No newline at end of file From cdbc839f4042c319552c4aa13e32609ebb1a5adb Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 14 Sep 2022 16:20:07 +0100 Subject: [PATCH 25/27] Update docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst Co-authored-by: Andrew Eisenberg --- docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst index 1984b12d6d8..b3ad59da2b5 100644 --- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst +++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst @@ -47,7 +47,7 @@ Conditions `__. .. pull-quote:: Important - There are several different versions of the CLI available to download, depending + There are several versions of the CLI available to download, depending on your use case: * If you want to use the most up to date CodeQL tools and features, download the version tagged ``latest``. From 67ce4426749040b08c0c03fc9b0ef9153250cbe5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 16 Sep 2022 14:23:44 +0000 Subject: [PATCH 26/27] Post-release preparation for codeql-cli-2.10.5 --- cpp/ql/lib/qlpack.yml | 2 +- cpp/ql/src/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/lib/qlpack.yml | 2 +- csharp/ql/campaigns/Solorigate/src/qlpack.yml | 2 +- csharp/ql/lib/qlpack.yml | 2 +- csharp/ql/src/qlpack.yml | 2 +- go/ql/lib/qlpack.yml | 2 +- go/ql/src/qlpack.yml | 2 +- java/ql/lib/qlpack.yml | 2 +- java/ql/src/qlpack.yml | 2 +- javascript/ql/lib/qlpack.yml | 2 +- javascript/ql/src/qlpack.yml | 2 +- python/ql/lib/qlpack.yml | 2 +- python/ql/src/qlpack.yml | 2 +- ruby/ql/lib/qlpack.yml | 2 +- ruby/ql/src/qlpack.yml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index 10d87da8f2b..4d96d9635ed 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.3.5 +version: 0.3.6-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index fb1043cf900..252f9baa0f4 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.3.4 +version: 0.3.5-dev groups: - cpp - queries diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 79f23b2b333..6d33146531d 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.2.5 +version: 1.2.6-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 8f1c7ce969f..0b31bb4af53 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.2.5 +version: 1.2.6-dev groups: - csharp - solorigate diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 3b5e0f4ebd6..0af84d51ff3 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.3.5 +version: 0.3.6-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 4efd85c33ae..2bd1377630e 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.3.4 +version: 0.3.5-dev groups: - csharp - queries diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 142cb56bdf0..24aa7b5555b 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.2.5 +version: 0.2.6-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index 687a6f19339..f09a484438b 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.2.5 +version: 0.2.6-dev groups: - go - queries diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index 8244ec88325..03b3ee513e8 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.3.5 +version: 0.3.6-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index e4fd07d53c6..3396c56e727 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.3.4 +version: 0.3.5-dev groups: - java - queries diff --git a/javascript/ql/lib/qlpack.yml b/javascript/ql/lib/qlpack.yml index b4cc4229c5d..50e91d2bb3f 100644 --- a/javascript/ql/lib/qlpack.yml +++ b/javascript/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-all -version: 0.2.5 +version: 0.2.6-dev groups: javascript dbscheme: semmlecode.javascript.dbscheme extractor: javascript diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 4c29faf8f6e..f2f20efe77e 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/javascript-queries -version: 0.3.4 +version: 0.3.5-dev groups: - javascript - queries diff --git a/python/ql/lib/qlpack.yml b/python/ql/lib/qlpack.yml index 394957b4ff2..2159b9feb55 100644 --- a/python/ql/lib/qlpack.yml +++ b/python/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-all -version: 0.5.5 +version: 0.5.6-dev groups: python dbscheme: semmlecode.python.dbscheme extractor: python diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 8beca495a77..64890188a55 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/python-queries -version: 0.4.3 +version: 0.4.4-dev groups: - python - queries diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index 0815ff3c100..0645e09464b 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-all -version: 0.3.5 +version: 0.3.6-dev groups: ruby extractor: ruby dbscheme: ruby.dbscheme diff --git a/ruby/ql/src/qlpack.yml b/ruby/ql/src/qlpack.yml index bf62aa5e568..453674eeb7c 100644 --- a/ruby/ql/src/qlpack.yml +++ b/ruby/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/ruby-queries -version: 0.3.4 +version: 0.3.5-dev groups: - ruby - queries From d0c6837a797231a0d664e99e78b8bc8ecade3615 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Sat, 17 Sep 2022 14:07:40 +0200 Subject: [PATCH 27/27] C#: Do not recognize 'run' as supported dotnet command for tracing. --- csharp/tools/tracing-config.lua | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/csharp/tools/tracing-config.lua b/csharp/tools/tracing-config.lua index b34549e73fd..03d1e49699a 100644 --- a/csharp/tools/tracing-config.lua +++ b/csharp/tools/tracing-config.lua @@ -36,26 +36,12 @@ function RegisterExtractorPack(id) match = true break end - if arg == 'run' then - -- for `dotnet run`, we need to make sure that `-p:UseSharedCompilation=false` is - -- not passed in as an argument to the program that is run - match = true - needsSeparator = true - end - end - if arg == '--' then - needsSeparator = false - break end end if match then - local injections = { '-p:UseSharedCompilation=false' } - if needsSeparator then - table.insert(injections, '--') - end return { order = ORDER_REPLACE, - invocation = BuildExtractorInvocation(id, compilerPath, compilerPath, compilerArguments, nil, injections) + invocation = BuildExtractorInvocation(id, compilerPath, compilerPath, compilerArguments, nil, { '-p:UseSharedCompilation=false' }) } end return nil