Skip to content

Commit 410350c

Browse files
authored
Merge branch 'main' into feature/python-mcp-remote-sources
2 parents 1ae3030 + b6a9c9a commit 410350c

10 files changed

Lines changed: 166 additions & 99 deletions

File tree

‎cpp/ql/test/library-tests/ir/ir/PrintAST.expected‎

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4367,18 +4367,6 @@ destructors_for_temps.cpp:
43674367
# 109| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
43684368
# 109| Type = [IntPointerType] int *
43694369
# 109| ValueCategory = prvalue
4370-
# 109| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithArrayAndDestructor
4371-
# 109| Type = [VoidType] void
4372-
# 109| ValueCategory = prvalue
4373-
# 109| getQualifier(): [ReuseExpr] reuse of temporary object
4374-
# 109| Type = [Struct] ClassWithArrayAndDestructor
4375-
# 109| ValueCategory = xvalue
4376-
# 109| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithArrayAndDestructor
4377-
# 109| Type = [VoidType] void
4378-
# 109| ValueCategory = prvalue
4379-
# 109| getQualifier(): [ReuseExpr] reuse of temporary object
4380-
# 109| Type = [Struct] ClassWithArrayAndDestructor
4381-
# 109| ValueCategory = xvalue
43824370
# 109| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
43834371
# 109| Type = [LValueReferenceType] const int &
43844372
# 109| ValueCategory = prvalue
@@ -4387,6 +4375,18 @@ destructors_for_temps.cpp:
43874375
# 109| Type = [SpecifiedType] const int
43884376
# 109| ValueCategory = lvalue
43894377
# 110| getStmt(1): [ReturnStmt] return ...
4378+
# 111| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithArrayAndDestructor
4379+
# 111| Type = [VoidType] void
4380+
# 111| ValueCategory = prvalue
4381+
# 111| getQualifier(): [ReuseExpr] reuse of temporary object
4382+
# 111| Type = [Struct] ClassWithArrayAndDestructor
4383+
# 111| ValueCategory = xvalue
4384+
# 111| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithArrayAndDestructor
4385+
# 111| Type = [VoidType] void
4386+
# 111| ValueCategory = prvalue
4387+
# 111| getQualifier(): [ReuseExpr] reuse of temporary object
4388+
# 111| Type = [Struct] ClassWithArrayAndDestructor
4389+
# 111| ValueCategory = xvalue
43904390
generic.c:
43914391
# 1| [TopLevelFunction] void c11_generic_test_with_load(unsigned int, int)
43924392
# 1| <params>:
@@ -15082,6 +15082,9 @@ ir.cpp:
1508215082
# 1476| getQualifier(): [FunctionCall] call to returnValue
1508315083
# 1476| Type = [Struct] UnusualFields
1508415084
# 1476| ValueCategory = prvalue
15085+
#-----| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
15086+
#-----| Type = [Struct] UnusualFields
15087+
#-----| ValueCategory = prvalue(load)
1508515088
# 1476| getArrayOffset(): [Literal] 3
1508615089
# 1476| Type = [IntType] int
1508715090
# 1476| Value = [Literal] 3

‎cpp/ql/test/library-tests/ir/ir/aliased_ir.expected‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12179,19 +12179,19 @@ ir.cpp:
1217912179
# 1474| r1474_10(int) = Load[?] : &:r1474_9, ~m1474_5
1218012180
# 1474| m1474_11(int) = Store[x] : &:r1474_1, r1474_10
1218112181
# 1476| r1476_1(glval<float &>) = VariableAddress[rf] :
12182+
#-----| r0_1(glval<UnusualFields>) = VariableAddress[#temp0:0] :
1218212183
# 1476| r1476_2(glval<unknown>) = FunctionAddress[returnValue] :
1218312184
# 1476| r1476_3(UnusualFields) = Call[returnValue] : func:r1476_2
1218412185
# 1476| m1476_4(unknown) = ^CallSideEffect : ~m1474_5
1218512186
# 1476| m1476_5(unknown) = Chi : total:m1474_5, partial:m1476_4
12186-
# 1476| r1476_6(glval<UnusualFields>) = VariableAddress[#temp1476:23] :
12187-
# 1476| m1476_7(UnusualFields) = Store[#temp1476:23] : &:r1476_6, r1476_3
12188-
# 1476| r1476_8(glval<float[10]>) = FieldAddress[a] : r1476_6
12189-
# 1476| r1476_9(float *) = Convert : r1476_8
12190-
# 1476| r1476_10(int) = Constant[3] :
12191-
# 1476| r1476_11(glval<float>) = PointerAdd[4] : r1476_9, r1476_10
12192-
# 1476| r1476_12(glval<float>) = Convert : r1476_11
12193-
# 1476| r1476_13(float &) = CopyValue : r1476_12
12194-
# 1476| m1476_14(float &) = Store[rf] : &:r1476_1, r1476_13
12187+
# 1476| m1476_6(UnusualFields) = Store[#temp0:0] : &:r0_1, r1476_3
12188+
# 1476| r1476_7(glval<float[10]>) = FieldAddress[a] : r0_1
12189+
# 1476| r1476_8(float *) = Convert : r1476_7
12190+
# 1476| r1476_9(int) = Constant[3] :
12191+
# 1476| r1476_10(glval<float>) = PointerAdd[4] : r1476_8, r1476_9
12192+
# 1476| r1476_11(glval<float>) = Convert : r1476_10
12193+
# 1476| r1476_12(float &) = CopyValue : r1476_11
12194+
# 1476| m1476_13(float &) = Store[rf] : &:r1476_1, r1476_12
1219512195
# 1477| r1477_1(glval<float>) = VariableAddress[f] :
1219612196
# 1477| r1477_2(glval<unknown>) = FunctionAddress[returnValue] :
1219712197
# 1477| r1477_3(UnusualFields) = Call[returnValue] : func:r1477_2

