mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
Merge pull request #5040 from MathiasVP/strset-and-strtok-models
C++: Strset and strtok model implementations
This commit is contained in:
@@ -15,6 +15,8 @@ private import implementations.Strcat
|
||||
private import implementations.Strcpy
|
||||
private import implementations.Strdup
|
||||
private import implementations.Strftime
|
||||
private import implementations.Strtok
|
||||
private import implementations.Strset
|
||||
private import implementations.StdContainer
|
||||
private import implementations.StdPair
|
||||
private import implementations.StdMap
|
||||
|
||||
62
cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll
Normal file
62
cpp/ql/src/semmle/code/cpp/models/implementations/Strset.qll
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `strset` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The standard function `strset` and its assorted variants
|
||||
*/
|
||||
private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
|
||||
SideEffectFunction {
|
||||
StrsetFunction() {
|
||||
hasGlobalName([
|
||||
"strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l",
|
||||
"_mbsnbset", "_mbsnbset_l", "_strnset", "_strnset_l", "_wcsnset", "_wcsnset_l", "_mbsnset",
|
||||
"_mbsnset_l"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from the character that overrides the string
|
||||
input.isParameter(1) and
|
||||
(
|
||||
output.isReturnValueDeref()
|
||||
or
|
||||
output.isParameterDeref(0)
|
||||
)
|
||||
or
|
||||
// flow from the input string to the output string
|
||||
input.isParameter(0) and
|
||||
output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { none() }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and buffer = true and mustWrite = true
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 0 and buffer = true
|
||||
}
|
||||
}
|
||||
49
cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll
Normal file
49
cpp/ql/src/semmle/code/cpp/models/implementations/Strtok.qll
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Provides implementation classes modeling `strtok` and various similar
|
||||
* functions. See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
/**
|
||||
* The standard function `strtok` and its assorted variants
|
||||
*/
|
||||
private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
|
||||
Strtok() {
|
||||
this.hasGlobalOrStdName("strtok") or
|
||||
this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"])
|
||||
}
|
||||
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = [0, 1] }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) { bufParam = [0, 1] }
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate parameterNeverEscapes(int index) { index = 1 }
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int index) { none() }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(0) and output.isReturnValue()
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { none() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { none() }
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 0 and buffer = true and mustWrite = false
|
||||
}
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = [0, 1] and buffer = true
|
||||
}
|
||||
}
|
||||
@@ -5861,6 +5861,28 @@
|
||||
| taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | |
|
||||
| taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | |
|
||||
| taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT |
|
||||
| taint.cpp:492:24:492:29 | source | taint.cpp:494:27:494:32 | source | |
|
||||
| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:494:35:494:39 | delim | |
|
||||
| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:496:7:496:11 | delim | |
|
||||
| taint.cpp:494:20:494:25 | call to strtok | taint.cpp:495:7:495:15 | tokenized | |
|
||||
| taint.cpp:494:27:494:32 | source | taint.cpp:494:20:494:25 | call to strtok | TAINT |
|
||||
| taint.cpp:503:26:503:28 | ptr | taint.cpp:504:10:504:12 | ptr | |
|
||||
| taint.cpp:503:26:503:28 | ptr | taint.cpp:505:7:505:9 | ptr | |
|
||||
| taint.cpp:503:26:503:28 | ptr | taint.cpp:506:8:506:10 | ptr | |
|
||||
| taint.cpp:503:36:503:41 | source | taint.cpp:504:15:504:20 | source | |
|
||||
| taint.cpp:504:10:504:12 | ptr | taint.cpp:504:2:504:8 | call to _strset | |
|
||||
| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:505:7:505:9 | ptr | |
|
||||
| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | |
|
||||
| taint.cpp:504:15:504:20 | source | taint.cpp:504:2:504:8 | call to _strset | TAINT |
|
||||
| taint.cpp:504:15:504:20 | source | taint.cpp:504:10:504:12 | ref arg ptr | |
|
||||
| taint.cpp:505:7:505:9 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | |
|
||||
| taint.cpp:506:8:506:10 | ptr | taint.cpp:506:7:506:10 | * ... | TAINT |
|
||||
| taint.cpp:509:26:509:31 | source | taint.cpp:510:10:510:15 | source | |
|
||||
| taint.cpp:509:26:509:31 | source | taint.cpp:511:7:511:12 | source | |
|
||||
| taint.cpp:510:10:510:15 | ref arg source | taint.cpp:511:7:511:12 | source | |
|
||||
| taint.cpp:510:10:510:15 | source | taint.cpp:510:2:510:8 | call to _strset | |
|
||||
| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:2:510:8 | call to _strset | TAINT |
|
||||
| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:10:510:15 | ref arg source | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
|
||||
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |
|
||||
|
||||
@@ -484,3 +484,29 @@ void test_getdelim(FILE* source1) {
|
||||
|
||||
sink(line); // $ ir,ast
|
||||
}
|
||||
|
||||
// --- strtok ---
|
||||
|
||||
char *strtok(char *str, const char *delim);
|
||||
|
||||
void test_strtok(char *source) {
|
||||
const char* delim = ",.-;:_";
|
||||
char* tokenized = strtok(source, delim);
|
||||
sink(tokenized); // $ ast,ir
|
||||
sink(delim);
|
||||
}
|
||||
|
||||
// --- strset ---
|
||||
|
||||
char *_strset(char *str, int c);
|
||||
|
||||
void test_strset_1(char* ptr, char source) {
|
||||
_strset(ptr, source);
|
||||
sink(ptr); // $ SPURIOUS: ast,ir
|
||||
sink(*ptr); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_strset_2(char* source) {
|
||||
_strset(source, 0);
|
||||
sink(source); // $ ast,ir
|
||||
}
|
||||
Reference in New Issue
Block a user