Skip to content

Commit c006526

Browse files
committed
Merge branch 'main' into feat/csharp-missed-firstordefault-opprtunity
2 parents 6da0e6a + 1c6516e commit c006526

15 files changed

Lines changed: 397 additions & 207 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ abstract class MemoryLocation0 extends TMemoryLocation {
295295
*/
296296
abstract class VirtualVariable extends MemoryLocation0 { }
297297

298+
pragma[nomagic]
299+
private VirtualVariable getAllocationMemoryLocation(Allocation alloc) {
300+
result.getAnAllocation() = alloc
301+
}
302+
298303
abstract class AllocationMemoryLocation extends MemoryLocation0 {
299304
Allocation var;
300305
boolean isMayAccess;
@@ -313,7 +318,7 @@ abstract class AllocationMemoryLocation extends MemoryLocation0 {
313318
result = getGroupedMemoryLocation(var, false, false).getVirtualVariable()
314319
or
315320
not exists(getGroupedMemoryLocation(var, false, false)) and
316-
result.(AllocationMemoryLocation).getAnAllocation() = var
321+
result = getAllocationMemoryLocation(var)
317322
)
318323
}
319324

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,11 @@ class TranslatedExplicitFieldInitialization extends TranslatedNonDefaultFieldIni
618618
override int getPosition() { result = position }
619619
}
620620

621+
pragma[nomagic]
622+
private Instruction getCallInstruction(TranslatedDefaultFieldInitialization tdfi) {
623+
result = tdfi.getInstruction(CallTag())
624+
}
625+
621626
/**
622627
* The IR translation of the initialization of a field from an element of an initializer
623628
* list where default initialization is used.
@@ -642,7 +647,7 @@ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization
642647

643648
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
644649
tag = CallTargetTag() and
645-
result = this.getInstruction(CallTag())
650+
result = getCallInstruction(this)
646651
or
647652
tag = CallTag() and
648653
result = this.getSideEffects().getFirstInstruction(kind)

docs/codeql/reusables/supported-versions-compilers.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
:stub-columns: 1
55

66
Language,Variants,Compilers,Extensions
7-
C/C++,"C89, C99, C11, C17, C23, C++98, C++03, C++11, C++14, C++17, C++20, C++23 [1]_ [2]_ [3]_","Clang (including clang-cl and armclang) extensions (up to Clang 21),
7+
C/C++,"C89, C99, C11, C17, C23, C++98, C++03, C++11, C++14, C++17, C++20, C++23 [1]_ [2]_ [3]_","Clang (including clang-cl and armclang) extensions (up to Clang 22),
88

9-
GNU extensions (up to GCC 15),
9+
GNU extensions (up to GCC 16),
1010

1111
Microsoft extensions (up to VS 2022),
1212

go/ql/lib/semmle/go/dependencies/SemVer.qll

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ overlay[local?]
55
module;
66

77
import semmle.go.dependencies.Dependencies
8+
private import codeql.util.SemVer
89

910
/**
1011
* A SemVer-formatted version string in a dependency.
@@ -17,63 +18,42 @@ class DependencySemVer extends string {
1718

1819
DependencySemVer() {
1920
this = dep.getDepVersion() and
20-
normalized = normalizeSemver(this)
21+
normalized = padSemVer(this)
2122
}
2223

2324
/**
2425
* Holds if this version may be before `last`.
2526
*/
2627
bindingset[last]
27-
predicate maybeBefore(string last) { normalized < normalizeSemver(last) }
28+
predicate maybeBefore(string last) { normalized < padSemVer(last) }
2829

2930
/**
3031
* Holds if this version may be after `first`.
3132
*/
3233
bindingset[first]
33-
predicate maybeAfter(string first) { normalizeSemver(first) < normalized }
34+
predicate maybeAfter(string first) { padSemVer(first) < normalized }
3435