‎cpp/ql/test/library-tests/ir/ir/raw_ir.expected‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11173,18 +11173,18 @@ ir.cpp:
1117311173
# 1474| r1474_9(int) = Load[?] : &:r1474_8, ~m?
1117411174
# 1474| mu1474_10(int) = Store[x] : &:r1474_1, r1474_9
1117511175
# 1476| r1476_1(glval<float &>) = VariableAddress[rf] :
11176+
#-----| r0_1(glval<UnusualFields>) = VariableAddress[#temp0:0] :
1117611177
# 1476| r1476_2(glval<unknown>) = FunctionAddress[returnValue] :
1117711178
# 1476| r1476_3(UnusualFields) = Call[returnValue] : func:r1476_2
1117811179
# 1476| mu1476_4(unknown) = ^CallSideEffect : ~m?
11179-
# 1476| r1476_5(glval<UnusualFields>) = VariableAddress[#temp1476:23] :
11180-
# 1476| mu1476_6(UnusualFields) = Store[#temp1476:23] : &:r1476_5, r1476_3
11181-
# 1476| r1476_7(glval<float[10]>) = FieldAddress[a] : r1476_5
11182-
# 1476| r1476_8(float *) = Convert : r1476_7
11183-
# 1476| r1476_9(int) = Constant[3] :
11184-
# 1476| r1476_10(glval<float>) = PointerAdd[4] : r1476_8, r1476_9
11185-
# 1476| r1476_11(glval<float>) = Convert : r1476_10
11186-
# 1476| r1476_12(float &) = CopyValue : r1476_11
11187-
# 1476| mu1476_13(float &) = Store[rf] : &:r1476_1, r1476_12
11180+
# 1476| mu1476_5(UnusualFields) = Store[#temp0:0] : &:r0_1, r1476_3
11181+
# 1476| r1476_6(glval<float[10]>) = FieldAddress[a] : r0_1
11182+
# 1476| r1476_7(float *) = Convert : r1476_6
11183+
# 1476| r1476_8(int) = Constant[3] :
11184+
# 1476| r1476_9(glval<float>) = PointerAdd[4] : r1476_7, r1476_8
11185+
# 1476| r1476_10(glval<float>) = Convert : r1476_9
11186+
# 1476| r1476_11(float &) = CopyValue : r1476_10
11187+
# 1476| mu1476_12(float &) = Store[rf] : &:r1476_1, r1476_11
1118811188
# 1477| r1477_1(glval<float>) = VariableAddress[f] :
1118911189
# 1477| r1477_2(glval<unknown>) = FunctionAddress[returnValue] :
1119011190
# 1477| r1477_3(UnusualFields) = Call[returnValue] : func:r1477_2

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
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 22),
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 23),
88

99
GNU extensions (up to GCC 16),
1010

11-
Microsoft extensions (up to VS 2022),
11+
Microsoft extensions (up to VS 2026),
1212

1313
Arm Compiler 5 [4]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``"
1414
C#,C# up to 14,"Microsoft Visual Studio up to 2019 with .NET up to 4.8,

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowGraph.qll‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,26 @@ module DebugGraph<relevantNodeSig/1 relevantNode> {
176176
value = node.toString()
177177
}
178178

