Merge pull request #5040 from MathiasVP/strset-and-strtok-models

C++: Strset and strtok model implementations
This commit is contained in:
Geoffrey White
2021-01-28 18:34:06 +00:00
committed by GitHub
5 changed files with 161 additions and 0 deletions

View File

@@ -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

View 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
}
}

View 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
}
}

View File

@@ -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 | |

View File

@@ -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
}