3536
/**
3637
* Holds if this version may be between `first` (inclusive) and `last` (exclusive).
3738
*/
3839
bindingset[first, last]
3940
predicate maybeBetween(string first, string last) {
40-
normalizeSemver(first) <= normalized and
41-
normalized < normalizeSemver(last)
41+
padSemVer(first) <= normalized and
42+
normalized < padSemVer(last)
4243
}
4344

4445
/**
4546
* Holds if this version is equivalent to `other`.
4647
*/
4748
bindingset[other]
48-
predicate is(string other) { normalized = normalizeSemver(other) }
49+
predicate is(string other) { normalized = padSemVer(other) }
4950

5051
/**
5152
* Gets the dependency that uses this string.
5253
*/
5354
Dependency getDependency() { result = dep }
5455
}
5556

56-
bindingset[str]
57-
private string leftPad(string str) { result = ("000" + str).suffix(str.length()) }
58-
59-
/**
60-
* Normalizes a SemVer string such that the lexicographical ordering
61-
* of two normalized strings is consistent with the SemVer ordering.
62-
*
63-
* Pre-release information and build metadata is not yet supported.
64-
*/
65-
bindingset[orig]
66-
private string normalizeSemver(string orig) {
67-
exists(string pattern, string major, string minor, string patch |
68-
pattern = "v?(\\d+)\\.(\\d+)\\.(\\d+)(\\D.*)?" and
69-
major = orig.regexpCapture(pattern, 1) and
70-
minor = orig.regexpCapture(pattern, 2) and
71-
patch = orig.regexpCapture(pattern, 3)
72-
|
73-
result = leftPad(major) + "." + leftPad(minor) + "." + leftPad(patch)
74-
)
75-
}
76-
7757
/**
7858
* A version string in a dependency that has a SemVer, but also contains a git commit SHA.
7959
*

java/kotlin-extractor/src/main/java/com/semmle/util/files/FileUtil.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,8 @@ public static File tryMakeCanonical (File f)
12441244
try {
12451245
// getCanonicalFile does not canonicalize subst drives on Windows, so do this separately. This
12461246
// is a no-op on non-Windows platforms.
1247-
return SubstResolver.resolve(f.getCanonicalFile()); }
1248-
catch (IOException ignored) {
1247+
return SubstResolver.resolve(f.getCanonicalFile());
1248+
} catch (IOException ignored) {
12491249
Exceptions.ignore(ignored, "Can't log error: Could be too verbose.");
12501250
return new File(simplifyPath(f));
12511251
}

java/ql/integration-tests/java/gradle-sample-without-wrapper-or-gradle-buildless/test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
# The version of gradle used doesn't work on java 17
77
def test(codeql, use_java_11, java, environment, check_diagnostics):
88
check_diagnostics.redact += ["attributes.java_vendor"]
9-
check_diagnostics.replacements = [("11\\.[0-9]+\\.[0-9]+", "11")]
9+
# the JDK build provided by the CI runner image may report any number of version components
10+
# (e.g. `11.0.32` or `11.0.32.1`), so keep only the feature version
11+
check_diagnostics.replacements = [(r'"11(\.[0-9]+)+"', '"11"')]
1012
gradle_override_dir = pathlib.Path(tempfile.mkdtemp())
1113
if runs_on.windows:
1214
(gradle_override_dir / "gradle.bat").write_text("@echo off\nexit /b 2\n")

javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import semmle.javascript.dependencies.Dependencies
6+
private import codeql.util.SemVer
67

78
/**
89
* A SemVer-formatted version string in a dependency.
@@ -15,59 +16,38 @@ class DependencySemVer extends string {
1516

1617
DependencySemVer() {
1718
dep.info(_, this) and
18-
normalized = normalizeSemver(this)
19+
normalized = padSemVer(this)
1920
}
2021

2122
/**
2223
* Holds if this version may be before `last`.
2324
*/
2425
bindingset[last]
25-
predicate maybeBefore(string last) { normalized < normalizeSemver(last) }
26+
predicate maybeBefore(string last) { normalized < padSemVer(last) }
2627

