Skip to content

Commit f015cea

Browse files
committed
Merge branch 'main' into feature/service-stack
2 parents 05dd3fa + 0198cf6 commit f015cea

File tree

778 files changed

+28170
-5657
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

778 files changed

+28170
-5657
lines changed

.github/workflows/csv-coverage-update.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
jobs:
99
update:
1010
name: Update framework coverage report
11-
if: github.event.repository.fork == false
11+
if: github.repository == 'github/codeql'
1212
runs-on: ubuntu-latest
1313

1414
steps:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The `SimpleRangeAnalysis` library includes information from the
3+
immediate guard for determining the upper bound of a stack
4+
variable for improved accuracy.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The `memberMayBeVarSize` predicate considers more fields to be variable size.
3+
As a result, the "Static buffer overflow" query (cpp/static-buffer-overflow)
4+
produces fewer false positives.

cpp/ql/lib/semmle/code/cpp/File.qll

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class Container extends Locatable, @container {
171171
* To get the full path, use `getAbsolutePath`.
172172
*/
173173
class Folder extends Container, @folder {
174-
override string getAbsolutePath() { folders(underlyingElement(this), result, _) }
174+
override string getAbsolutePath() { folders(underlyingElement(this), result) }
175175

176176
override Location getLocation() {
177177
result.getContainer() = this and
@@ -190,7 +190,7 @@ class Folder extends Container, @folder {
190190
* DEPRECATED: use `getAbsolutePath` instead.
191191
* Gets the name of this folder.
192192
*/
193-
deprecated string getName() { folders(underlyingElement(this), result, _) }
193+
deprecated string getName() { folders(underlyingElement(this), result) }
194194

195195
/**
196196
* DEPRECATED: use `getAbsolutePath` instead.
@@ -208,17 +208,7 @@ class Folder extends Container, @folder {
208208
* DEPRECATED: use `getBaseName` instead.
209209
* Gets the last part of the folder name.
210210
*/
211-
deprecated string getShortName() {
212-
exists(string longnameRaw, string longname |
213-
folders(underlyingElement(this), _, longnameRaw) and
214-
longname = longnameRaw.replaceAll("\\", "/")
215-
|
216-
exists(int index |
217-
result = longname.splitAt("/", index) and
218-
not exists(longname.splitAt("/", index + 1))
219-
)
220-
)
221-
}
211+
deprecated string getShortName() { result = this.getBaseName() }
222212

223213
/**
224214
* DEPRECATED: use `getParentContainer` instead.
@@ -242,7 +232,7 @@ class Folder extends Container, @folder {
242232
* `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`.
243233
*/
244234
class File extends Container, @file {
245-
override string getAbsolutePath() { files(underlyingElement(this), result, _, _, _) }
235+
override string getAbsolutePath() { files(underlyingElement(this), result) }
246236

247237
override string toString() { result = Container.super.toString() }
248238

@@ -336,7 +326,13 @@ class File extends Container, @file {
336326
* for example, for "file.tar.gz", this predicate will have the result
337327
* "tar.gz", while `getExtension` will have the result "gz".
338328
*/
339-
string getExtensions() { files(underlyingElement(this), _, _, result, _) }
329+
string getExtensions() {
330+
exists(string name, int firstDotPos |
331+
name = this.getBaseName() and
332+
firstDotPos = min([name.indexOf("."), name.length() - 1]) and
333+
result = name.suffix(firstDotPos + 1)
334+
)
335+
}
340336

341337
/**
342338
* Gets the short name of this file, that is, the prefix of its base name up
@@ -351,7 +347,16 @@ class File extends Container, @file {
351347
* for example, for "file.tar.gz", this predicate will have the result
352348
* "file", while `getStem` will have the result "file.tar".
353349
*/
354-
string getShortName() { files(underlyingElement(this), _, result, _, _) }
350+
string getShortName() {
351+
exists(string name, int firstDotPos |
352+
name = this.getBaseName() and
353+
firstDotPos = min([name.indexOf("."), name.length()]) and
354+
result = name.prefix(firstDotPos)
355+
)
356+
or
357+
this.getAbsolutePath() = "" and
358+
result = ""
359+
}
355360
}
356361

357362
/**

cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ import cpp
22
import semmle.code.cpp.dataflow.DataFlow
33

44
/**
5-
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
6-
* example:
5+
* Holds if `v` is a member variable of `c` that looks like it might be variable sized
6+
* in practice. For example:
77
* ```
88
* struct myStruct { // c
99
* int amount;
1010
* char data[1]; // v
1111
* };
1212
* ```
13-
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
14-
* there must be at least one instance where a `c` pointer is allocated with additional space. For
15-
* example, holds for `c` if it occurs as
13+
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`.
14+
* In addition, if the size of the structure is taken, there must be at least one instance
15+
* where a `c` pointer is allocated with additional space.
16+
* For example, holds for `c` if it occurs as
1617
* ```
1718
* malloc(sizeof(c) + 100 * sizeof(char))
1819
* ```
@@ -27,27 +28,25 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
2728
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
2829
v = c.getCanonicalMember(i) and
2930
// v is an array of size at most 1
30-
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
31+
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1 and
32+
not c instanceof Union
3133
) and
34+
// If the size is taken, then arithmetic is performed on the result at least once
3235
(
36+
// `sizeof(c)` is not taken
37+
not exists(SizeofOperator so |
38+
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
39+
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
40+
)
41+
or
42+
// or `sizeof(c)` is taken
3343
exists(SizeofOperator so |
34-
// `sizeof(c)` is taken
3544
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
3645
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
3746
|
38-
// arithmetic is performed on the result
47+
// and arithmetic is performed on the result
3948
so.getParent*() instanceof AddExpr
4049
)
41-
or
42-
exists(AddressOfExpr aoe |
43-
// `&(c.v)` is taken
44-
aoe.getAddressable() = v
45-
)
46-
or
47-
exists(BuiltInOperationBuiltInOffsetOf oo |
48-
// `offsetof(c, v)` using a builtin
49-
oo.getAChild().(VariableAccess).getTarget() = v
50-
)
5150
)
5251
}
5352

@@ -61,6 +60,10 @@ int getBufferSize(Expr bufferExpr, Element why) {
6160
result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and
6261
why = bufferVar and
6362
not memberMayBeVarSize(_, bufferVar) and
63+
not exists(Union bufferType |
64+
bufferType.getAMemberVariable() = why and
65+
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1
66+
) and
6467
not result = 0 // zero sized arrays are likely to have special usage, for example
6568
or
6669
// behaving a bit like a 'union' overlapping other fields.
@@ -82,6 +85,13 @@ int getBufferSize(Expr bufferExpr, Element why) {
8285
parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and
8386
result = getBufferSize(parentPtr, _) + bufferVar.getType().getSize() - parentClass.getSize()
8487
)
88+
or
89+
exists(Union bufferType |
90+
bufferType.getAMemberVariable() = why and
91+
why = bufferVar and
92+
bufferVar.getUnspecifiedType().(ArrayType).getSize() <= 1 and
93+
result = bufferType.getSize()
94+
)
8595
)
8696
or
8797
// buffer is a fixed size dynamic allocation

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -923,28 +923,29 @@ private module Stage2 {
923923

924924
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
925925

926-
class Cc = boolean;
927-
928-
class CcCall extends Cc {
929-
CcCall() { this = true }
926+
class Cc = CallContext;
930927

931-
/** Holds if this call context may be `call`. */
932-
predicate matchesCall(DataFlowCall call) { any() }
933-
}
928+
class CcCall = CallContextCall;
934929

935-
class CcNoCall extends Cc {
936-
CcNoCall() { this = false }
937-
}
930+
class CcNoCall = CallContextNoCall;
938931

939-
Cc ccNone() { result = false }
932+
Cc ccNone() { result instanceof CallContextAny }
940933

941934
private class LocalCc = Unit;
942935

943936
bindingset[call, c, outercc]
944-
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
937+
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
938+
checkCallContextCall(outercc, call, c) and
939+
if recordDataFlowCallSiteDispatch(call, c)
940+
then result = TSpecificCall(call)
941+
else result = TSomeCall()
942+
}
945943

946944
bindingset[call, c, innercc]
947-
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
945+
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
946+
checkCallContextReturn(innercc, c, call) and
947+
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
948+
}
948949

949950
bindingset[node, cc, config]
950951
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1172,7 +1173,8 @@ private module Stage2 {
11721173
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
11731174
pragma[only_bind_into](config)) and
11741175
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1175-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1176+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1177+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
11761178
pragma[only_bind_into](config))
11771179
)
11781180
}
@@ -1860,7 +1862,8 @@ private module Stage3 {
18601862
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
18611863
pragma[only_bind_into](config)) and
18621864
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1863-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1865+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1866+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
18641867
pragma[only_bind_into](config))
18651868
)
18661869
}
@@ -2117,7 +2120,7 @@ private module Stage3 {
21172120
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
21182121
exists(AccessPathFront apf |
21192122
Stage3::revFlow(node, true, _, apf, config) and
2120-
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
2123+
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
21212124
)
21222125
}
21232126

