Merge pull request #5065 from MathiasVP/scanf-model

C++: Add sscanf and fscanf models
This commit is contained in:
Geoffrey White
2021-02-02 10:30:19 +00:00
committed by GitHub
5 changed files with 88 additions and 3 deletions

View File

@@ -92,7 +92,9 @@ class Snscanf extends ScanfFunction {
this instanceof TopLevelFunction and
(
hasName("_snscanf") or // _snscanf(src, max_amount, format, args...)
hasName("_snwscanf") // _snwscanf(src, max_amount, format, args...)
hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
hasName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
// note that the max_amount is not a limit on the output length, it's an input length
// limit used with non null-terminated strings.
)
@@ -101,6 +103,12 @@ class Snscanf extends ScanfFunction {
override int getInputParameterIndex() { result = 0 }
override int getFormatParameterIndex() { result = 2 }
/**
* Gets the position at which the maximum number of characters in the
* input string is specified.
*/
int getInputLengthParameterIndex() { result = 1 }
}
/**

View File

@@ -25,3 +25,4 @@ private import implementations.StdString
private import implementations.Swap
private import implementations.GetDelim
private import implementations.SmartPointer
private import implementations.Sscanf

View File

@@ -0,0 +1,72 @@
/**
* Provides implementation classes modeling `sscanf`, `fscanf` and various similar
* functions. See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.commons.Scanf
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function `sscanf`, `fscanf` and its assorted variants
*/
private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, SideEffectFunction {
SscanfModel() { this instanceof Sscanf or this instanceof Fscanf or this instanceof Snscanf }
override predicate hasArrayWithNullTerminator(int bufParam) {
bufParam = this.(ScanfFunction).getFormatParameterIndex()
or
not this instanceof Fscanf and
bufParam = this.(ScanfFunction).getInputParameterIndex()
}
override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) }
private int getLengthParameterIndex() { result = this.(Snscanf).getInputLengthParameterIndex() }
private int getLocaleParameterIndex() {
this.getName().matches("%\\_l") and
(
if exists(getLengthParameterIndex())
then result = getLengthParameterIndex() + 2
else result = 2
)
}
private int getArgsStartPosition() { result = this.getNumberOfParameters() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(this.(ScanfFunction).getInputParameterIndex()) and
output.isParameterDeref(any(int i | i >= getArgsStartPosition()))
}
override predicate parameterNeverEscapes(int index) {
index = [0 .. max(getACallToThisFunction().getNumberOfArguments())]
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i >= getArgsStartPosition() and
buffer = true and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
buffer = true and
i =
[
this.(ScanfFunction).getInputParameterIndex(),
this.(ScanfFunction).getFormatParameterIndex(), getLocaleParameterIndex()
]
}
}

View File

@@ -123,7 +123,7 @@ void test1()
{
int i = 0;
sink(sscanf(string::source(), "%i", &i));
sink(i); // $ MISSING: ast,ir
sink(i); // $ ast,ir
}
{
char buffer[256] = {0};
@@ -133,7 +133,7 @@ void test1()
{
char buffer[256] = {0};
sink(sscanf(string::source(), "%s", &buffer));
sink(buffer); // $ MISSING: ast,ir
sink(buffer); // $ ast,ir
}
}

View File

@@ -378,23 +378,27 @@
| format.cpp:114:37:114:50 | call to source | format.cpp:114:18:114:23 | ref arg buffer | TAINT |
| format.cpp:119:10:119:11 | 0 | format.cpp:120:29:120:29 | i | |
| format.cpp:119:10:119:11 | 0 | format.cpp:121:8:121:8 | i | |
| format.cpp:120:15:120:19 | 123 | format.cpp:120:28:120:29 | ref arg & ... | TAINT |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:120:29:120:29 | i [inner post update] | |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:121:8:121:8 | i | |
| format.cpp:120:29:120:29 | i | format.cpp:120:28:120:29 | & ... | |
| format.cpp:124:10:124:11 | 0 | format.cpp:125:40:125:40 | i | |
| format.cpp:124:10:124:11 | 0 | format.cpp:126:8:126:8 | i | |
| format.cpp:125:15:125:28 | call to source | format.cpp:125:39:125:40 | ref arg & ... | TAINT |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:125:40:125:40 | i [inner post update] | |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:126:8:126:8 | i | |
| format.cpp:125:40:125:40 | i | format.cpp:125:39:125:40 | & ... | |
| format.cpp:129:21:129:24 | {...} | format.cpp:130:32:130:37 | buffer | |
| format.cpp:129:21:129:24 | {...} | format.cpp:131:8:131:13 | buffer | |
| format.cpp:129:23:129:23 | 0 | format.cpp:129:21:129:24 | {...} | TAINT |
| format.cpp:130:15:130:22 | Hello. | format.cpp:130:31:130:37 | ref arg & ... | TAINT |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:130:32:130:37 | buffer [inner post update] | |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:131:8:131:13 | buffer | |
| format.cpp:130:32:130:37 | buffer | format.cpp:130:31:130:37 | & ... | |
| format.cpp:134:21:134:24 | {...} | format.cpp:135:40:135:45 | buffer | |
| format.cpp:134:21:134:24 | {...} | format.cpp:136:8:136:13 | buffer | |
| format.cpp:134:23:134:23 | 0 | format.cpp:134:21:134:24 | {...} | TAINT |
| format.cpp:135:15:135:28 | call to source | format.cpp:135:39:135:45 | ref arg & ... | TAINT |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:135:40:135:45 | buffer [inner post update] | |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:136:8:136:13 | buffer | |
| format.cpp:135:40:135:45 | buffer | format.cpp:135:39:135:45 | & ... | |