mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge pull request #5065 from MathiasVP/scanf-model
C++: Add sscanf and fscanf models
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,3 +25,4 @@ private import implementations.StdString
|
||||
private import implementations.Swap
|
||||
private import implementations.GetDelim
|
||||
private import implementations.SmartPointer
|
||||
private import implementations.Sscanf
|
||||
|
||||
72
cpp/ql/src/semmle/code/cpp/models/implementations/Sscanf.qll
Normal file
72
cpp/ql/src/semmle/code/cpp/models/implementations/Sscanf.qll
Normal 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()
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 | & ... | |
|
||||
|
||||
Reference in New Issue
Block a user