Skip to content

Commit 95e030f

Browse files
committed
Rust: Detect constant accesses and perform very limited constant propagation.
1 parent 8155ff7 commit 95e030f

3 files changed

Lines changed: 27 additions & 18 deletions

File tree

rust/ql/lib/codeql/rust/security/HardcodedCryptographicValueExtensions.qll

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,27 @@ module HardcodedCryptographicValue {
6262
abstract class Barrier extends DataFlow::Node { }
6363

6464
/**
65-
* A literal, considered as a flow source.
65+
* Holds if `e` is a literal or a combination of literals that is constant.
6666
*/
67-
private class LiteralSource extends Source {
68-
LiteralSource() { this.asExpr() instanceof LiteralExpr }
67+
private predicate isConstant(Expr e) {
68+
e instanceof LiteralExpr // e.g. `0`
69+
or
70+
e.(ArrayListExpr).getExpr(_) instanceof LiteralExpr // e.g. `[0, 0, 0, 0]`
71+
or
72+
e.(ArrayRepeatExpr).getRepeatOperand() instanceof LiteralExpr // e.g. `[0; 10]`
73+
or
74+
e instanceof ConstAccess // e.g. `u64::MAX`
75+
or
76+
// e.g. `1 << 4`
77+
isConstant(e.(BinaryExpr).getLhs()) and
78+
isConstant(e.(BinaryExpr).getRhs())
6979
}
7080

7181
/**
72-
* An array initialized from a list of literals, considered as a single flow source. For example:
73-
* ```
74-
* [0, 0, 0, 0]
75-
* [0; 10]
76-
* ```
82+
* A constant, considered as a flow source.
7783
*/
78-
private class ArrayListSource extends Source {
79-
ArrayListSource() {
80-
this.asExpr().(ArrayListExpr).getExpr(_) instanceof LiteralExpr or
81-
this.asExpr().(ArrayRepeatExpr).getRepeatOperand() instanceof LiteralExpr
82-
}
84+
private class ConstantSource extends Source {
85+
ConstantSource() { isConstant(this.asExpr()) }
8386
}
8487

8588
/**
@@ -165,9 +168,9 @@ module HardcodedCryptographicValue {
165168
private class ArithmeticOperationBarrier extends Barrier {
166169
ArithmeticOperationBarrier() {
167170
// binary operations (e.g. `a + b`, `a ^ b`)
168-
this.asExpr() instanceof BinaryArithmeticOperation
171+
this.asExpr() = any(BinaryArithmeticOperation a).getAnOperand()
169172
or
170-
this.asExpr() instanceof BinaryBitwiseOperation
173+
this.asExpr() = any(BinaryBitwiseOperation a).getAnOperand()
171174
or
172175
// compound assignments (e.g. `a += b`, `a ^= b`)
173176
this.asExpr() = any(AssignArithmeticOperation a).getAnOperand()

rust/ql/test/query-tests/security/CWE-798/HardcodedCryptographicValue.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
| test_heuristic.rs:64:20:64:27 | [0u8; 16] | test_heuristic.rs:64:20:64:27 | [0u8; 16] | test_heuristic.rs:64:19:64:27 | &... | This hard-coded value is used as $@. | test_heuristic.rs:64:19:64:27 | &... | a nonce |
1616
| test_heuristic.rs:65:31:65:38 | [0u8; 16] | test_heuristic.rs:65:31:65:38 | [0u8; 16] | test_heuristic.rs:65:30:65:38 | &... | This hard-coded value is used as $@. | test_heuristic.rs:65:30:65:38 | &... | a salt |
1717
| test_heuristic.rs:67:22:67:22 | 0 | test_heuristic.rs:67:22:67:22 | 0 | test_heuristic.rs:67:22:67:22 | 0 | This hard-coded value is used as $@. | test_heuristic.rs:67:22:67:22 | 0 | a salt |
18+
| test_heuristic.rs:71:22:71:27 | ... << ... | test_heuristic.rs:71:22:71:27 | ... << ... | test_heuristic.rs:71:22:71:27 | ... << ... | This hard-coded value is used as $@. | test_heuristic.rs:71:22:71:27 | ... << ... | a salt |
19+
| test_heuristic.rs:72:22:72:29 | ...::MAX | test_heuristic.rs:72:22:72:29 | ...::MAX | test_heuristic.rs:72:22:72:29 | ...::MAX | This hard-coded value is used as $@. | test_heuristic.rs:72:22:72:29 | ...::MAX | a salt |
20+
| test_heuristic.rs:73:22:73:33 | ... / ... | test_heuristic.rs:73:22:73:33 | ... / ... | test_heuristic.rs:73:22:73:33 | ... / ... | This hard-coded value is used as $@. | test_heuristic.rs:73:22:73:33 | ... / ... | a salt |
1821
edges
1922
| test_cipher.rs:18:9:18:14 | const1 [&ref] | test_cipher.rs:19:73:19:78 | const1 [&ref] | provenance | |
2023
| test_cipher.rs:18:28:18:36 | &... [&ref] | test_cipher.rs:18:9:18:14 | const1 [&ref] | provenance | |
@@ -164,4 +167,7 @@ nodes
164167
| test_heuristic.rs:65:30:65:38 | &... | semmle.label | &... |
165168
| test_heuristic.rs:65:31:65:38 | [0u8; 16] | semmle.label | [0u8; 16] |
166169
| test_heuristic.rs:67:22:67:22 | 0 | semmle.label | 0 |
170+
| test_heuristic.rs:71:22:71:27 | ... << ... | semmle.label | ... << ... |
171+
| test_heuristic.rs:72:22:72:29 | ...::MAX | semmle.label | ...::MAX |
172+
| test_heuristic.rs:73:22:73:33 | ... / ... | semmle.label | ... / ... |
167173
subpaths

rust/ql/test/query-tests/security/CWE-798/test_heuristic.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ fn test(var_string: &str, var_data: &[u8;16], var_u64: u64) {
6868
mc2.set_salt_u64(var_u64);
6969
mc2.set_salt_u64(var_u64 + 1);
7070
mc2.set_salt_u64((var_u64 << 32) ^ (var_u64 & 0xFFFFFFFF));
71-
mc2.set_salt_u64(1 << 4); // $ MISSING: Alert[rust/hard-coded-cryptographic-value]
72-
mc2.set_salt_u64(u64::MAX); // $ MISSING: Alert[rust/hard-coded-cryptographic-value]
73-
mc2.set_salt_u64(u64::MAX / 4); // $ MISSING: Alert[rust/hard-coded-cryptographic-value]
71+
mc2.set_salt_u64(1 << 4); // $ Alert[rust/hard-coded-cryptographic-value]
72+
mc2.set_salt_u64(u64::MAX); // $ Alert[rust/hard-coded-cryptographic-value]
73+
mc2.set_salt_u64(u64::MAX / 4); // $ Alert[rust/hard-coded-cryptographic-value]
7474

7575
let mut key1 = "foo".to_string(); // $ MISSING: Alert[rust/hard-coded-cryptographic-value]
7676
key1 += "bar"; // $ MISSING: Alert[rust/hard-coded-cryptographic-value]

0 commit comments

Comments
 (0)