Skip to content

Commit 9351cd4

Browse files
committed
Merge remote-tracking branch 'githubsemmle/master' into HEAD
2 parents e27a699 + a2827e9 commit 9351cd4

File tree

71 files changed

+957
-288
lines changed

Some content is hidden

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

71 files changed

+957
-288
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Improvements to C/C++ analysis
2+
3+
The following changes in version 1.24 affect C/C++ analysis in all applications.
4+
5+
## General improvements
6+
7+
## New queries
8+
9+
| **Query** | **Tags** | **Purpose** |
10+
|-----------------------------|-----------|--------------------------------------------------------------------|
11+
12+
## Changes to existing queries
13+
14+
| **Query** | **Expected impact** | **Change** |
15+
|----------------------------|------------------------|------------------------------------------------------------------|
16+
| No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. |
17+
18+
## Changes to libraries
19+
20+
*

change-notes/1.24/analysis-javascript.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- [react](https://www.npmjs.com/package/react)
77
- [Handlebars](https://www.npmjs.com/package/handlebars)
88

9+
- Imports with the `.js` extension can now be resolved to a TypeScript file,
10+
when the import refers to a file generated by TypeScript.
11+
912
## New queries
1013

1114
| **Query** | **Tags** | **Purpose** |

config/identical-files.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@
143143
"cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll",
144144
"csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll"
145145
],
146+
"IR SSASanity": [
147+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSASanity.qll",
148+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSASanity.qll",
149+
"csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSASanity.qll"
150+
],
146151
"C++ IR InstructionImports": [
147152
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionImports.qll",
148153
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/InstructionImports.qll",

cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,28 @@
1616

1717
import cpp
1818
import semmle.code.cpp.dataflow.DataFlow
19-
import semmle.code.cpp.models.implementations.Memcpy
19+
import semmle.code.cpp.models.interfaces.ArrayFunction
2020

2121
class MallocCall extends FunctionCall {
2222
MallocCall() { this.getTarget().hasGlobalOrStdName("malloc") }
2323

24-
Expr getAllocatedSize() {
25-
if this.getArgument(0) instanceof VariableAccess
26-
then
27-
exists(LocalScopeVariable v, ControlFlowNode def |
28-
definitionUsePair(v, def, this.getArgument(0)) and
29-
exprDefinition(v, def, result)
30-
)
31-
else result = this.getArgument(0)
32-
}
24+
Expr getAllocatedSize() { result = this.getArgument(0) }
3325
}
3426

3527
predicate terminationProblem(MallocCall malloc, string msg) {
36-
malloc.getAllocatedSize() instanceof StrlenCall and
37-
not exists(FunctionCall fc, MemcpyFunction memcpy, int ix |
38-
DataFlow::localExprFlow(malloc, fc.getArgument(ix)) and
39-
fc.getTarget() = memcpy and
40-
memcpy.hasArrayOutput(ix)
28+
// malloc(strlen(...))
29+
exists(StrlenCall strlen | DataFlow::localExprFlow(strlen, malloc.getAllocatedSize())) and
30+
// flows into a null-terminated string function
31+
exists(ArrayFunction af, FunctionCall fc, int arg |
32+
DataFlow::localExprFlow(malloc, fc.getArgument(arg)) and
33+
fc.getTarget() = af and
34+
(
35+
// null terminated string
36+
af.hasArrayWithNullTerminator(arg)
37+
or
38+
// likely a null terminated string (such as `strcpy`, `strcat`)
39+
af.hasArrayWithUnknownSize(arg)
40+
)
4141
) and
4242
msg = "This allocation does not include space to null-terminate the string."
4343
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var
1313
}
1414

1515
/**
16-
* Represents a variable referenced by the IR for a function. The variable may
17-
* be a user-declared variable (`IRUserVariable`) or a temporary variable
18-
* generated by the AST-to-IR translation (`IRTempVariable`).
16+
* A variable referenced by the IR for a function. The variable may be a user-declared variable
17+
* (`IRUserVariable`) or a temporary variable generated by the AST-to-IR translation
18+
* (`IRTempVariable`).
1919
*/
20-
abstract class IRVariable extends TIRVariable {
20+
class IRVariable extends TIRVariable {
2121
Language::Function func;
2222

23-
abstract string toString();
23+
IRVariable() {
24+
this = TIRUserVariable(_, _, func) or
25+
this = TIRTempVariable(func, _, _, _) or
26+
this = TIRStringLiteral(func, _, _, _)
27+
}
28+
29+
string toString() { none() }
2430

2531
/**
2632
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -41,19 +47,19 @@ abstract class IRVariable extends TIRVariable {
4147
/**
4248
* Gets the type of the variable.
4349
*/
44-
abstract Language::LanguageType getLanguageType();
50+
Language::LanguageType getLanguageType() { none() }
4551

4652
/**
4753
* Gets the AST node that declared this variable, or that introduced this
4854
* variable as part of the AST-to-IR translation.
4955
*/
50-
abstract Language::AST getAST();
56+
Language::AST getAST() { none() }
5157

5258
/**
5359
* Gets an identifier string for the variable. This identifier is unique
5460
* within the function.
5561
*/
56-
abstract string getUniqueId();
62+
string getUniqueId() { none() }
5763

5864
/**
5965
* Gets the source location of this variable.
@@ -72,7 +78,7 @@ abstract class IRVariable extends TIRVariable {
7278
}
7379

7480
/**
75-
* Represents a user-declared variable referenced by the IR for a function.
81+
* A user-declared variable referenced by the IR for a function.
7682
*/
7783
class IRUserVariable extends IRVariable, TIRUserVariable {
7884
Language::Variable var;
@@ -97,20 +103,34 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
97103
}
98104

99105
/**
100-
* Represents a variable (user-declared or temporary) that is allocated on the
101-
* stack. This includes all parameters, non-static local variables, and
102-
* temporary variables.
106+
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
107+
* parameters, non-static local variables, and temporary variables.
103108
*/
104-
abstract class IRAutomaticVariable extends IRVariable { }
109+
class IRAutomaticVariable extends IRVariable {
110+
IRAutomaticVariable() {
111+
exists(Language::Variable var |
112+
this = TIRUserVariable(var, _, func) and
113+
Language::isVariableAutomatic(var)
114+
)
115+
or
116+
this = TIRTempVariable(func, _, _, _)
117+
}
118+
}
105119

120+
/**
121+
* A user-declared variable that is allocated on the stack. This includes all parameters and
122+
* non-static local variables.
123+
*/
106124
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
107125
override Language::AutomaticVariable var;
108126

109-
IRAutomaticUserVariable() { Language::isVariableAutomatic(var) }
110-
111127
final override Language::AutomaticVariable getVariable() { result = var }
112128
}
113129

130+
/**
131+
* A user-declared variable that is not allocated on the stack. This includes all global variables,
132+
* namespace-scope variables, static fields, and static local variables.
133+
*/
114134
class IRStaticUserVariable extends IRUserVariable {
115135
override Language::StaticVariable var;
116136

@@ -119,10 +139,19 @@ class IRStaticUserVariable extends IRUserVariable {
119139
final override Language::StaticVariable getVariable() { result = var }
120140
}
121141

122-
abstract class IRGeneratedVariable extends IRVariable {
142+
/**
143+
* A variable that is not user-declared. This includes temporary variables generated as part of IR
144+
* construction, as well as string literals.
145+
*/
146+
class IRGeneratedVariable extends IRVariable {
123147
Language::AST ast;
124148
Language::LanguageType type;
125149

150+
IRGeneratedVariable() {
151+
this = TIRTempVariable(func, ast, _, type) or
152+
this = TIRStringLiteral(func, ast, type, _)
153+
}
154+
126155
final override Language::LanguageType getLanguageType() { result = type }
127156

128157
final override Language::AST getAST() { result = ast }
@@ -144,6 +173,11 @@ IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
144173
result.getTag() = tag
145174
}
146175

176+
/**
177+
* A temporary variable introduced by IR construction. The most common examples are the variable
178+
* generated to hold the return value of afunction, or the variable generated to hold the result of
179+
* a condition operator (`a ? b : c`).
180+
*/
147181
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
148182
TempVariableTag tag;
149183

@@ -158,18 +192,28 @@ class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVa
158192
override string getBaseString() { result = "#temp" }
159193
}
160194

195+
/**
196+
* A temporary variable generated to hold the return value of a function.
197+
*/
161198
class IRReturnVariable extends IRTempVariable {
162199
IRReturnVariable() { tag = ReturnValueTempVar() }
163200

164201
final override string toString() { result = "#return" }
165202
}
166203

204+
/**
205+
* A temporary variable generated to hold the exception thrown by a `ThrowValue` instruction.
206+
*/
167207
class IRThrowVariable extends IRTempVariable {
168208
IRThrowVariable() { tag = ThrowTempVar() }
169209

170210
override string getBaseString() { result = "#throw" }
171211
}
172212

213+
/**
214+
* A variable generated to represent the contents of a string literal. This variable acts much like
215+
* a read-only global variable.
216+
*/
173217
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
174218
Language::StringLiteral literal;
175219

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,21 @@ module InstructionSanity {
9494
/**
9595
* Holds if instruction `instr` has multiple operands with tag `tag`.
9696
*/
97-
query predicate duplicateOperand(Instruction instr, OperandTag tag) {
98-
strictcount(NonPhiOperand operand |
99-
operand = instr.getAnOperand() and
100-
operand.getOperandTag() = tag
101-
) > 1 and
102-
not tag instanceof UnmodeledUseOperandTag
97+
query predicate duplicateOperand(
98+
Instruction instr, string message, IRFunction func, string funcText
99+
) {
100+
exists(OperandTag tag, int operandCount |
101+
operandCount = strictcount(NonPhiOperand operand |
102+
operand = instr.getAnOperand() and
103+
operand.getOperandTag() = tag
104+
) and
105+
operandCount > 1 and
106+
not tag instanceof UnmodeledUseOperandTag and
107+
message = "Instruction has " + operandCount + " operands with tag '" + tag.toString() + "'" +
108+
" in function '$@'." and
109+
func = instr.getEnclosingIRFunction() and
110+
funcText = Language::getIdentityString(func.getFunction())
111+
)
103112
}
104113

105114
/**

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,6 @@ private import semmle.code.cpp.models.interfaces.Alias
66

77
private class IntValue = Ints::IntValue;
88

9-
/**
10-
* Converts the bit count in `bits` to a byte count and a bit count in the form
11-
* bytes:bits.
12-
*/
13-
bindingset[bits]
14-
string bitsToBytesAndBits(int bits) { result = (bits / 8).toString() + ":" + (bits % 8).toString() }
15-
16-
/**
17-
* Gets a printable string for a bit offset with possibly unknown value.
18-
*/
19-
bindingset[bitOffset]
20-
string getBitOffsetString(IntValue bitOffset) {
21-
if Ints::hasValue(bitOffset)
22-
then
23-
if bitOffset >= 0
24-
then result = "+" + bitsToBytesAndBits(bitOffset)
25-
else result = "-" + bitsToBytesAndBits(Ints::neg(bitOffset))
26-
else result = "+?"
27-
}
28-
299
/**
3010
* Gets the offset of field `field` in bits.
3111
*/
@@ -137,7 +117,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) {
137117
or
138118
// Adding an integer to or subtracting an integer from a pointer propagates
139119
// the address with an offset.
140-
bitOffset = getPointerBitOffset(instr.(PointerOffsetInstruction))
120+
exists(PointerOffsetInstruction ptrOffset |
121+
ptrOffset = instr and
122+
operand = ptrOffset.getLeftOperand() and
123+
bitOffset = getPointerBitOffset(ptrOffset)
124+
)
141125
or
142126
// Computing a field address from a pointer propagates the address plus the
143127
// offset of the field.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,3 +865,17 @@ private module CachedForDebugging {
865865
result.getTag() = var.getTag()
866866
}
867867
}
868+
869+
module SSASanity {
870+
query predicate multipleOperandMemoryLocations(
871+
OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText
872+
) {
873+
exists(int locationCount |
874+
locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and
875+
locationCount > 1 and
876+
func = operand.getEnclosingIRFunction() and
877+
funcText = Language::getIdentityString(func.getFunction()) and
878+
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
879+
)
880+
}
881+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* @name Aliased SSA Sanity Check
3+
* @description Performs sanity checks on the SSA construction. This query should have no results.
4+
* @kind table
5+
* @id cpp/aliased-ssa-sanity-check
6+
*/
7+
8+
import SSASanity
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
private import SSAConstruction as SSA
2+
import SSA::SSASanity

0 commit comments

Comments
 (0)