Skip to content

Commit 6f34c32

Browse files
authored
Merge branch 'github:main' into amammad-python-WebAppsConstatntSecretKeys
2 parents a988ccb + 634c838 commit 6f34c32

File tree

171 files changed

+4581
-631
lines changed

Some content is hidden

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

171 files changed

+4581
-631
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: "Check implicit this warnings"
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
paths:
7+
- "**qlpack.yml"
8+
branches:
9+
- main
10+
- "rc/*"
11+
12+
jobs:
13+
check:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v3
17+
- name: Check that implicit this warnings is enabled for all packs
18+
shell: bash
19+
run: |
20+
EXIT_CODE=0
21+
packs="$(find . -iname 'qlpack.yml')"
22+
for pack_file in ${packs}; do
23+
option="$(yq '.warnOnImplicitThis' ${pack_file})"
24+
if [ "${option}" != "true" ]; then
25+
echo "::error file=${pack_file}::warnOnImplicitThis property must be set to 'true' for pack ${pack_file}"
26+
EXIT_CODE=1
27+
fi
28+
done
29+
exit "${EXIT_CODE}"

.pre-commit-config.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ repos:
55
rev: v3.2.0
66
hooks:
77
- id: trailing-whitespace
8-
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
8+
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
99
- id: end-of-file-fixer
10-
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
10+
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)|.*\.patch
1111

1212
- repo: https://github.com/pre-commit/mirrors-clang-format
1313
rev: v13.0.1
@@ -21,6 +21,11 @@ repos:
2121
- id: autopep8
2222
files: ^misc/codegen/.*\.py
2323

24+
- repo: https://github.com/warchant/pre-commit-buildifier
25+
rev: 0.0.2
26+
hooks:
27+
- id: buildifier
28+
2429
- repo: local
2530
hooks:
2631
- id: codeql-format

cpp/downgrades/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ name: codeql/cpp-downgrades
22
groups: cpp
33
downgrades: .
44
library: true
5+
warnOnImplicitThis: true

cpp/ql/examples/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ groups:
44
- examples
55
dependencies:
66
codeql/cpp-all: ${workspace}
7+
warnOnImplicitThis: true

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 130 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,11 @@ private class PrimaryArgumentNode extends ArgumentNode, OperandNode {
321321

322322
private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode {
323323
override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) {
324-
this.getCallInstruction() = dfCall and
325-
pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and
326-
super.hasAddressOperandAndIndirectionIndex(_, pos.(IndirectionPosition).getIndirectionIndex())
324+
exists(int indirectionIndex |
325+
pos = TIndirectionPosition(argumentIndex, pragma[only_bind_into](indirectionIndex)) and
326+
this.getCallInstruction() = dfCall and
327+
super.hasAddressOperandAndIndirectionIndex(_, pragma[only_bind_into](indirectionIndex))
328+
)
327329
}
328330
}
329331

@@ -651,13 +653,16 @@ predicate jumpStep(Node n1, Node n2) {
651653
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
652654
* Thus, `node2` references an object with a field `f` that contains the
653655
* value of `node1`.
656+
*
657+
* The boolean `certain` is true if the destination address does not involve
658+
* any pointer arithmetic, and false otherwise.
654659
*/
655-
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
660+
predicate storeStepImpl(Node node1, Content c, PostFieldUpdateNode node2, boolean certain) {
656661
exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store |
657662
nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and
658663
node2.getIndirectionIndex() = 1 and
659664
numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(),
660-
numberOfLoads)
665+
numberOfLoads, certain)
661666
|
662667
exists(FieldContent fc | fc = c |
663668
fc.getField() = node2.getUpdatedField() and
@@ -671,35 +676,51 @@ predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
671676
)
672677
}
673678

679+
/**
680+
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
681+
* Thus, `node2` references an object with a field `f` that contains the
682+
* value of `node1`.
683+
*/
684+
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
685+
storeStepImpl(node1, c, node2, _)
686+
}
687+
674688
/**
675689
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
676690
* operations and exactly `n` `LoadInstruction` operations.
677691
*/
678-
private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand operandTo, int ind) {
692+
private predicate numberOfLoadsFromOperandRec(
693+
Operand operandFrom, Operand operandTo, int ind, boolean certain
694+
) {
679695
exists(Instruction load | Ssa::isDereference(load, operandFrom) |
680-
operandTo = operandFrom and ind = 0
696+
operandTo = operandFrom and ind = 0 and certain = true
681697
or
682-
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1)
698+
numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1, certain)
683699
)
684700
or
685-
exists(Operand op, Instruction instr |
701+
exists(Operand op, Instruction instr, boolean isPointerArith, boolean certain0 |
686702
instr = op.getDef() and
687-
conversionFlow(operandFrom, instr, _, _) and
688-
numberOfLoadsFromOperand(op, operandTo, ind)
703+
conversionFlow(operandFrom, instr, isPointerArith, _) and
704+
numberOfLoadsFromOperand(op, operandTo, ind, certain0)
705+
|
706+
if isPointerArith = true then certain = false else certain = certain0
689707
)
690708
}
691709

