Skip to content

Commit 68a19d7

Browse files
authored
Merge branch 'master' into taintedmalloc
2 parents a7e349c + fcf04ab commit 68a19d7

File tree

56 files changed

+1186
-724
lines changed

Some content is hidden

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

56 files changed

+1186
-724
lines changed

change-notes/1.21/analysis-cpp.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
|----------------------------|------------------------|------------------------------------------------------------------|
1414
| Mismatching new/free or malloc/delete (`cpp/new-free-mismatch`) | Fewer false positive results | Fixed an issue where functions were being identified as allocation functions inappropriately. Also affects `cpp/new-array-delete-mismatch` and `cpp/new-delete-array-mismatch`. |
1515
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | More correct results | This query has been reworked so that it can find a wider variety of results. |
16+
| Memory may not be freed (`cpp/memory-may-not-be-freed`) | More correct results | Support added for more Microsoft-specific allocation functions, including `LocalAlloc`, `GlobalAlloc`, `HeapAlloc` and `CoTaskMemAlloc`. |
17+
| Memory is never freed (`cpp/memory-never-freed`) | More correct results | Support added for more Microsoft-specific allocation functions, including `LocalAlloc`, `GlobalAlloc`, `HeapAlloc` and `CoTaskMemAlloc`. |
1618
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | Resource allocation and deallocation functions are now determined more accurately. |
19+
| Comparison result is always the same | Fewer false positive results | The range analysis library is now more conservative about floating point values being possibly `NaN` |
1720

1821
## Changes to QL libraries
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Improvements to C# analysis
2+
3+
## Changes to existing queries
4+
5+
| **Query** | **Expected impact** | **Change** |
6+
|------------------------------|------------------------|-----------------------------------|
7+
8+
9+
## Changes to code extraction
10+
11+
* Named attribute arguments are now extracted.
12+
13+
## Changes to QL libraries
14+
15+
* The class `Attribute` has two new predicates: `getConstructorArgument()` and `getNamedArgument()`. The first predicate returns arguments to the underlying constructor call and the latter returns named arguments for initializing fields and properties.
16+
17+
## Changes to autobuilder

change-notes/1.21/analysis-javascript.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
| **Query** | **Expected impact** | **Change** |
1919
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
2020
| Expression has no effect | Fewer false-positive results | This rule now treats uses of `Object.defineProperty` more conservatively. |
21-
| Useless assignment to property | Fewer false-positive results | This rule now ignore reads of additional getters. |
21+
| Useless assignment to property | Fewer false-positive results | This rule now ignores reads of additional getters. |
2222
| Arbitrary file write during zip extraction ("Zip Slip") | More results | This rule now considers more libraries, including tar as well as zip. |
23+
| Client-side URL redirect | Fewer false-positive results | This rule now treats URLs as safe in more cases where the hostname cannot be tampered with. |
24+
| Server-side URL redirect | Fewer false-positive results | This rule now treats URLs as safe in more cases where the hostname cannot be tampered with. |
2325

2426
## Changes to QL libraries

cpp/ql/src/Likely Bugs/Arithmetic/PointlessComparison.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* readability
1313
*/
1414
import cpp
15+
private import semmle.code.cpp.commons.Exclusions
1516
private import semmle.code.cpp.rangeanalysis.PointlessComparison
1617
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
1718
import UnsignedGEZero
@@ -31,6 +32,7 @@ from
3132
where
3233
not cmp.isInMacroExpansion() and
3334
not cmp.isFromTemplateInstantiation(_) and
35+
not functionContainsDisabledCode(cmp.getEnclosingFunction()) and
3436
reachablePointlessComparison(cmp, left, right, value, ss) and
3537

3638
// a comparison between an enum and zero is always valid because whether

cpp/ql/src/Likely Bugs/Likely Typos/ExprHasNoEffect.ql

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* external/cwe/cwe-561
1212
*/
1313
import cpp
14+
private import semmle.code.cpp.commons.Exclusions
1415

1516
class PureExprInVoidContext extends ExprInVoidContext {
1617
PureExprInVoidContext() { this.isPure() }
@@ -23,71 +24,29 @@ predicate accessInInitOfForStmt(Expr e) {
2324
s.getExpr() = e)
2425
}
2526

26-
/**
27-
* Holds if the preprocessor branch `pbd` is on line `pbdStartLine` in file `file`.
28-
*/
29-
predicate pbdLocation(PreprocessorBranchDirective pbd, string file, int pbdStartLine) {
30-
pbd.getLocation().hasLocationInfo(file, pbdStartLine, _, _, _)
31-
}
32-
33-
/**
34-
* Holds if the body of the function `f` is on lines `fBlockStartLine` to `fBlockEndLine` in file `file`.
35-
*/
36-
predicate functionLocation(Function f, string file, int fBlockStartLine, int fBlockEndLine) {
37-
f.getBlock().getLocation().hasLocationInfo(file, fBlockStartLine, _, fBlockEndLine, _)
38-
}
3927
/**
4028
* Holds if the function `f`, or a function called by it, contains
4129
* code excluded by the preprocessor.
4230
*/
43-
predicate containsDisabledCode(Function f) {
44-
// `f` contains a preprocessor branch that was not taken
45-
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int fBlockStartLine, int fBlockEndLine |
46-
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
47-
pbdLocation(pbd, file, pbdStartLine) and
48-
pbdStartLine <= fBlockEndLine and
49-
pbdStartLine >= fBlockStartLine and
50-
(
51-
pbd.(PreprocessorBranch).wasNotTaken() or
52-
53-
// an else either was not taken, or it's corresponding branch
54-
// was not taken.
55-
pbd instanceof PreprocessorElse
56-
)
57-
) or
58-
31+
predicate functionContainsDisabledCodeRecursive(Function f) {
32+
functionContainsDisabledCode(f) or
5933
// recurse into function calls
6034
exists(FunctionCall fc |
6135
fc.getEnclosingFunction() = f and
62-
containsDisabledCode(fc.getTarget())
36+
functionContainsDisabledCodeRecursive(fc.getTarget())
6337
)
6438
}
6539

66-
6740
/**
6841
* Holds if the function `f`, or a function called by it, is inside a
6942
* preprocessor branch that may have code in another arm
7043
*/
71-
predicate definedInIfDef(Function f) {
72-
exists(PreprocessorBranchDirective pbd, string file, int pbdStartLine, int pbdEndLine, int fBlockStartLine, int fBlockEndLine |
73-
functionLocation(f, file, fBlockStartLine, fBlockEndLine) and
74-
pbdLocation(pbd, file, pbdStartLine) and
75-
pbdLocation(pbd.getNext(), file, pbdEndLine) and
76-
pbdStartLine <= fBlockStartLine and
77-
pbdEndLine >= fBlockEndLine and
78-
// pbd is a preprocessor branch where multiple branches exist
79-
(
80-
pbd.getNext() instanceof PreprocessorElse or
81-
pbd instanceof PreprocessorElse or
82-
pbd.getNext() instanceof PreprocessorElif or
83-
pbd instanceof PreprocessorElif
84-
)
85-
) or
86-
44+
predicate functionDefinedInIfDefRecursive(Function f) {
45+
functionDefinedInIfDef(f) or
8746
// recurse into function calls
8847
exists(FunctionCall fc |
8948
fc.getEnclosingFunction() = f and
90-
definedInIfDef(fc.getTarget())
49+
functionDefinedInIfDefRecursive(fc.getTarget())
9150
)
9251
}
9352

@@ -121,8 +80,8 @@ where // EQExprs are covered by CompareWhereAssignMeant.ql
12180
not parent instanceof PureExprInVoidContext and
12281
not peivc.getEnclosingFunction().isCompilerGenerated() and
12382
not peivc.getType() instanceof UnknownType and
124-
not containsDisabledCode(peivc.(FunctionCall).getTarget()) and
125-
not definedInIfDef(peivc.(FunctionCall).getTarget()) and
83+
not functionContainsDisabledCodeRecursive(peivc.(FunctionCall).getTarget()) and
84+
not functionDefinedInIfDefRecursive(peivc.(FunctionCall).getTarget()) and
12685
if peivc instanceof FunctionCall then
12786
exists(Function target |
12887
target = peivc.(FunctionCall).getTarget() and
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
7+
<overview>
8+
<p> The <code>alloca</code> macro allocates memory by expanding the current stack frame. Invoking
9+
<code>alloca</code> within a loop may lead to a stack overflow because the memory is not released
10+
until the function returns.
11+
</p>
12+
13+
</overview>
14+
<recommendation>
15+
16+
<p>
17+
Consider invoking <code>alloca</code> once outside the loop, or using <code>malloc</code> or
18+
<code>new</code> to allocate memory on the heap if the allocation must be done inside the loop.
19+
</p>
20+
21+
</recommendation>
22+
<example>
23+
<p>The variable <code>path</code> is allocated inside a loop with <code>alloca</code>. Consequently,
24+
storage for all copies of the path is present in the stack frame until the end of the function.
25+
</p>
26+
27+
<sample src="AllocaInLoopBad.cpp" />
28+
29+
<p>In the revised example, <code>path</code> is allocated with <code>malloc</code> and freed at the
30+
end of the loop.
31+
</p>
32+
33+
<sample src="AllocaInLoopGood.cpp" />
34+
35+
36+
</example>
37+
<references>
38+
39+
<li>Linux Programmer's Manual: <a href="http://man7.org/linux/man-pages/man3/alloca.3.html">ALLOCA(3)</a>.</li>
40+
41+
</references>
42+
</qhelp>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
char *dir_path;
2+
char **dir_entries;
3+
int count;
4+
5+
for (int i = 0; i < count; i++) {
6+
char *path = (char*)alloca(strlen(dir_path) + strlen(dir_entry[i]) + 2);
7+
// use path
8+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
char *dir_path;
2+
char **dir_entries;
3+
int count;
4+
5+
for (int i = 0; i < count; i++) {
6+
char *path = (char*)malloc(strlen(dir_path) + strlen(dir_entry[i]) + 2);
7+
// use path
8+
free(path);
9+
}

cpp/ql/src/jsf/4.07 Header Files/AV Rule 35.qhelp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ some are after the final <code>#endif</code>. All three of these things must be
6868
<li>
6969
<a href="http://www.cplusplus.com/forum/articles/10627/">Headers and Includes: Why and How</a>
7070
</li>
71+
<li>
72+
<a href="https://gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html">The Multiple-Include Optimization</a>
73+
</li>
7174

7275

7376
</references>

cpp/ql/src/semmle/code/cpp/commons/Alloc.qll

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ predicate allocationFunction(Function f)
3939
name = "MmAllocateNodePagesForMdlEx" or
4040
name = "MmMapLockedPagesWithReservedMapping" or
4141
name = "MmMapLockedPages" or
42-
name = "MmMapLockedPagesSpecifyCache"
42+
name = "MmMapLockedPagesSpecifyCache" or
43+
name = "LocalAlloc" or
44+
name = "LocalReAlloc" or
45+
name = "GlobalAlloc" or
46+
name = "GlobalReAlloc" or
47+
name = "HeapAlloc" or
48+
name = "HeapReAlloc" or
49+
name = "VirtualAlloc" or
50+
name = "CoTaskMemAlloc" or
51+
name = "CoTaskMemRealloc"
4352
)
4453
)
4554
}
@@ -81,7 +90,17 @@ predicate freeFunction(Function f, int argNum)
8190
(name = "MmFreeMappingAddress" and argNum = 0) or
8291
(name = "MmFreePagesFromMdl" and argNum = 0) or
8392
(name = "MmUnmapReservedMapping" and argNum = 0) or
84-
(name = "MmUnmapLockedPages" and argNum = 0)
93+
(name = "MmUnmapLockedPages" and argNum = 0) or
94+
(name = "LocalFree" and argNum = 0) or
95+
(name = "GlobalFree" and argNum = 0) or
96+
(name = "HeapFree" and argNum = 2) or
97+
(name = "VirtualFree" and argNum = 0) or
98+
(name = "CoTaskMemFree" and argNum = 0) or
99+
(name = "SysFreeString" and argNum = 0) or
100+
(name = "LocalReAlloc" and argNum = 0) or
101+
(name = "GlobalReAlloc" and argNum = 0) or
102+
(name = "HeapReAlloc" and argNum = 2) or
103+
(name = "CoTaskMemRealloc" and argNum = 0)
85104
)
86105
)
87106
}

0 commit comments

Comments
 (0)