2728
/**
2829
* Holds if this version may be after `first`.
2930
*/
3031
bindingset[first]
31-
predicate maybeAfter(string first) { normalizeSemver(first) < normalized }
32+
predicate maybeAfter(string first) { padSemVer(first) < normalized }
3233

3334
/**
3435
* Holds if this version may be between `first` (inclusive) and `last` (exclusive).
3536
*/
3637
bindingset[first, last]
3738
predicate maybeBetween(string first, string last) {
38-
normalizeSemver(first) <= normalized and
39-
normalized < normalizeSemver(last)
39+
padSemVer(first) <= normalized and
40+
normalized < padSemVer(last)
4041
}
4142

4243
/**
4344
* Holds if this version is equivalent to `other`.
4445
*/
4546
bindingset[other]
46-
predicate is(string other) { normalized = normalizeSemver(other) }
47+
predicate is(string other) { normalized = padSemVer(other) }
4748

4849
/**
4950
* Gets the dependency that uses this string.
5051
*/
5152
Dependency getDependency() { result = dep }
5253
}
53-
54-
bindingset[str]
55-
private string leftPad(string str) { result = ("000" + str).suffix(str.length()) }
56-
57-
/**
58-
* Normalizes a SemVer string such that the lexicographical ordering
59-
* of two normalized strings is consistent with the SemVer ordering.
60-
*
61-
* Pre-release information and build metadata is not yet supported.
62-
*/
63-
bindingset[orig]
64-
private string normalizeSemver(string orig) {
65-
exists(string pattern, string major, string minor, string patch |
66-
pattern = "(\\d+)\\.(\\d+)\\.(\\d+)" and
67-
major = orig.regexpCapture(pattern, 1) and
68-
minor = orig.regexpCapture(pattern, 2) and
69-
patch = orig.regexpCapture(pattern, 3)
70-
|
71-
result = leftPad(major) + "." + leftPad(minor) + "." + leftPad(patch)
72-
)
73-
}

ruby/ql/lib/codeql/ruby/frameworks/Gemfile.qll

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
private import codeql.ruby.AST
6+
private import codeql.util.SemVer
67

78
/**
89
* Provides classes and predicates for Gemfiles, including version constraint logic.
@@ -138,7 +139,7 @@ module Gemfile {
138139
exists(int thisMajor, int thisMinor, int otherMajor, int otherMinor |
139140
thisMajor = this.getVersion().getMajor() and
140141
thisMinor = this.getVersion().getMinor() and
141-
exists(string maj, string mi | normalizeSemver(other, _, maj, mi, _) |
142+
exists(string maj, string mi | exists(padSemVer(other, maj, mi, _)) |
142143
otherMajor = maj.toInt() and otherMinor = mi.toInt()
143144
)
144145
|
@@ -171,26 +172,26 @@ module Gemfile {
171172

172173
Version() {
173174
this = any(Gem c).getAVersionConstraint().getVersionString() and
174-
normalized = normalizeSemver(this)
175+
normalized = padSemVer(this)
175176
}
176177

177178
/**
178179
* Holds if this version is strictly before the version defined by `other`.
179180
*/
180181
bindingset[other]
181-
predicate before(string other) { normalized < normalizeSemver(other) }
182+
predicate before(string other) { normalized < padSemVer(other) }
182183

183184
/**
184185
* Holds if this versino is equal to the version defined by `other`.
185186
*/
186187
bindingset[other]
187-
predicate equal(string other) { normalized = normalizeSemver(other) }
188+
predicate equal(string other) { normalized = padSemVer(other) }
188189

189190
/**
190191
* Holds if this version is strictly after the version defined by `other`.
191192
*/
192193
bindingset[other]
193-
predicate after(string other) { normalized > normalizeSemver(other) }
194+
predicate after(string other) { normalized > padSemVer(other) }
194195

