C++: Implement model for _strinc and related functions.

This commit is contained in:
Mathias Vorreiter Pedersen
2021-02-02 12:20:02 +01:00
parent 5db1984315
commit b54f74a68a
4 changed files with 155 additions and 0 deletions

View File

@@ -17,6 +17,7 @@ private import implementations.Strdup
private import implementations.Strftime
private import implementations.Strtok
private import implementations.Strset
private import implementations.Strcrement
private import implementations.StdContainer
private import implementations.StdPair
private import implementations.StdMap

View File

@@ -0,0 +1,49 @@
/**
* Provides implementation classes modeling `strinc`, `strdec` and their variants.
* See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The function `_strinc`, `_strdec` and their variants.
*/
private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunction {
Strcrement() {
this.hasGlobalName([
"_strinc", // _strinc(source, locale)
"_wcsinc", // _strinc(source, locale)
"_mbsinc", // _strinc(source)
"_mbsinc_l", // _strinc(source, locale)
"_strdec", // _strdec(start, source)
"_wcsdec", // _wcsdec(start, source)
"_mbsdec", // _mbsdec(start, source)
"_mbsdec_l" // _mbsdec_l(start, source, locale)
])
}
override predicate hasArrayWithNullTerminator(int bufParam) {
// Match all parameters that are not locales.
this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType
}
override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(int index | hasArrayInput(index) |
input.isParameter(index) and output.isReturnValue()
or
input.isParameterDeref(index) and output.isReturnValueDeref()
)
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
hasArrayInput(i) and buffer = true
}
}

View File

@@ -5970,6 +5970,68 @@
| taint.cpp:572:37:572:41 | delim | taint.cpp:572:21:572:26 | call to strsep | TAINT |
| taint.cpp:573:10:573:18 | ref arg tokenized | taint.cpp:574:11:574:19 | tokenized | |
| taint.cpp:574:11:574:19 | tokenized | taint.cpp:574:10:574:19 | * ... | TAINT |
| taint.cpp:584:25:584:30 | source | taint.cpp:585:18:585:23 | source | |
| taint.cpp:584:39:584:43 | clean | taint.cpp:589:18:589:22 | clean | |
| taint.cpp:584:82:584:87 | locale | taint.cpp:585:26:585:31 | locale | |
| taint.cpp:584:82:584:87 | locale | taint.cpp:589:25:589:30 | locale | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:585:2:585:32 | ... = ... | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:586:7:586:11 | dest1 | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:587:8:587:12 | dest1 | |
| taint.cpp:585:18:585:23 | source | taint.cpp:585:10:585:16 | call to _strinc | TAINT |
| taint.cpp:585:26:585:31 | locale | taint.cpp:585:10:585:16 | call to _strinc | TAINT |
| taint.cpp:585:26:585:31 | ref arg locale | taint.cpp:589:25:589:30 | locale | |
| taint.cpp:586:7:586:11 | ref arg dest1 | taint.cpp:587:8:587:12 | dest1 | |
| taint.cpp:587:8:587:12 | dest1 | taint.cpp:587:7:587:12 | * ... | TAINT |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:589:2:589:31 | ... = ... | |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:590:7:590:11 | dest2 | |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:591:8:591:12 | dest2 | |
| taint.cpp:589:18:589:22 | clean | taint.cpp:589:10:589:16 | call to _strinc | TAINT |
| taint.cpp:589:25:589:30 | locale | taint.cpp:589:10:589:16 | call to _strinc | TAINT |
| taint.cpp:590:7:590:11 | ref arg dest2 | taint.cpp:591:8:591:12 | dest2 | |
| taint.cpp:591:8:591:12 | dest2 | taint.cpp:591:7:591:12 | * ... | TAINT |
| taint.cpp:594:34:594:48 | source_unsigned | taint.cpp:595:26:595:40 | source_unsigned | |
| taint.cpp:594:57:594:62 | source | taint.cpp:599:40:599:45 | source | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:595:2:595:41 | ... = ... | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:596:7:596:19 | dest_unsigned | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:597:8:597:20 | dest_unsigned | |
| taint.cpp:595:26:595:40 | source_unsigned | taint.cpp:595:18:595:24 | call to _mbsinc | TAINT |
| taint.cpp:596:7:596:19 | ref arg dest_unsigned | taint.cpp:597:8:597:20 | dest_unsigned | |
| taint.cpp:597:8:597:20 | dest_unsigned | taint.cpp:597:7:597:20 | * ... | TAINT |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:599:2:599:46 | ... = ... | |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:600:7:600:10 | dest | |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:601:8:601:11 | dest | |
| taint.cpp:599:40:599:45 | source | taint.cpp:599:16:599:22 | call to _mbsinc | TAINT |
| taint.cpp:600:7:600:10 | ref arg dest | taint.cpp:601:8:601:11 | dest | |
| taint.cpp:601:8:601:11 | dest | taint.cpp:601:7:601:11 | * ... | TAINT |
| taint.cpp:604:40:604:45 | source | taint.cpp:605:18:605:23 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:605:31:605:36 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:611:25:611:30 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:616:18:616:23 | source | |
| taint.cpp:604:63:604:67 | clean | taint.cpp:611:18:611:22 | clean | |
| taint.cpp:604:63:604:67 | clean | taint.cpp:616:26:616:30 | clean | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:605:2:605:37 | ... = ... | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:606:7:606:11 | dest1 | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:607:8:607:12 | dest1 | |
| taint.cpp:605:18:605:23 | source | taint.cpp:605:18:605:28 | ... + ... | TAINT |
| taint.cpp:605:18:605:28 | ... + ... | taint.cpp:605:10:605:16 | call to _strdec | TAINT |
| taint.cpp:605:27:605:28 | 12 | taint.cpp:605:18:605:28 | ... + ... | TAINT |
| taint.cpp:605:31:605:36 | source | taint.cpp:605:10:605:16 | call to _strdec | TAINT |
| taint.cpp:606:7:606:11 | ref arg dest1 | taint.cpp:607:8:607:12 | dest1 | |
| taint.cpp:607:8:607:12 | dest1 | taint.cpp:607:7:607:12 | * ... | TAINT |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:611:2:611:31 | ... = ... | |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:612:7:612:11 | dest2 | |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:613:8:613:12 | dest2 | |
| taint.cpp:611:18:611:22 | clean | taint.cpp:611:10:611:16 | call to _strdec | TAINT |
| taint.cpp:611:25:611:30 | source | taint.cpp:611:10:611:16 | call to _strdec | TAINT |
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:613:8:613:12 | dest2 | |
| taint.cpp:613:8:613:12 | dest2 | taint.cpp:613:7:613:12 | * ... | TAINT |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:616:2:616:31 | ... = ... | |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:617:7:617:11 | dest3 | |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:618:8:618:12 | dest3 | |
| taint.cpp:616:18:616:23 | source | taint.cpp:616:10:616:16 | call to _strdec | TAINT |
| taint.cpp:616:26:616:30 | clean | taint.cpp:616:10:616:16 | call to _strdec | TAINT |
| taint.cpp:617:7:617:11 | ref arg dest3 | taint.cpp:618:8:618:12 | dest3 | |
| taint.cpp:618:8:618:12 | dest3 | taint.cpp:618:7:618:12 | * ... | TAINT |
| 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