@@ -2618,7 +2621,8 @@ private module Stage4 {
26182621
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
26192622
pragma[only_bind_into](config)) and
26202623
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
2621-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
2624+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
2625+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
26222626
pragma[only_bind_into](config))
26232627
)
26242628
}
@@ -3686,8 +3690,8 @@ private module Subpaths {
36863690
*/
36873691
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
36883692
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
3689-
arg.getASuccessor() = par and
3690-
arg.getASuccessor() = out and
3693+
pragma[only_bind_into](arg).getASuccessor() = par and
3694+
pragma[only_bind_into](arg).getASuccessor() = out and
36913695
subpaths03(arg, p, ret, o, apout) and
36923696
par.getNodeEx() = p and
36933697
out.getNodeEx() = o and

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -923,28 +923,29 @@ private module Stage2 {
923923

924924
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
925925

926-
class Cc = boolean;
927-
928-
class CcCall extends Cc {
929-
CcCall() { this = true }
926+
class Cc = CallContext;
930927

931-
/** Holds if this call context may be `call`. */
932-
predicate matchesCall(DataFlowCall call) { any() }
933-
}
928+
class CcCall = CallContextCall;
934929

935-
class CcNoCall extends Cc {
936-
CcNoCall() { this = false }
937-
}
930+
class CcNoCall = CallContextNoCall;
938931

939-
Cc ccNone() { result = false }
932+
Cc ccNone() { result instanceof CallContextAny }
940933

941934
private class LocalCc = Unit;
942935

943936
bindingset[call, c, outercc]
944-
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
937+
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
938+
checkCallContextCall(outercc, call, c) and
939+
if recordDataFlowCallSiteDispatch(call, c)
940+
then result = TSpecificCall(call)
941+
else result = TSomeCall()
942+
}
945943

946944
bindingset[call, c, innercc]
947-
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
945+
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
946+
checkCallContextReturn(innercc, c, call) and
947+
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
948+
}
948949