179+
private predicate isBypassedStoreReadStep(Step s) {
180+
exists(ContentSet contents |
181+
s.read(contents)
182+
or
183+
s.store(contents)
184+
|
185+
bypassContentSet(contents)
186+
)
187+
}
188+
179189
query predicate edges(Node node1, Node node2, string key, string value) {
180190
key = "semmle.label" and
181191
relevantDataFlowNode(node1) and
182192
relevantDataFlowNode(node2) and
183193
(
184194
exists(Step step |
185195
step(node1, step, node2) and
186-
value = step.toString()
196+
if isBypassedStoreReadStep(step)
197+
then value = "value [bypassed " + step.toString() + "]"
198+
else value = step.toString()
187199
)
188200
or
189201
exists(boolean isUseStep |

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowInstantiation.qll‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,20 +127,33 @@ module DataFlowInput implements InputSig<Location> {
127127
//
128128
// Steps
129129
//
130+
pragma[nomagic]
131+
private Step valueStepEx() {
132+
result.value()
133+
or
134+
exists(ContentSet contents | bypassContentSet(contents) |
135+
result.read(contents)
136+
or
137+
result.store(contents)
138+
)
139+
}
140+
130141
predicate simpleLocalFlowStep(Node node1, Node node2, string model) {
131-
step(node1, any(Step s | s.value()), node2) and model = ""
142+
step(node1, valueStepEx(), node2) and model = ""
132143
or
133144
localSsaStep(node1, node2, _) and model = ""
134145
}
135146

136147
predicate jumpStep(Node node1, Node node2) { step(node1, any(Step s | s.jump()), node2) }
137148

138149
predicate readStep(Node node1, ContentSet c, Node node2) {
139-
step(node1, any(Step s | s.read(c)), node2)
150+
step(node1, any(Step s | s.read(c)), node2) and
151+
not bypassContentSet(c)
140152
}
141153

142154
predicate storeStep(Node node1, ContentSet c, Node node2) {
143-
step(node1, any(Step s | s.store(c)), node2)
155+
step(node1, any(Step s | s.store(c)), node2) and
156+
not bypassContentSet(c)
144157
}
145158

146159
predicate clearsContent(Node n, ContentSet c) { none() } // TODO

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPlugin.qll‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,16 @@ private module Plugins {
1313
class DataFlowPlugin extends Unit {
1414
/** Holds if there is a language-specific step from `node1 -> step -> node2`. */
1515
predicate step(Node node1, Step step, Node node2) { none() }
16+
17+
/**
18+
* Holds if a read/store step with the given `contents` should be converted to a value step.
19+
*
20+
* This affects the steps generated by the language-agnostic code as well as steps from the plugin itself.
21+
*/
22+
predicate bypassContentSet(ContentSet contents) { none() }
1623
}
24+
25+
/**
26+
* Holds if a read/store step with the given `contents` should be converted to a value step.
27+
*/
28+
predicate bypassContentSet(ContentSet contents) { any(DataFlowPlugin p).bypassContentSet(contents) }

‎unified/ql/lib/codeql/unified/internal/dataflow/DataFlowPluginSwift.qll‎

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ private import unified
66
private import AllDataFlow
77

88
private class SwiftDataFlowPlugin extends DataFlowPlugin {
9+
override predicate bypassContentSet(ContentSet contents) {
10+
contents.asSingleton().asNamedMember() = "some.0"
11+
}
12+
913
// Note: For now we assume all code is Swift, but in the future we must restrict these rules to Swift-files
1014
override predicate step(Node node1, Step step, Node node2) {
1115
exists(BinaryExpr expr |
@@ -27,33 +31,31 @@ private class SwiftDataFlowPlugin extends DataFlowPlugin {
2731
)
2832
or
2933
exists(UnaryExpr expr |
30-
expr.getOperator().(PostfixOperator).getValue() = "!" and
31-
node1.isResultValue(expr.getOperand()) and
32-
(step.readName("some.0") or step.taint()) and
33-
node2.isResultValue(expr)
34+
expr.getOperator().(PostfixOperator).getValue() = "!"
3435
or
35-
expr.getOperator().(PrefixOperator).getValue() = ["try", "try!", "await"] and
36+
expr.getOperator().(PrefixOperator).getValue() = ["try", "try!", "try?", "await"]
37+
|
3638
node1.isResultValue(expr.getOperand()) and
3739
step.value() and
3840
node2.isResultValue(expr)
39-
or
40-
expr.getOperator().(PrefixOperator).getValue() = "try?" and
41-
// TODO: preserve the value of some.0 if it is already stored in that
42-
node1.isResultValue(expr.getOperand()) and
43-
step.storeName("some.0") and
44-
node2.isResultValue(expr)
4541
)
4642
or
4743
exists(TypeCastExpr expr |
48-
// The `as?` type cast boxes the incoming value in Optional depending on whether the type cast succeeded
49-
expr.getOperator().getValue() = "as?" and
44+
// Type-cast operators:
45+
// - "as": Safe upcast conversion
46+
// - "as?": Wrap in Optional<T> if cast succeeds
47+
// - "as!": Throw if cast fails
48+
//
49+
// Since we bypass Optional<T> content, we model all of these as value steps.
50+
expr.getOperator().getValue() = ["as", "as?", "as!"] and
5051
node1.isResultValue(expr.getExpr()) and
51-
step.storeName("some.0") and
52+
step.value() and
5253
node2.isResultValue(expr)
53-
or
54-
// Safe upcast conversion ("as") and downcast-or-throw ("as!") propagate the value directly
55-
expr.getOperator().getValue() = ["as", "as!"] and
56-
node1.isResultValue(expr.getExpr()) and
54+
)
55+
or
56+
exists(NullCoalescingExpr expr |
57+
// We bypass Optional<T> content so we add value-flow out of both operands of "??"
58+
node1.isResultValue(expr.getAnOperand()) and
5759
step.value() and
5860
node2.isResultValue(expr)
5961
)

0 commit comments

Comments
 (0)