@@ -574,3 +574,46 @@ void test_strsep(char *source) {
sink(*tokenized); // $ ast,ir
}
}
// --- _strinc and related functions ---
char* _strinc(const char*, _locale_t);
unsigned char* _mbsinc(const unsigned char*);
unsigned char *_strdec(const unsigned char*, const unsigned char*);
void test__strinc(char* source, char* clean, char* dest1, char* dest2, _locale_t locale) {
dest1 = _strinc(source, locale);
sink(dest1); // $ ast,ir
sink(*dest1); // $ ast,ir
dest2 = _strinc(clean, locale);
sink(dest2);
sink(*dest2);
}
void test__mbsinc(unsigned char* source_unsigned, char* source, unsigned char* dest_unsigned, char* dest) {
dest_unsigned = _mbsinc(source_unsigned);
sink(dest_unsigned); // $ ast,ir
sink(*dest_unsigned); // $ ast,ir
dest = (char*)_mbsinc((unsigned char*)source);
sink(dest); // $ ast,ir
sink(*dest); // $ ast,ir
}
void test__strdec(const unsigned char* source, unsigned char* clean, unsigned char* dest1, unsigned char* dest2, unsigned char* dest3) {
dest1 = _strdec(source + 12, source);
sink(dest1); // $ ast,ir
sink(*dest1); // $ ast,ir
// If `clean` does not precede `source` this technically breaks the precondition of _strdec.
// We would still like to have taint, though.
dest2 = _strdec(clean, source);
sink(dest2); // $ ast,ir
sink(*dest2); // $ ast,ir
// Also breaks the precondition on _strdec.
dest3 = _strdec(source, clean);
sink(dest3); // $ ast,ir
sink(*dest3); // $ ast,ir
}