692710
/**
693711
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
694712
* operations and exactly `n` `LoadInstruction` operations.
695713
*/
696-
private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n) {
697-
numberOfLoadsFromOperandRec(operandFrom, operandTo, n)
714+
private predicate numberOfLoadsFromOperand(
715+
Operand operandFrom, Operand operandTo, int n, boolean certain
716+
) {
717+
numberOfLoadsFromOperandRec(operandFrom, operandTo, n, certain)
698718
or
699719
not Ssa::isDereference(_, operandFrom) and
700720
not conversionFlow(operandFrom, _, _, _) and
701721
operandFrom = operandTo and
702-
n = 0
722+
n = 0 and
723+
certain = true
703724
}
704725

705726
// Needed to join on both an operand and an index at the same time.
@@ -729,7 +750,7 @@ predicate readStep(Node node1, Content c, Node node2) {
729750
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
730751
// in `storeStep`.
731752
nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and
732-
numberOfLoadsFromOperand(fa1, operand, numberOfLoads)
753+
numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _)
733754
|
734755
exists(FieldContent fc | fc = c |
735756
fc.getField() = fa1.getField() and
@@ -747,7 +768,33 @@ predicate readStep(Node node1, Content c, Node node2) {
747768
* Holds if values stored inside content `c` are cleared at node `n`.
748769
*/
749770
predicate clearsContent(Node n, Content c) {
750-
none() // stub implementation
771+
n =
772+
any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun)
773+
.getPreUpdateNode() and
774+
(
775+
// The crement operations and pointer addition and subtraction self-assign. We do not
776+
// want to clear the contents if it is indirectly pointed at by any of these operations,
777+
// as part of the contents might still be accessible afterwards. If there is no such
778+
// indirection clearing the contents is safe.
779+
not exists(Operand op, Cpp::Operation p |
780+
n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and
781+
(
782+
p instanceof Cpp::AssignPointerAddExpr or
783+
p instanceof Cpp::AssignPointerSubExpr or
784+
p instanceof Cpp::CrementOperation
785+
)
786+
|
787+
p.getAnOperand() = op.getUse().getAst()
788+
)
789+
or
790+
forex(PostUpdateNode pun, Content d |
791+
pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and
792+
storeStepImpl(_, d, pun, true) and
793+
pun.getPreUpdateNode() = n
794+
|
795+
c.getIndirectionIndex() = d.getIndirectionIndex()
796+
)
797+
)
751798
}
752799

753800
/**
@@ -809,7 +856,73 @@ class DataFlowCall extends CallInstruction {
809856
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
810857
}
811858

812-
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
859+
module IsUnreachableInCall {
860+
private import semmle.code.cpp.ir.ValueNumbering
861+
private import semmle.code.cpp.controlflow.IRGuards as G
862+
863+
private class ConstantIntegralTypeArgumentNode extends PrimaryArgumentNode {
864+
int value;
865+
866+
ConstantIntegralTypeArgumentNode() {
867+
value = op.getDef().(IntegerConstantInstruction).getValue().toInt()
868+
}
869+
870+
int getValue() { result = value }
871+
}
872+
873+
pragma[nomagic]
874+
private predicate ensuresEq(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
875+
any(G::IRGuardCondition guard).ensuresEq(left, right, k, block, areEqual)
876+
}
877+
878+
pragma[nomagic]
879+
private predicate ensuresLt(Operand left, Operand right, int k, IRBlock block, boolean areEqual) {
880+
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
881+
}
882+
883+
predicate isUnreachableInCall(Node n, DataFlowCall call) {
884+
exists(
885+
DirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
886+
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
887+
|
888+
// arg flows into `paramNode`
889+
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
890+
left = constant.getAUse() and
891+
right = valueNumber(paramNode.getInstruction()).getAUse() and
892+
block = n.getBasicBlock()
893+
|
894+
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
895+
exists(boolean areEqual |
896+
ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
897+
pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
898+
|
899+
// this block ensures that left = right + k, but it holds that `left != right + k`
900+
areEqual = true and
901+
constant.getValue().toInt() != arg.getValue() + k
902+
or
903+
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
904+
areEqual = false and
905+
constant.getValue().toInt() = arg.getValue() + k
906+
)
907+
or
908+
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
909+
exists(boolean isLessThan |
910+
ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
911+
pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
912+
|
913+
isLessThan = true and
914+
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
915+
constant.getValue().toInt() >= arg.getValue() + k
916+
or
917+
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
918+
isLessThan = false and
919+
constant.getValue().toInt() < arg.getValue() + k
920+
)
921+
)
922+
}
923+
}
924+
925+
import IsUnreachableInCall
813926

814927
int accessPathLimit() { result = 5 }
815928

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1832,6 +1832,20 @@ class Content extends TContent {
18321832
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
18331833
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
18341834
}
1835+
1836+
/** Gets the indirection index of this `Content`. */
1837+
abstract int getIndirectionIndex();
1838+
1839+
/**
1840+
* INTERNAL: Do not use.
1841+
*
1842+
* Holds if a write to this `Content` implies that `c` is
1843+
* also cleared.
1844+
*
1845+
* For example, a write to a field `f` implies that any content of
1846+
* the form `*f` is also cleared.
1847+
*/
1848+
abstract predicate impliesClearOf(Content c);
18351849
}
18361850

18371851
/** A reference through a non-union instance field. */
@@ -1849,10 +1863,21 @@ class FieldContent extends Content, TFieldContent {
18491863

18501864
Field getField() { result = f }
18511865

1866+
/** Gets the indirection index of this `FieldContent`. */
18521867
pragma[inline]
1853-
int getIndirectionIndex() {
1868+
override int getIndirectionIndex() {
18541869
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
18551870
}
1871+
1872+
override predicate impliesClearOf(Content c) {
1873+
exists(FieldContent fc |
1874+
fc = c and
1875+
fc.getField() = f and
1876+
// If `this` is `f` then `c` is cleared if it's of the
1877+
// form `*f`, `**f`, etc.
1878+
fc.getIndirectionIndex() >= indirectionIndex
1879+
)
1880+
}
18561881
}
18571882

18581883
/** A reference through an instance field of a union. */
@@ -1877,9 +1902,21 @@ class UnionContent extends Content, TUnionContent {
18771902

18781903
/** Gets the indirection index of this `UnionContent`. */
18791904
pragma[inline]
1880-
int getIndirectionIndex() {
1905+
override int getIndirectionIndex() {
18811906
pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex)
18821907
}
1908+
1909+
override predicate impliesClearOf(Content c) {
1910+
exists(UnionContent uc |
1911+
uc = c and
1912+
uc.getUnion() = u and
1913+
// If `this` is `u` then `c` is cleared if it's of the
1914+
// form `*u`, `**u`, etc. (and we ignore `bytes` because
1915+
// we know the entire union is overwritten because it's a
1916+
// union).
1917+
uc.getIndirectionIndex() >= indirectionIndex
1918+
)
1919+
}
18831920
}
18841921

18851922
/**

cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionP
7070
// Conservatively assume that every edge is a back edge if we don't have dominance information.
7171
(
7272
phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or
73-
irreducibleSccEdge(phi.getBasicBlock(), edge.getOrigBlock()) or
73+
irreducibleSccEdge(edge.getOrigBlock(), phi.getBasicBlock()) or
7474
not edge.getOrigBlock().hasDominanceInformation()
7575
)
7676
}

cpp/ql/src/Security/CWE/CWE-119/OverrunWriteProductFlow.ql

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ module ValidState {
120120

121121
predicate isBarrier(DataFlow::Node node, FlowState state) { none() }
122122

123+
predicate isBarrierOut(DataFlow::Node node) {
124+
node = any(DataFlow::SsaPhiNode phi).getAnInput(true)
125+
}
126+
123127
predicate isAdditionalFlowStep(
124128
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
125129
) {
@@ -233,7 +237,8 @@ module StringSizeConfig implements ProductFlow::StateConfigSig {
233237
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
234238
// to the size of the allocation. This state is then checked in `isSinkPair`.
235239
exists(state1) and
236-
hasSize(bufSource.asConvertedExpr(), sizeSource, state2)
240+
hasSize(bufSource.asConvertedExpr(), sizeSource, state2) and
241+
validState(sizeSource, state2)
237242
}
238243

239244
predicate isSinkPair(

cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ predicate isInvalidPointerDerefSink2(DataFlow::Node sink, Instruction i, string
8080

8181
predicate arrayTypeCand(ArrayType arrayType) {
8282
any(Variable v).getUnspecifiedType() = arrayType and
83-
exists(arrayType.getArraySize())
83+
exists(arrayType.getByteSize())
8484
}
8585

86-
pragma[nomagic]
87-
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int arraySize) {
86+
bindingset[baseTypeSize]
87+
pragma[inline_late]
88+
predicate arrayTypeHasSizes(ArrayType arr, int baseTypeSize, int size) {
8889
arrayTypeCand(arr) and
89-
arr.getBaseType().getSize() = baseTypeSize and
90-
arr.getArraySize() = arraySize
90+
arr.getByteSize() / baseTypeSize = size
9191
}
9292

9393
bindingset[pai]

0 commit comments

Comments
 (0)