mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge pull request #3089 from geoffw0/sideeffect
CPP: Add side effect models for strcpy and strcat.
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user