From ea7602b57149eb9498a107cec873b7361a68f0e2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 8 Jul 2019 11:41:46 -0700 Subject: [PATCH 1/5] C++: add test for Alias and SideEffect models --- .../ir/ssa/aliased_ssa_ir.expected | 42 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 9 ++++ .../ir/ssa/unaliased_ssa_ir.expected | 40 ++++++++++++++++++ 3 files changed, 91 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 1e0ebfdfdd1e..548f71e3e605 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -758,3 +758,45 @@ ssa.cpp: # 184| v0_22(void) = ReturnVoid : # 184| v0_23(void) = UnmodeledUse : mu* # 184| v0_24(void) = ExitFunction : + +# 197| int PureFunctions(char*, char*, int) +# 197| Block 0 +# 197| v0_0(void) = EnterFunction : +# 197| m0_1(unknown) = AliasedDefinition : +# 197| mu0_2(unknown) = UnmodeledDefinition : +# 197| r0_3(glval) = VariableAddress[str1] : +# 197| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 197| r0_5(glval) = VariableAddress[str2] : +# 197| m0_6(char *) = InitializeParameter[str2] : &:r0_5 +# 197| r0_7(glval) = VariableAddress[x] : +# 197| m0_8(int) = InitializeParameter[x] : &:r0_7 +# 198| r0_9(glval) = VariableAddress[ret] : +# 198| r0_10(glval) = FunctionAddress[strcmp] : +# 198| r0_11(glval) = VariableAddress[str1] : +# 198| r0_12(char *) = Load : &:r0_11, m0_4 +# 198| r0_13(char *) = Convert : r0_12 +# 198| r0_14(glval) = VariableAddress[str2] : +# 198| r0_15(char *) = Load : &:r0_14, m0_6 +# 198| r0_16(char *) = Convert : r0_15 +# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 +# 198| m0_18(unknown) = ^CallSideEffect : ~m0_1 +# 198| m0_19(unknown) = Chi : total:m0_1, partial:m0_18 +# 198| m0_20(int) = Store : &:r0_9, r0_17 +# 199| r0_21(glval) = FunctionAddress[abs] : +# 199| r0_22(glval) = VariableAddress[x] : +# 199| r0_23(int) = Load : &:r0_22, m0_8 +# 199| r0_24(int) = Call : func:r0_21, 0:r0_23 +# 199| m0_25(unknown) = ^CallSideEffect : ~m0_19 +# 199| m0_26(unknown) = Chi : total:m0_19, partial:m0_25 +# 199| r0_27(glval) = VariableAddress[ret] : +# 199| r0_28(int) = Load : &:r0_27, m0_20 +# 199| r0_29(int) = Add : r0_28, r0_24 +# 199| m0_30(int) = Store : &:r0_27, r0_29 +# 200| r0_31(glval) = VariableAddress[#return] : +# 200| r0_32(glval) = VariableAddress[ret] : +# 200| r0_33(int) = Load : &:r0_32, m0_30 +# 200| m0_34(int) = Store : &:r0_31, r0_33 +# 197| r0_35(glval) = VariableAddress[#return] : +# 197| v0_36(void) = ReturnValue : &:r0_35, m0_34 +# 197| v0_37(void) = UnmodeledUse : mu* +# 197| v0_38(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 729d8392e833..47f13846083e 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -189,4 +189,13 @@ static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c : "+a" (a), "+b" (b) : "c" (c), "d" (d) ); +} + +int strcmp(const char *, const char *); +int abs(int); + +int PureFunctions(char *str1, char *str2, int x) { + int ret = strcmp(str1, str2); + ret += abs(x); + return ret; } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 0b506082a457..ebf7f46d2c84 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -724,3 +724,43 @@ ssa.cpp: # 184| v0_17(void) = ReturnVoid : # 184| v0_18(void) = UnmodeledUse : mu* # 184| v0_19(void) = ExitFunction : + +# 197| int PureFunctions(char*, char*, int) +# 197| Block 0 +# 197| v0_0(void) = EnterFunction : +# 197| mu0_1(unknown) = AliasedDefinition : +# 197| mu0_2(unknown) = UnmodeledDefinition : +# 197| r0_3(glval) = VariableAddress[str1] : +# 197| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 197| r0_5(glval) = VariableAddress[str2] : +# 197| m0_6(char *) = InitializeParameter[str2] : &:r0_5 +# 197| r0_7(glval) = VariableAddress[x] : +# 197| m0_8(int) = InitializeParameter[x] : &:r0_7 +# 198| r0_9(glval) = VariableAddress[ret] : +# 198| r0_10(glval) = FunctionAddress[strcmp] : +# 198| r0_11(glval) = VariableAddress[str1] : +# 198| r0_12(char *) = Load : &:r0_11, m0_4 +# 198| r0_13(char *) = Convert : r0_12 +# 198| r0_14(glval) = VariableAddress[str2] : +# 198| r0_15(char *) = Load : &:r0_14, m0_6 +# 198| r0_16(char *) = Convert : r0_15 +# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 +# 198| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 198| m0_19(int) = Store : &:r0_9, r0_17 +# 199| r0_20(glval) = FunctionAddress[abs] : +# 199| r0_21(glval) = VariableAddress[x] : +# 199| r0_22(int) = Load : &:r0_21, m0_8 +# 199| r0_23(int) = Call : func:r0_20, 0:r0_22 +# 199| mu0_24(unknown) = ^CallSideEffect : ~mu0_2 +# 199| r0_25(glval) = VariableAddress[ret] : +# 199| r0_26(int) = Load : &:r0_25, m0_19 +# 199| r0_27(int) = Add : r0_26, r0_23 +# 199| m0_28(int) = Store : &:r0_25, r0_27 +# 200| r0_29(glval) = VariableAddress[#return] : +# 200| r0_30(glval) = VariableAddress[ret] : +# 200| r0_31(int) = Load : &:r0_30, m0_28 +# 200| m0_32(int) = Store : &:r0_29, r0_31 +# 197| r0_33(glval) = VariableAddress[#return] : +# 197| v0_34(void) = ReturnValue : &:r0_33, m0_32 +# 197| v0_35(void) = UnmodeledUse : mu* +# 197| v0_36(void) = ExitFunction : From 41e4d920e3402265b158d0782fa4aff1324b8bf2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 8 Jul 2019 12:26:58 -0700 Subject: [PATCH 2/5] C++: alias and side effect info for pure functions --- .../code/cpp/models/implementations/Pure.qll | 57 +++++++++++++++++-- .../ir/ssa/aliased_ssa_ir.expected | 39 ++++++------- .../ir/ssa/unaliased_ssa_ir.expected | 27 +++++---- 3 files changed, 83 insertions(+), 40 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 9af506140dd4..b3aaed2cfb8b 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -1,17 +1,17 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.Alias +import semmle.code.cpp.models.interfaces.SideEffect -class PureFunction extends ArrayFunction, TaintFunction { - PureFunction() { +class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { + PureStrFunction() { exists(string name | hasName(name) and ( - name = "abs" - or name = "atof" + name = "atof" or name = "atoi" or name = "atol" or name = "atoll" - or name = "labs" or name = "strcasestr" or name = "strchnul" or name = "strchr" @@ -54,4 +54,51 @@ class PureFunction extends ArrayFunction, TaintFunction { output.isOutReturnValue() ) } + + override predicate parameterNeverEscapes(int i) { + getParameter(i).getUnspecifiedType() instanceof PointerType + } + + override predicate parameterEscapesOnlyViaReturn(int i) { + none() + } + + override predicate parameterIsAlwaysReturned(int i) { + none() + } + + override predicate neverReadsMemory() { + none() + } + + override predicate neverWritesMemory() { + any() + } +} + +class PureFunction extends TaintFunction, SideEffectFunction { + PureFunction() { + exists(string name | + hasName(name) and + ( + name = "abs" or + name = "labs" + ) + ) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + exists (ParameterIndex i | + input.isInParameter(i) + ) and + output.isOutReturnValue() + } + + override predicate neverReadsMemory() { + any() + } + + override predicate neverWritesMemory() { + any() + } } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 548f71e3e605..0d35bda4a08a 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -779,24 +779,21 @@ ssa.cpp: # 198| r0_15(char *) = Load : &:r0_14, m0_6 # 198| r0_16(char *) = Convert : r0_15 # 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 198| m0_18(unknown) = ^CallSideEffect : ~m0_1 -# 198| m0_19(unknown) = Chi : total:m0_1, partial:m0_18 -# 198| m0_20(int) = Store : &:r0_9, r0_17 -# 199| r0_21(glval) = FunctionAddress[abs] : -# 199| r0_22(glval) = VariableAddress[x] : -# 199| r0_23(int) = Load : &:r0_22, m0_8 -# 199| r0_24(int) = Call : func:r0_21, 0:r0_23 -# 199| m0_25(unknown) = ^CallSideEffect : ~m0_19 -# 199| m0_26(unknown) = Chi : total:m0_19, partial:m0_25 -# 199| r0_27(glval) = VariableAddress[ret] : -# 199| r0_28(int) = Load : &:r0_27, m0_20 -# 199| r0_29(int) = Add : r0_28, r0_24 -# 199| m0_30(int) = Store : &:r0_27, r0_29 -# 200| r0_31(glval) = VariableAddress[#return] : -# 200| r0_32(glval) = VariableAddress[ret] : -# 200| r0_33(int) = Load : &:r0_32, m0_30 -# 200| m0_34(int) = Store : &:r0_31, r0_33 -# 197| r0_35(glval) = VariableAddress[#return] : -# 197| v0_36(void) = ReturnValue : &:r0_35, m0_34 -# 197| v0_37(void) = UnmodeledUse : mu* -# 197| v0_38(void) = ExitFunction : +# 198| v0_18(void) = ^CallReadSideEffect : ~m0_1 +# 198| m0_19(int) = Store : &:r0_9, r0_17 +# 199| r0_20(glval) = FunctionAddress[abs] : +# 199| r0_21(glval) = VariableAddress[x] : +# 199| r0_22(int) = Load : &:r0_21, m0_8 +# 199| r0_23(int) = Call : func:r0_20, 0:r0_22 +# 199| r0_24(glval) = VariableAddress[ret] : +# 199| r0_25(int) = Load : &:r0_24, m0_19 +# 199| r0_26(int) = Add : r0_25, r0_23 +# 199| m0_27(int) = Store : &:r0_24, r0_26 +# 200| r0_28(glval) = VariableAddress[#return] : +# 200| r0_29(glval) = VariableAddress[ret] : +# 200| r0_30(int) = Load : &:r0_29, m0_27 +# 200| m0_31(int) = Store : &:r0_28, r0_30 +# 197| r0_32(glval) = VariableAddress[#return] : +# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31 +# 197| v0_34(void) = UnmodeledUse : mu* +# 197| v0_35(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index ebf7f46d2c84..12f235280d47 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -745,22 +745,21 @@ ssa.cpp: # 198| r0_15(char *) = Load : &:r0_14, m0_6 # 198| r0_16(char *) = Convert : r0_15 # 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 198| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 198| v0_18(void) = ^CallReadSideEffect : ~mu0_2 # 198| m0_19(int) = Store : &:r0_9, r0_17 # 199| r0_20(glval) = FunctionAddress[abs] : # 199| r0_21(glval) = VariableAddress[x] : # 199| r0_22(int) = Load : &:r0_21, m0_8 # 199| r0_23(int) = Call : func:r0_20, 0:r0_22 -# 199| mu0_24(unknown) = ^CallSideEffect : ~mu0_2 -# 199| r0_25(glval) = VariableAddress[ret] : -# 199| r0_26(int) = Load : &:r0_25, m0_19 -# 199| r0_27(int) = Add : r0_26, r0_23 -# 199| m0_28(int) = Store : &:r0_25, r0_27 -# 200| r0_29(glval) = VariableAddress[#return] : -# 200| r0_30(glval) = VariableAddress[ret] : -# 200| r0_31(int) = Load : &:r0_30, m0_28 -# 200| m0_32(int) = Store : &:r0_29, r0_31 -# 197| r0_33(glval) = VariableAddress[#return] : -# 197| v0_34(void) = ReturnValue : &:r0_33, m0_32 -# 197| v0_35(void) = UnmodeledUse : mu* -# 197| v0_36(void) = ExitFunction : +# 199| r0_24(glval) = VariableAddress[ret] : +# 199| r0_25(int) = Load : &:r0_24, m0_19 +# 199| r0_26(int) = Add : r0_25, r0_23 +# 199| m0_27(int) = Store : &:r0_24, r0_26 +# 200| r0_28(glval) = VariableAddress[#return] : +# 200| r0_29(glval) = VariableAddress[ret] : +# 200| r0_30(int) = Load : &:r0_29, m0_27 +# 200| m0_31(int) = Store : &:r0_28, r0_30 +# 197| r0_32(glval) = VariableAddress[#return] : +# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31 +# 197| v0_34(void) = UnmodeledUse : mu* +# 197| v0_35(void) = ExitFunction : From 3804c1fbcf3df9db655e52d7ed11d3c932f2d0e5 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 9 Jul 2019 11:45:27 -0700 Subject: [PATCH 3/5] C++: model returns of strstr and strpbrk --- .../code/cpp/models/implementations/Pure.qll | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index b3aaed2cfb8b..7de857205295 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -23,7 +23,6 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side or name = "strnlen" or name = "strrchr" or name = "strspn" - or name = "strstr" or name = "strtod" or name = "strtof" or name = "strtol" @@ -38,6 +37,54 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side getParameter(bufParam).getUnspecifiedType() instanceof PointerType } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + exists (ParameterIndex i | + input.isInParameter(i) or + ( + input.isInParameterPointer(i) and + getParameter(i).getUnspecifiedType() instanceof PointerType + ) + ) and + ( + output.isOutReturnValue() + ) + } + + override predicate parameterNeverEscapes(int i) { + getParameter(i).getUnspecifiedType() instanceof PointerType + } + + override predicate parameterEscapesOnlyViaReturn(int i) { + none() + } + + override predicate parameterIsAlwaysReturned(int i) { + none() + } + + override predicate neverReadsMemory() { + none() + } + + override predicate neverWritesMemory() { + any() + } +} +class PureReturningStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { + PureReturningStrFunction() { + exists(string name | + hasName(name) and + ( + name = "strstr" or + name = "strpbrk" + ) + ) + } + + override predicate hasArrayInput(int bufParam) { + getParameter(bufParam).getUnspecifiedType() instanceof PointerType + } + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists (ParameterIndex i | input.isInParameter(i) or @@ -56,11 +103,11 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side } override predicate parameterNeverEscapes(int i) { - getParameter(i).getUnspecifiedType() instanceof PointerType + i = 1 } override predicate parameterEscapesOnlyViaReturn(int i) { - none() + i = 0 } override predicate parameterIsAlwaysReturned(int i) { From 72f9addd0b04086b60da2235dd1f563512459ec3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 10 Jul 2019 12:27:04 -0700 Subject: [PATCH 4/5] C++: move strstr back into main pure str model --- .../code/cpp/models/implementations/Pure.qll | 64 +++---------------- 1 file changed, 10 insertions(+), 54 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 7de857205295..3bc0e0956e8e 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -16,6 +16,8 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side or name = "strchnul" or name = "strchr" or name = "strchrnul" + or name = "strstr" + or name = "strpbrk" or name = "strcmp" or name = "strcspn" or name = "strlen" @@ -46,68 +48,22 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side ) ) and ( - output.isOutReturnValue() + output.isOutReturnValue() or + output.isOutReturnPointer() ) } override predicate parameterNeverEscapes(int i) { - getParameter(i).getUnspecifiedType() instanceof PointerType - } - - override predicate parameterEscapesOnlyViaReturn(int i) { - none() - } - - override predicate parameterIsAlwaysReturned(int i) { - none() - } - - override predicate neverReadsMemory() { - none() - } - - override predicate neverWritesMemory() { - any() - } -} -class PureReturningStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { - PureReturningStrFunction() { - exists(string name | - hasName(name) and - ( - name = "strstr" or - name = "strpbrk" - ) + getParameter(i).getUnspecifiedType() instanceof PointerType and + not ( + i = 0 and + getType().getUnspecifiedType() instanceof PointerType ) } - - override predicate hasArrayInput(int bufParam) { - getParameter(bufParam).getUnspecifiedType() instanceof PointerType - } - - override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { - exists (ParameterIndex i | - input.isInParameter(i) or - ( - input.isInParameterPointer(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType - ) - ) and - ( - ( - output.isOutReturnPointer() and - getUnspecifiedType() instanceof PointerType - ) or - output.isOutReturnValue() - ) - } - - override predicate parameterNeverEscapes(int i) { - i = 1 - } override predicate parameterEscapesOnlyViaReturn(int i) { - i = 0 + i = 0 and + getType().getUnspecifiedType() instanceof PointerType } override predicate parameterIsAlwaysReturned(int i) { From c195420ba1038144ae7560700de317dc2497cf44 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 11 Jul 2019 11:00:52 -0700 Subject: [PATCH 5/5] C++: respond to PR comments --- .../code/cpp/models/implementations/Pure.qll | 30 +++---- .../ir/ssa/aliased_ssa_ir.expected | 86 +++++++++++-------- cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 2 + .../ir/ssa/unaliased_ssa_ir.expected | 86 +++++++++++-------- 4 files changed, 113 insertions(+), 91 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index 3bc0e0956e8e..1b09d885b1eb 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -6,7 +6,7 @@ import semmle.code.cpp.models.interfaces.SideEffect class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { exists(string name | - hasName(name) and + hasGlobalName(name) and ( name = "atof" or name = "atoi" @@ -41,29 +41,28 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists (ParameterIndex i | - input.isInParameter(i) or - ( - input.isInParameterPointer(i) and - getParameter(i).getUnspecifiedType() instanceof PointerType - ) + input.isInParameter(i) and + exists(getParameter(i)) + or + input.isInParameterPointer(i) and + getParameter(i).getUnspecifiedType() instanceof PointerType ) and ( - output.isOutReturnValue() or - output.isOutReturnPointer() + output.isOutReturnPointer() and + getUnspecifiedType() instanceof PointerType + or + output.isOutReturnValue() ) } override predicate parameterNeverEscapes(int i) { getParameter(i).getUnspecifiedType() instanceof PointerType and - not ( - i = 0 and - getType().getUnspecifiedType() instanceof PointerType - ) + not parameterEscapesOnlyViaReturn(i) } override predicate parameterEscapesOnlyViaReturn(int i) { i = 0 and - getType().getUnspecifiedType() instanceof PointerType + getUnspecifiedType() instanceof PointerType } override predicate parameterIsAlwaysReturned(int i) { @@ -82,7 +81,7 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, Side class PureFunction extends TaintFunction, SideEffectFunction { PureFunction() { exists(string name | - hasName(name) and + hasGlobalName(name) and ( name = "abs" or name = "labs" @@ -92,7 +91,8 @@ class PureFunction extends TaintFunction, SideEffectFunction { override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { exists (ParameterIndex i | - input.isInParameter(i) + input.isInParameter(i) and + exists(getParameter(i)) ) and output.isOutReturnValue() } diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 0d35bda4a08a..fe11d99f31f6 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -759,41 +759,51 @@ ssa.cpp: # 184| v0_23(void) = UnmodeledUse : mu* # 184| v0_24(void) = ExitFunction : -# 197| int PureFunctions(char*, char*, int) -# 197| Block 0 -# 197| v0_0(void) = EnterFunction : -# 197| m0_1(unknown) = AliasedDefinition : -# 197| mu0_2(unknown) = UnmodeledDefinition : -# 197| r0_3(glval) = VariableAddress[str1] : -# 197| m0_4(char *) = InitializeParameter[str1] : &:r0_3 -# 197| r0_5(glval) = VariableAddress[str2] : -# 197| m0_6(char *) = InitializeParameter[str2] : &:r0_5 -# 197| r0_7(glval) = VariableAddress[x] : -# 197| m0_8(int) = InitializeParameter[x] : &:r0_7 -# 198| r0_9(glval) = VariableAddress[ret] : -# 198| r0_10(glval) = FunctionAddress[strcmp] : -# 198| r0_11(glval) = VariableAddress[str1] : -# 198| r0_12(char *) = Load : &:r0_11, m0_4 -# 198| r0_13(char *) = Convert : r0_12 -# 198| r0_14(glval) = VariableAddress[str2] : -# 198| r0_15(char *) = Load : &:r0_14, m0_6 -# 198| r0_16(char *) = Convert : r0_15 -# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 198| v0_18(void) = ^CallReadSideEffect : ~m0_1 -# 198| m0_19(int) = Store : &:r0_9, r0_17 -# 199| r0_20(glval) = FunctionAddress[abs] : -# 199| r0_21(glval) = VariableAddress[x] : -# 199| r0_22(int) = Load : &:r0_21, m0_8 -# 199| r0_23(int) = Call : func:r0_20, 0:r0_22 -# 199| r0_24(glval) = VariableAddress[ret] : -# 199| r0_25(int) = Load : &:r0_24, m0_19 -# 199| r0_26(int) = Add : r0_25, r0_23 -# 199| m0_27(int) = Store : &:r0_24, r0_26 -# 200| r0_28(glval) = VariableAddress[#return] : -# 200| r0_29(glval) = VariableAddress[ret] : -# 200| r0_30(int) = Load : &:r0_29, m0_27 -# 200| m0_31(int) = Store : &:r0_28, r0_30 -# 197| r0_32(glval) = VariableAddress[#return] : -# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31 -# 197| v0_34(void) = UnmodeledUse : mu* -# 197| v0_35(void) = ExitFunction : +# 198| int PureFunctions(char*, char*, int) +# 198| Block 0 +# 198| v0_0(void) = EnterFunction : +# 198| m0_1(unknown) = AliasedDefinition : +# 198| mu0_2(unknown) = UnmodeledDefinition : +# 198| r0_3(glval) = VariableAddress[str1] : +# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 198| r0_5(glval) = VariableAddress[str2] : +# 198| m0_6(char *) = InitializeParameter[str2] : &:r0_5 +# 198| r0_7(glval) = VariableAddress[x] : +# 198| m0_8(int) = InitializeParameter[x] : &:r0_7 +# 199| r0_9(glval) = VariableAddress[ret] : +# 199| r0_10(glval) = FunctionAddress[strcmp] : +# 199| r0_11(glval) = VariableAddress[str1] : +# 199| r0_12(char *) = Load : &:r0_11, m0_4 +# 199| r0_13(char *) = Convert : r0_12 +# 199| r0_14(glval) = VariableAddress[str2] : +# 199| r0_15(char *) = Load : &:r0_14, m0_6 +# 199| r0_16(char *) = Convert : r0_15 +# 199| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 +# 199| v0_18(void) = ^CallReadSideEffect : ~m0_1 +# 199| m0_19(int) = Store : &:r0_9, r0_17 +# 200| r0_20(glval) = FunctionAddress[strlen] : +# 200| r0_21(glval) = VariableAddress[str1] : +# 200| r0_22(char *) = Load : &:r0_21, m0_4 +# 200| r0_23(char *) = Convert : r0_22 +# 200| r0_24(int) = Call : func:r0_20, 0:r0_23 +# 200| v0_25(void) = ^CallReadSideEffect : ~m0_1 +# 200| r0_26(glval) = VariableAddress[ret] : +# 200| r0_27(int) = Load : &:r0_26, m0_19 +# 200| r0_28(int) = Add : r0_27, r0_24 +# 200| m0_29(int) = Store : &:r0_26, r0_28 +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 47f13846083e..8ada4a691f9c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -192,10 +192,12 @@ static void AsmStmtWithOutputs(unsigned int& a, unsigned int& b, unsigned int& c } int strcmp(const char *, const char *); +int strlen(const char *); int abs(int); int PureFunctions(char *str1, char *str2, int x) { int ret = strcmp(str1, str2); + ret += strlen(str1); ret += abs(x); return ret; } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 12f235280d47..ce0d93233404 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -725,41 +725,51 @@ ssa.cpp: # 184| v0_18(void) = UnmodeledUse : mu* # 184| v0_19(void) = ExitFunction : -# 197| int PureFunctions(char*, char*, int) -# 197| Block 0 -# 197| v0_0(void) = EnterFunction : -# 197| mu0_1(unknown) = AliasedDefinition : -# 197| mu0_2(unknown) = UnmodeledDefinition : -# 197| r0_3(glval) = VariableAddress[str1] : -# 197| m0_4(char *) = InitializeParameter[str1] : &:r0_3 -# 197| r0_5(glval) = VariableAddress[str2] : -# 197| m0_6(char *) = InitializeParameter[str2] : &:r0_5 -# 197| r0_7(glval) = VariableAddress[x] : -# 197| m0_8(int) = InitializeParameter[x] : &:r0_7 -# 198| r0_9(glval) = VariableAddress[ret] : -# 198| r0_10(glval) = FunctionAddress[strcmp] : -# 198| r0_11(glval) = VariableAddress[str1] : -# 198| r0_12(char *) = Load : &:r0_11, m0_4 -# 198| r0_13(char *) = Convert : r0_12 -# 198| r0_14(glval) = VariableAddress[str2] : -# 198| r0_15(char *) = Load : &:r0_14, m0_6 -# 198| r0_16(char *) = Convert : r0_15 -# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 198| v0_18(void) = ^CallReadSideEffect : ~mu0_2 -# 198| m0_19(int) = Store : &:r0_9, r0_17 -# 199| r0_20(glval) = FunctionAddress[abs] : -# 199| r0_21(glval) = VariableAddress[x] : -# 199| r0_22(int) = Load : &:r0_21, m0_8 -# 199| r0_23(int) = Call : func:r0_20, 0:r0_22 -# 199| r0_24(glval) = VariableAddress[ret] : -# 199| r0_25(int) = Load : &:r0_24, m0_19 -# 199| r0_26(int) = Add : r0_25, r0_23 -# 199| m0_27(int) = Store : &:r0_24, r0_26 -# 200| r0_28(glval) = VariableAddress[#return] : -# 200| r0_29(glval) = VariableAddress[ret] : -# 200| r0_30(int) = Load : &:r0_29, m0_27 -# 200| m0_31(int) = Store : &:r0_28, r0_30 -# 197| r0_32(glval) = VariableAddress[#return] : -# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31 -# 197| v0_34(void) = UnmodeledUse : mu* -# 197| v0_35(void) = ExitFunction : +# 198| int PureFunctions(char*, char*, int) +# 198| Block 0 +# 198| v0_0(void) = EnterFunction : +# 198| mu0_1(unknown) = AliasedDefinition : +# 198| mu0_2(unknown) = UnmodeledDefinition : +# 198| r0_3(glval) = VariableAddress[str1] : +# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 198| r0_5(glval) = VariableAddress[str2] : +# 198| m0_6(char *) = InitializeParameter[str2] : &:r0_5 +# 198| r0_7(glval) = VariableAddress[x] : +# 198| m0_8(int) = InitializeParameter[x] : &:r0_7 +# 199| r0_9(glval) = VariableAddress[ret] : +# 199| r0_10(glval) = FunctionAddress[strcmp] : +# 199| r0_11(glval) = VariableAddress[str1] : +# 199| r0_12(char *) = Load : &:r0_11, m0_4 +# 199| r0_13(char *) = Convert : r0_12 +# 199| r0_14(glval) = VariableAddress[str2] : +# 199| r0_15(char *) = Load : &:r0_14, m0_6 +# 199| r0_16(char *) = Convert : r0_15 +# 199| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 +# 199| v0_18(void) = ^CallReadSideEffect : ~mu0_2 +# 199| m0_19(int) = Store : &:r0_9, r0_17 +# 200| r0_20(glval) = FunctionAddress[strlen] : +# 200| r0_21(glval) = VariableAddress[str1] : +# 200| r0_22(char *) = Load : &:r0_21, m0_4 +# 200| r0_23(char *) = Convert : r0_22 +# 200| r0_24(int) = Call : func:r0_20, 0:r0_23 +# 200| v0_25(void) = ^CallReadSideEffect : ~mu0_2 +# 200| r0_26(glval) = VariableAddress[ret] : +# 200| r0_27(int) = Load : &:r0_26, m0_19 +# 200| r0_28(int) = Add : r0_27, r0_24 +# 200| m0_29(int) = Store : &:r0_26, r0_28 +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction :