Skip to content

Commit edeefe5

Browse files
authored
Merge pull request #17298 from paldepind/model-functions-that-dont-throw
C++: Add basic modeling of functions that don't throw
2 parents 123c375 + d1fecd8 commit edeefe5

File tree

12 files changed

+51
-15
lines changed

12 files changed

+51
-15
lines changed

cpp/ql/lib/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ private import implementations.Accept
4242
private import implementations.Poll
4343
private import implementations.Select
4444
private import implementations.MySql
45+
private import implementations.NoexceptFunction
4546
private import implementations.ODBC
4647
private import implementations.SqLite3
4748
private import implementations.PostgreSql

cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import semmle.code.cpp.models.interfaces.DataFlow
99
import semmle.code.cpp.models.interfaces.Alias
1010
import semmle.code.cpp.models.interfaces.SideEffect
1111
import semmle.code.cpp.models.interfaces.Taint
12+
import semmle.code.cpp.models.interfaces.NonThrowing
1213

1314
/**
1415
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
1516
* `__builtin___memcpy_chk`.
1617
*/
1718
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
18-
AliasFunction
19+
AliasFunction, NonThrowingFunction
1920
{
2021
MemcpyFunction() {
2122
// memcpy(dest, src, num)

cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
88
import semmle.code.cpp.models.interfaces.DataFlow
99
import semmle.code.cpp.models.interfaces.Alias
1010
import semmle.code.cpp.models.interfaces.SideEffect
11+
import semmle.code.cpp.models.interfaces.NonThrowing
1112

1213
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
13-
SideEffectFunction
14+
SideEffectFunction, NonThrowingFunction
1415
{
1516
MemsetFunctionModel() {
1617
this.hasGlobalOrStdOrBslName("memset")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import semmle.code.cpp.models.interfaces.NonThrowing
2+
3+
/**
4+
* A function that is annotated with a `noexcept` specifier (or the equivalent
5+
* `throw()` specifier) guaranteeing that the function can not throw exceptions.
6+
*
7+
* Note: The `throw` specifier was deprecated in C++11 and removed in C++17.
8+
*/
9+
class NoexceptFunction extends NonThrowingFunction {
10+
NoexceptFunction() { this.isNoExcept() or this.isNoThrow() }
11+
}

cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
import semmle.code.cpp.models.interfaces.FormattingFunction
99
import semmle.code.cpp.models.interfaces.Alias
1010
import semmle.code.cpp.models.interfaces.SideEffect
11+
import semmle.code.cpp.models.interfaces.NonThrowing
1112

1213
/**
1314
* The standard functions `printf`, `wprintf` and their glib variants.
1415
*/
15-
private class Printf extends FormattingFunction, AliasFunction {
16+
private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunction {
1617
Printf() {
1718
this instanceof TopLevelFunction and
1819
(
@@ -36,7 +37,7 @@ private class Printf extends FormattingFunction, AliasFunction {
3637
/**
3738
* The standard functions `fprintf`, `fwprintf` and their glib variants.
3839
*/
39-
private class Fprintf extends FormattingFunction {
40+
private class Fprintf extends FormattingFunction, NonThrowingFunction {
4041
Fprintf() {
4142
this instanceof TopLevelFunction and
4243
(
@@ -54,7 +55,7 @@ private class Fprintf extends FormattingFunction {
5455
/**
5556
* The standard function `sprintf` and its Microsoft and glib variants.
5657
*/
57-
private class Sprintf extends FormattingFunction {
58+
private class Sprintf extends FormattingFunction, NonThrowingFunction {
5859
Sprintf() {
5960
this instanceof TopLevelFunction and
6061
(
@@ -97,7 +98,7 @@ private class Sprintf extends FormattingFunction {
9798
/**
9899
* Implements `Snprintf`.
99100
*/
100-
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
101+
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, NonThrowingFunction {
101102
SnprintfImpl() {
102103
this instanceof TopLevelFunction and
103104
(
@@ -204,7 +205,7 @@ private class StringCchPrintf extends FormattingFunction {
204205
/**
205206
* The standard function `syslog`.
206207
*/
207-
private class Syslog extends FormattingFunction {
208+
private class Syslog extends FormattingFunction, NonThrowingFunction {
208209
Syslog() {
209210
this instanceof TopLevelFunction and
210211
this.hasGlobalName("syslog") and

cpp/ql/lib/semmle/code/cpp/models/implementations/Strcat.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
77
import semmle.code.cpp.models.interfaces.DataFlow
88
import semmle.code.cpp.models.interfaces.Taint
99
import semmle.code.cpp.models.interfaces.SideEffect
10+
import semmle.code.cpp.models.interfaces.NonThrowing
1011

1112
/**
1213
* The standard function `strcat` and its wide, sized, and Microsoft variants.
1314
*
1415
* Does not include `strlcat`, which is covered by `StrlcatFunction`
1516
*/
16-
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
17+
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction,
18+
NonThrowingFunction
19+
{
1720
StrcatFunction() {
1821
this.hasGlobalOrStdOrBslName([
1922
"strcat", // strcat(dst, src)

cpp/ql/lib/semmle/code/cpp/models/implementations/Strcpy.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
77
import semmle.code.cpp.models.interfaces.DataFlow
88
import semmle.code.cpp.models.interfaces.Taint
99
import semmle.code.cpp.models.interfaces.SideEffect
10+
import semmle.code.cpp.models.interfaces.NonThrowing
1011

1112
/**
1213
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
1314
*/
14-
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
15+
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction,
16+
NonThrowingFunction
17+
{
1518
StrcpyFunction() {
1619
this.hasGlobalOrStdOrBslName([
1720
"strcpy", // strcpy(dst, src)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Provides an abstract class for modeling functions that never throw.
3+
*/
4+
5+
import semmle.code.cpp.Function
6+
import semmle.code.cpp.models.Models
7+
8+
/**
9+
* A function that is guaranteed to never throw.
10+
*/
11+
abstract class NonThrowingFunction extends Function { }

cpp/ql/src/Security/CWE/CWE-570/IncorrectAllocationErrorHandling.ql

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import cpp
1717
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1818
import semmle.code.cpp.controlflow.Guards
19+
import semmle.code.cpp.models.implementations.NoexceptFunction
1920

2021
/** Gets the `Constructor` invoked when `newExpr` allocates memory. */
2122
Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) {
@@ -44,9 +45,8 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
4445
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
4546
*/
4647
predicate functionMayThrow(Function f) {
47-
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock())) and
48-
not f.isNoExcept() and
49-
not f.isNoThrow()
48+
not f instanceof NonThrowingFunction and
49+
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock()))
5050
}
5151

5252
/** Holds if the evaluation of `stmt` may throw an exception. */
@@ -172,8 +172,7 @@ class ThrowingAllocator extends Function {
172172
not exists(Parameter p | p = this.getAParameter() |
173173
p.getUnspecifiedType().stripType() instanceof NoThrowType
174174
) and
175-
not this.isNoExcept() and
176-
not this.isNoThrow()
175+
not this instanceof NoexceptFunction
177176
)
178177
}
179178
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.

0 commit comments

Comments
 (0)