949950
bindingset[node, cc, config]
950951
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
@@ -1172,7 +1173,8 @@ private module Stage2 {
11721173
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
11731174
pragma[only_bind_into](config)) and
11741175
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1175-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1176+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1177+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
11761178
pragma[only_bind_into](config))
11771179
)
11781180
}
@@ -1860,7 +1862,8 @@ private module Stage3 {
18601862
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
18611863
pragma[only_bind_into](config)) and
18621864
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
1863-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
1865+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
1866+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
18641867
pragma[only_bind_into](config))
18651868
)
18661869
}
@@ -2117,7 +2120,7 @@ private module Stage3 {
21172120
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
21182121
exists(AccessPathFront apf |
21192122
Stage3::revFlow(node, true, _, apf, config) and
2120-
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
2123+
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
21212124
)
21222125
}
21232126

@@ -2618,7 +2621,8 @@ private module Stage4 {
26182621
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
26192622
pragma[only_bind_into](config)) and
26202623
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
2621-
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
2624+
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
2625+
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
26222626
pragma[only_bind_into](config))
26232627
)
26242628
}
@@ -3686,8 +3690,8 @@ private module Subpaths {
36863690
*/
36873691
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
36883692
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
3689-
arg.getASuccessor() = par and
3690-
arg.getASuccessor() = out and
3693+
pragma[only_bind_into](arg).getASuccessor() = par and
3694+
pragma[only_bind_into](arg).getASuccessor() = out and
36913695
subpaths03(arg, p, ret, o, apout) and
36923696
par.getNodeEx() = p and
36933697
out.getNodeEx() = o and

0 commit comments

Comments
 (0)