Merge pull request #3089 from geoffw0/sideeffect

CPP: Add side effect models for strcpy and strcat.
This commit is contained in:
Jonas Jensen
2020-03-31 12:11:04 +02:00
committed by GitHub
5 changed files with 171 additions and 2 deletions

View File

@@ -1,11 +1,12 @@
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function `strcat` and its wide, sized, and Microsoft variants.
*/
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction {
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
StrcatFunction() {
exists(string name | name = getName() |
name = "strcat" or // strcat(dst, src)
@@ -56,4 +57,19 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction {
override predicate hasArrayWithNullTerminator(int param) { param = 1 }
override predicate hasArrayWithUnknownSize(int param) { param = 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 = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
(i = 0 or i = 1) and
buffer = true
}
}

View File

@@ -1,11 +1,12 @@
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
*/
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() {
this.hasName("strcpy") or
this.hasName("_mbscpy") or
@@ -74,4 +75,23 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
output.isReturnValueDeref()
)
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
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 = 1 and
buffer = true
}
override ParameterIndex getParameterSizeIndex(ParameterIndex i) {
hasArrayWithVariableSize(i, result)
}
}

View File

@@ -8475,6 +8475,76 @@ ir.cpp:
# 1243| Type = [PointerType] const char *
# 1243| ValueCategory = prvalue(load)
# 1244| 3: [ReturnStmt] return ...
# 1248| [TopLevelFunction] char* strcpy(char*, char const*)
# 1248| params:
# 1248| 0: [Parameter] destination
# 1248| Type = [CharPointerType] char *
# 1248| 1: [Parameter] source
# 1248| Type = [PointerType] const char *
# 1249| [TopLevelFunction] char* strcat(char*, char const*)
# 1249| params:
# 1249| 0: [Parameter] destination
# 1249| Type = [CharPointerType] char *
# 1249| 1: [Parameter] source
# 1249| Type = [PointerType] const char *
# 1251| [TopLevelFunction] void test_strings(char*, char*)
# 1251| params:
# 1251| 0: [Parameter] s1
# 1251| Type = [CharPointerType] char *
# 1251| 1: [Parameter] s2
# 1251| Type = [CharPointerType] char *
# 1251| body: [Block] { ... }
# 1252| 0: [DeclStmt] declaration
# 1252| 0: [VariableDeclarationEntry] definition of buffer
# 1252| Type = [ArrayType] char[1024]
# 1252| init: [Initializer] initializer for buffer
# 1252| expr: [ArrayAggregateLiteral] {...}
# 1252| Type = [ArrayType] char[1024]
# 1252| ValueCategory = prvalue
# 1252| [0]: [CStyleCast] (char)...
# 1252| Conversion = [IntegralConversion] integral conversion
# 1252| Type = [PlainCharType] char
# 1252| Value = [CStyleCast] 0
# 1252| ValueCategory = prvalue
# 1252| expr: [Literal] 0
# 1252| Type = [IntType] int
# 1252| Value = [Literal] 0
# 1252| ValueCategory = prvalue
# 1254| 1: [ExprStmt] ExprStmt
# 1254| 0: [FunctionCall] call to strcpy
# 1254| Type = [CharPointerType] char *
# 1254| ValueCategory = prvalue
# 1254| 0: [ArrayToPointerConversion] array to pointer conversion
# 1254| Type = [CharPointerType] char *
# 1254| ValueCategory = prvalue
# 1254| expr: [VariableAccess] buffer
# 1254| Type = [ArrayType] char[1024]
# 1254| ValueCategory = lvalue
# 1254| 1: [CStyleCast] (const char *)...
# 1254| Conversion = [PointerConversion] pointer conversion
# 1254| Type = [PointerType] const char *
# 1254| ValueCategory = prvalue
# 1254| expr: [VariableAccess] s1
# 1254| Type = [CharPointerType] char *
# 1254| ValueCategory = prvalue(load)
# 1255| 2: [ExprStmt] ExprStmt
# 1255| 0: [FunctionCall] call to strcat
# 1255| Type = [CharPointerType] char *
# 1255| ValueCategory = prvalue
# 1255| 0: [ArrayToPointerConversion] array to pointer conversion
# 1255| Type = [CharPointerType] char *
# 1255| ValueCategory = prvalue
# 1255| expr: [VariableAccess] buffer
# 1255| Type = [ArrayType] char[1024]
# 1255| ValueCategory = lvalue
# 1255| 1: [CStyleCast] (const char *)...
# 1255| Conversion = [PointerConversion] pointer conversion
# 1255| Type = [PointerType] const char *
# 1255| ValueCategory = prvalue
# 1255| expr: [VariableAccess] s2
# 1255| Type = [CharPointerType] char *
# 1255| ValueCategory = prvalue(load)
# 1256| 3: [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| params:

View File

@@ -1243,4 +1243,16 @@ void staticLocalWithConstructor(const char* dynamic) {
static String c(dynamic);
}
// --- strings ---
char *strcpy(char *destination, const char *source);
char *strcat(char *destination, const char *source);
void test_strings(char *s1, char *s2) {
char buffer[1024] = {0};
strcpy(buffer, s1);
strcat(buffer, s2);
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -6417,6 +6417,57 @@ ir.cpp:
# 1241| mu1241_6(bool) = Store : &:r1241_1, r1241_5
#-----| Goto -> Block 1
# 1251| void test_strings(char*, char*)
# 1251| Block 0
# 1251| v1251_1(void) = EnterFunction :
# 1251| mu1251_2(unknown) = AliasedDefinition :
# 1251| mu1251_3(unknown) = InitializeNonLocal :
# 1251| mu1251_4(unknown) = UnmodeledDefinition :
# 1251| r1251_5(glval<char *>) = VariableAddress[s1] :
# 1251| mu1251_6(char *) = InitializeParameter[s1] : &:r1251_5
# 1251| r1251_7(char *) = Load : &:r1251_5, ~mu1251_6
# 1251| mu1251_8(unknown) = InitializeIndirection[s1] : &:r1251_7
# 1251| r1251_9(glval<char *>) = VariableAddress[s2] :
# 1251| mu1251_10(char *) = InitializeParameter[s2] : &:r1251_9
# 1251| r1251_11(char *) = Load : &:r1251_9, ~mu1251_10
# 1251| mu1251_12(unknown) = InitializeIndirection[s2] : &:r1251_11
# 1252| r1252_1(glval<char[1024]>) = VariableAddress[buffer] :
# 1252| mu1252_2(char[1024]) = Uninitialized[buffer] : &:r1252_1
# 1252| r1252_3(int) = Constant[0] :
# 1252| r1252_4(glval<char>) = PointerAdd[1] : r1252_1, r1252_3
# 1252| r1252_5(char) = Constant[0] :
# 1252| mu1252_6(char) = Store : &:r1252_4, r1252_5
# 1252| r1252_7(int) = Constant[1] :
# 1252| r1252_8(glval<char>) = PointerAdd[1] : r1252_1, r1252_7
# 1252| r1252_9(unknown[1023]) = Constant[0] :
# 1252| mu1252_10(unknown[1023]) = Store : &:r1252_8, r1252_9
# 1254| r1254_1(glval<unknown>) = FunctionAddress[strcpy] :
# 1254| r1254_2(glval<char[1024]>) = VariableAddress[buffer] :
# 1254| r1254_3(char *) = Convert : r1254_2
# 1254| r1254_4(glval<char *>) = VariableAddress[s1] :
# 1254| r1254_5(char *) = Load : &:r1254_4, ~mu1251_4
# 1254| r1254_6(char *) = Convert : r1254_5
# 1254| r1254_7(char *) = Call : func:r1254_1, 0:r1254_3, 1:r1254_6
# 1254| v1254_8(void) = ^BufferReadSideEffect[1] : &:r1254_6, ~mu1251_4
# 1254| mu1254_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1254_3
# 1255| r1255_1(glval<unknown>) = FunctionAddress[strcat] :
# 1255| r1255_2(glval<char[1024]>) = VariableAddress[buffer] :
# 1255| r1255_3(char *) = Convert : r1255_2
# 1255| r1255_4(glval<char *>) = VariableAddress[s2] :
# 1255| r1255_5(char *) = Load : &:r1255_4, ~mu1251_4
# 1255| r1255_6(char *) = Convert : r1255_5
# 1255| r1255_7(char *) = Call : func:r1255_1, 0:r1255_3, 1:r1255_6
# 1255| v1255_8(void) = ^BufferReadSideEffect[0] : &:r1255_3, ~mu1251_4
# 1255| v1255_9(void) = ^BufferReadSideEffect[1] : &:r1255_6, ~mu1251_4
# 1255| mu1255_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1255_3
# 1256| v1256_1(void) = NoOp :
# 1251| v1251_13(void) = ReturnIndirection : &:r1251_7, ~mu1251_4
# 1251| v1251_14(void) = ReturnIndirection : &:r1251_11, ~mu1251_4
# 1251| v1251_15(void) = ReturnVoid :
# 1251| v1251_16(void) = UnmodeledUse : mu*
# 1251| v1251_17(void) = AliasedUse : ~mu1251_4
# 1251| v1251_18(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0