195196
/**
196197
* Holds if this version defines a patch number.
@@ -212,43 +213,4 @@ module Gemfile {
212213
*/
213214
int getPatch() { result = getPatch(normalized).toInt() }
214215
}
215-
216-
/**
217-
* Normalizes a SemVer string such that the lexicographical ordering
218-
* of two normalized strings is consistent with the SemVer ordering.
219-
*
220-
* Pre-release information and build metadata is not supported.
221-
*/
222-
bindingset[orig]
223-
private predicate normalizeSemver(
224-
string orig, string normalized, string major, string minor, string patch
225-
) {
226-
major = getMajor(orig) and
227-
(
228-
minor = getMinor(orig)
229-
or
230-
not exists(getMinor(orig)) and minor = "0"
231-
) and
232-
(
233-
patch = getPatch(orig)
234-
or
235-
not exists(getPatch(orig)) and patch = "0"
236-
) and
237-
normalized = leftPad(major) + "." + leftPad(minor) + "." + leftPad(patch)
238-
}
239-
240-
bindingset[orig]
241-
private string normalizeSemver(string orig) { normalizeSemver(orig, result, _, _, _) }
242-
243-
bindingset[s]
244-
private string getMajor(string s) { result = s.regexpCapture("(\\d+).*", 1) }
245-
246-
bindingset[s]
247-
private string getMinor(string s) { result = s.regexpCapture("(\\d+)\\.(\\d+).*", 2) }
248-
249-
bindingset[s]
250-
private string getPatch(string s) { result = s.regexpCapture("(\\d+)\\.(\\d+)\\.(\\d+).*", 3) }
251-
252-
bindingset[str]
253-
private string leftPad(string str) { result = ("000" + str).suffix(str.length()) }
254216
}

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
4848
private import codeql.rust.internal.CachedStages
4949
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
5050
private import codeql.util.Option
51+
private import codeql.util.SemVer
5152

5253
private newtype TNamespace =
5354
TTypeNamespace() or
@@ -568,6 +569,16 @@ class CrateItemNode extends NamedItemNode instanceof Crate {
568569
)
569570
}
570571

572+
pragma[nomagic]
573+
predicate isLatestVersion(string name) {
574+
this =
575+
max(CrateItemNode c, string ver |
576+
name = c.getName() and ver = padSemVer(c.(Crate).getVersion())
577+
|
578+
c order by ver
579+
)
580+
}
581+
571582
override string getName() { result = Crate.super.getName() }
572583

573584
override Namespace getNamespace() {
@@ -1529,11 +1540,11 @@ private predicate crateDependencyEdge(SourceFileItemNode file, string name, Crat
15291540
crateDependency(file, name, dep)
15301541
or
15311542
// As a fallback, give all files access to crates that do not conflict with known dependencies
1532-
// and declarations. This is in order to workaround incomplete crate dependency information
1533-
// provided by the extractor, as well as `CrateItemNode.getASourceFile()` being unable to map
1534-
// a given file to its crate (for example, if the file is `mod` imported inside a macro that the
1535-
// extractor is unable to expand).
1536-
name = dep.getName() and
1543+
// and declarations, as long as those crates have a unique latest version.
1544+
// This is in order to workaround incomplete crate dependency information provided by the extractor,
1545+
// as well as `CrateItemNode.getASourceFile()` being unable to map a given file to its crate (for
1546+
// example, if the file is `mod` imported inside a macro that the extractor is unable to expand).
1547+
dep = unique(CrateItemNode dep0 | dep0.isLatestVersion(name)) and
15371548
not hasDeclOrDep(file, name)
15381549
}
15391550

@@ -2385,6 +2396,11 @@ private module Debug {
23852396
useImportEdge(use, name, item, kind)
23862397
}
23872398

2399+
predicate debugCrateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
2400+
file = getRelevantLocatable() and
2401+
crateDependencyEdge(file, name, dep)
2402+
}
2403+
23882404
ItemNode debugGetASuccessor(ItemNode i, string name, SuccessorKind kind) {
23892405
i = getRelevantLocatable() and
23902406
result = i.getASuccessor(name, kind, _)

0 commit comments

Comments
 (0)