From bd396985285562a4bb5f2a5eb6c925f8c87af25c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 17 Jan 2019 13:11:14 -0800 Subject: [PATCH 01/17] C++: test changes for interproc escape analysis --- .../test/library-tests/ir/escape/escape.cpp | 74 +++++ .../ir/escape/points_to.expected | 276 +++++++++++------- .../ir/escape/ssa_escape.expected | 5 + 3 files changed, 247 insertions(+), 108 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/escape/escape.cpp b/cpp/ql/test/library-tests/ir/escape/escape.cpp index 8a3e57a25d2..9a9d2884a9f 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.cpp +++ b/cpp/ql/test/library-tests/ir/escape/escape.cpp @@ -1,5 +1,44 @@ void CallByPointer(int* p); void CallByReference(int& r); +int *GetPointer(); +int &GetReference(); + +int FetchFromPointer(int *no_p) { + return *no_p; +} + +int FetchFromReference(int &no_r) { + return no_r; +} + +int *ReturnPointer(int *no_p) { + return no_p; +} + +int &ReturnReference(int &no_r) { + return no_r; +} + +void CallByPointerParamEscape(int *no_p) { + CallByPointer(no_p); +} + +void CallByReferenceParamEscape(int &no_r) { + CallByReference(no_r); +} + +int *MaybeReturn(int *no_p, int *no_q, bool no_b) { + if (no_b) { + return no_p; + } else { + return no_q; + } +} + +int &EscapeAndReturn(int &no_r) { + CallByReference(no_r); + return no_r; +} struct Point { float x; @@ -95,4 +134,39 @@ void Escape() int passByRef; CallByReference(passByRef); + + int no_ssa_passByPtr; + FetchFromPointer(&no_ssa_passByPtr); + + int no_ssa_passByRef; + FetchFromReference(no_ssa_passByRef); + + int no_ssa_passByPtr_ret; + FetchFromPointer(&no_ssa_passByPtr_ret); + + int no_ssa_passByRef_ret; + FetchFromReference(no_ssa_passByRef_ret); + + int passByPtr2; + CallByPointerParamEscape(&passByPtr2); + + int passByRef2; + CallByReferenceParamEscape(passByRef2); + + int passByPtr3; + CallByPointerParamEscape(ReturnPointer(&passByPtr3)); + + int passByRef3; + CallByReferenceParamEscape(ReturnReference(passByRef3)); + + int passByPtr4; + int passByPtr5; + bool no_b2 = false; + MaybeReturn(&passByPtr4, &passByPtr5, no_b2); + + int passByRef6; + EscapeAndReturn(passByRef6); + + int no_ssa_passByRef7; + ReturnReference(no_ssa_passByRef7); } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index 5d387a4b267..52aeb2df1e8 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,108 +1,168 @@ -| escape.cpp:32:9:32:17 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:33:9:33:11 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:35:5:35:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:36:5:36:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:36:11:36:13 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:37:5:37:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:37:17:37:19 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:38:5:38:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:38:19:38:21 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:40:5:40:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:41:6:41:8 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:42:5:42:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:42:19:42:28 | PointerAdd[4] | no_+0:0 | -| escape.cpp:42:21:42:23 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:43:5:43:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:43:19:43:28 | PointerSub[4] | no_+0:0 | -| escape.cpp:43:21:43:23 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:44:5:44:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:44:19:44:26 | PointerAdd[4] | no_+0:0 | -| escape.cpp:44:24:44:26 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:45:10:45:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:47:13:47:15 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:50:15:50:17 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:51:10:51:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:51:16:51:18 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:51:22:51:24 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:54:10:54:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:56:13:56:15 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:59:9:59:16 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:60:5:60:12 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:61:5:61:18 | Convert | no_Array+0:0 | -| escape.cpp:61:11:61:18 | Convert | no_Array+0:0 | -| escape.cpp:61:11:61:18 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:62:5:62:12 | Convert | no_Array+0:0 | -| escape.cpp:62:5:62:12 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:62:5:62:15 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:63:5:63:15 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:63:7:63:14 | Convert | no_Array+0:0 | -| escape.cpp:63:7:63:14 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:64:5:64:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:64:17:64:24 | Convert | no_Array+0:0 | -| escape.cpp:64:17:64:24 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:64:17:64:27 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:65:5:65:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:65:17:65:27 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:65:19:65:26 | Convert | no_Array+0:0 | -| escape.cpp:65:19:65:26 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:67:11:67:18 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:67:21:67:32 | FieldAddress[x] | no_Point+0:0 | -| escape.cpp:67:21:67:32 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:67:21:67:32 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:68:11:68:14 | VariableAddress[no_x] | no_x+0:0 | -| escape.cpp:68:18:68:25 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:68:27:68:27 | FieldAddress[x] | no_Point+0:0 | -| escape.cpp:69:5:69:12 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:69:14:69:14 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:69:18:69:21 | VariableAddress[no_x] | no_x+0:0 | -| escape.cpp:70:11:70:14 | VariableAddress[no_y] | no_y+0:0 | -| escape.cpp:70:20:70:27 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:70:31:70:31 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:71:7:71:14 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:71:18:71:18 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:71:22:71:25 | VariableAddress[no_y] | no_y+0:0 | -| escape.cpp:72:11:72:14 | VariableAddress[no_z] | no_z+0:0 | -| escape.cpp:72:21:72:28 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:72:30:72:30 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:73:8:73:15 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:73:17:73:17 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:73:22:73:25 | VariableAddress[no_z] | no_z+0:0 | -| escape.cpp:75:13:75:22 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:76:5:76:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | -| escape.cpp:76:5:76:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | -| escape.cpp:76:5:76:14 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:76:16:76:16 | FieldAddress[b] | no_Derived+0:0 | -| escape.cpp:77:11:77:14 | VariableAddress[no_b] | no_b+0:0 | -| escape.cpp:77:18:77:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | -| escape.cpp:77:18:77:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | -| escape.cpp:77:18:77:27 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:77:29:77:29 | FieldAddress[b] | no_Derived+0:0 | -| escape.cpp:78:5:78:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | -| escape.cpp:78:5:78:14 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:78:16:78:17 | FieldAddress[i2] | no_Derived+16:0 | -| escape.cpp:79:11:79:15 | VariableAddress[no_i2] | no_i2+0:0 | -| escape.cpp:79:19:79:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | -| escape.cpp:79:19:79:28 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:79:30:79:31 | FieldAddress[i2] | no_Derived+16:0 | -| escape.cpp:81:9:81:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | -| escape.cpp:82:10:82:13 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:82:17:82:30 | Store | no_ssa_addrOf+0:0 | -| escape.cpp:82:18:82:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | -| escape.cpp:84:9:84:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | -| escape.cpp:85:10:85:13 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:85:17:85:28 | Store | no_ssa_refTo+0:0 | -| escape.cpp:85:17:85:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | -| escape.cpp:87:9:87:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | -| escape.cpp:88:10:88:15 | VariableAddress[no_rae] | no_rae+0:0 | -| escape.cpp:88:19:88:42 | Convert | no_ssa_refToArrayElement+0:0 | -| escape.cpp:88:19:88:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | -| escape.cpp:88:19:88:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | -| escape.cpp:88:19:88:45 | Store | no_ssa_refToArrayElement+20:0 | -| escape.cpp:90:9:90:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | -| escape.cpp:91:11:91:15 | VariableAddress[no_ra] | no_ra+0:0 | -| escape.cpp:91:24:91:40 | Store | no_ssa_refToArray+0:0 | -| escape.cpp:91:24:91:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | -| escape.cpp:93:9:93:17 | VariableAddress[passByPtr] | passByPtr+0:0 | -| escape.cpp:94:20:94:28 | VariableAddress[passByPtr] | passByPtr+0:0 | -| escape.cpp:96:9:96:17 | VariableAddress[passByRef] | passByRef+0:0 | -| escape.cpp:97:21:97:29 | VariableAddress[passByRef] | passByRef+0:0 | +| escape.cpp:6:5:6:20 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:6:27:6:30 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:7:3:7:15 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:7:11:7:14 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:10:5:10:22 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:10:29:10:32 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:11:3:11:14 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:11:10:11:13 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:14:6:14:18 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:14:25:14:28 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:15:3:15:14 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:15:10:15:13 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:18:6:18:20 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:18:27:18:30 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:19:3:19:14 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:19:10:19:13 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:22:36:22:39 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:23:17:23:20 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:26:38:26:41 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:27:19:27:22 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:30:6:30:16 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:30:23:30:26 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:30:34:30:37 | VariableAddress[no_q] | no_q+0:0 | +| escape.cpp:30:45:30:48 | VariableAddress[no_b] | no_b+0:0 | +| escape.cpp:31:7:31:10 | VariableAddress[no_b] | no_b+0:0 | +| escape.cpp:32:5:32:16 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:32:12:32:15 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:34:5:34:16 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:34:12:34:15 | VariableAddress[no_q] | no_q+0:0 | +| escape.cpp:38:6:38:20 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:40:3:40:14 | VariableAddress[#return] | #return+0:0 | +| escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:71:9:71:17 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:72:9:72:11 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:74:5:74:7 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:75:5:75:7 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:75:11:75:13 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:76:5:76:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:76:17:76:19 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:77:5:77:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:77:19:77:21 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:79:5:79:7 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:80:6:80:8 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:81:5:81:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:81:19:81:28 | PointerAdd[4] | no_+0:0 | +| escape.cpp:81:21:81:23 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:82:5:82:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:82:19:82:28 | PointerSub[4] | no_+0:0 | +| escape.cpp:82:21:82:23 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:83:5:83:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:83:19:83:26 | PointerAdd[4] | no_+0:0 | +| escape.cpp:83:24:83:26 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:84:10:84:12 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:86:13:86:15 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:89:15:89:17 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:90:10:90:12 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:90:16:90:18 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:90:22:90:24 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:93:10:93:12 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:95:13:95:15 | VariableAddress[no_] | no_+0:0 | +| escape.cpp:98:9:98:16 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:99:5:99:12 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:100:5:100:18 | Convert | no_Array+0:0 | +| escape.cpp:100:11:100:18 | Convert | no_Array+0:0 | +| escape.cpp:100:11:100:18 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:101:5:101:12 | Convert | no_Array+0:0 | +| escape.cpp:101:5:101:12 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:101:5:101:15 | PointerAdd[4] | no_Array+20:0 | +| escape.cpp:102:5:102:15 | PointerAdd[4] | no_Array+20:0 | +| escape.cpp:102:7:102:14 | Convert | no_Array+0:0 | +| escape.cpp:102:7:102:14 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:103:5:103:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:103:17:103:24 | Convert | no_Array+0:0 | +| escape.cpp:103:17:103:24 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:103:17:103:27 | PointerAdd[4] | no_Array+20:0 | +| escape.cpp:104:5:104:13 | VariableAddress[no_result] | no_result+0:0 | +| escape.cpp:104:17:104:27 | PointerAdd[4] | no_Array+20:0 | +| escape.cpp:104:19:104:26 | Convert | no_Array+0:0 | +| escape.cpp:104:19:104:26 | VariableAddress[no_Array] | no_Array+0:0 | +| escape.cpp:106:11:106:18 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:106:21:106:32 | FieldAddress[x] | no_Point+0:0 | +| escape.cpp:106:21:106:32 | FieldAddress[y] | no_Point+4:0 | +| escape.cpp:106:21:106:32 | FieldAddress[z] | no_Point+8:0 | +| escape.cpp:107:11:107:14 | VariableAddress[no_x] | no_x+0:0 | +| escape.cpp:107:18:107:25 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:107:27:107:27 | FieldAddress[x] | no_Point+0:0 | +| escape.cpp:108:5:108:12 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:108:14:108:14 | FieldAddress[y] | no_Point+4:0 | +| escape.cpp:108:18:108:21 | VariableAddress[no_x] | no_x+0:0 | +| escape.cpp:109:11:109:14 | VariableAddress[no_y] | no_y+0:0 | +| escape.cpp:109:20:109:27 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:109:31:109:31 | FieldAddress[y] | no_Point+4:0 | +| escape.cpp:110:7:110:14 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:110:18:110:18 | FieldAddress[y] | no_Point+4:0 | +| escape.cpp:110:22:110:25 | VariableAddress[no_y] | no_y+0:0 | +| escape.cpp:111:11:111:14 | VariableAddress[no_z] | no_z+0:0 | +| escape.cpp:111:21:111:28 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:111:30:111:30 | FieldAddress[z] | no_Point+8:0 | +| escape.cpp:112:8:112:15 | VariableAddress[no_Point] | no_Point+0:0 | +| escape.cpp:112:17:112:17 | FieldAddress[z] | no_Point+8:0 | +| escape.cpp:112:22:112:25 | VariableAddress[no_z] | no_z+0:0 | +| escape.cpp:114:13:114:22 | VariableAddress[no_Derived] | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | VariableAddress[no_Derived] | no_Derived+0:0 | +| escape.cpp:115:16:115:16 | FieldAddress[b] | no_Derived+0:0 | +| escape.cpp:116:11:116:14 | VariableAddress[no_b] | no_b+0:0 | +| escape.cpp:116:18:116:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | +| escape.cpp:116:18:116:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | +| escape.cpp:116:18:116:27 | VariableAddress[no_Derived] | no_Derived+0:0 | +| escape.cpp:116:29:116:29 | FieldAddress[b] | no_Derived+0:0 | +| escape.cpp:117:5:117:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | +| escape.cpp:117:5:117:14 | VariableAddress[no_Derived] | no_Derived+0:0 | +| escape.cpp:117:16:117:17 | FieldAddress[i2] | no_Derived+16:0 | +| escape.cpp:118:11:118:15 | VariableAddress[no_i2] | no_i2+0:0 | +| escape.cpp:118:19:118:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | +| escape.cpp:118:19:118:28 | VariableAddress[no_Derived] | no_Derived+0:0 | +| escape.cpp:118:30:118:31 | FieldAddress[i2] | no_Derived+16:0 | +| escape.cpp:120:9:120:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | +| escape.cpp:121:10:121:13 | VariableAddress[no_p] | no_p+0:0 | +| escape.cpp:121:17:121:30 | Store | no_ssa_addrOf+0:0 | +| escape.cpp:121:18:121:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | +| escape.cpp:123:9:123:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | +| escape.cpp:124:10:124:13 | VariableAddress[no_r] | no_r+0:0 | +| escape.cpp:124:17:124:28 | Store | no_ssa_refTo+0:0 | +| escape.cpp:124:17:124:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | +| escape.cpp:126:9:126:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:10:127:15 | VariableAddress[no_rae] | no_rae+0:0 | +| escape.cpp:127:19:127:42 | Convert | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:19:127:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:19:127:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | +| escape.cpp:127:19:127:45 | Store | no_ssa_refToArrayElement+20:0 | +| escape.cpp:129:9:129:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | +| escape.cpp:130:11:130:15 | VariableAddress[no_ra] | no_ra+0:0 | +| escape.cpp:130:24:130:40 | Store | no_ssa_refToArray+0:0 | +| escape.cpp:130:24:130:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | +| escape.cpp:132:9:132:17 | VariableAddress[passByPtr] | passByPtr+0:0 | +| escape.cpp:133:20:133:28 | VariableAddress[passByPtr] | passByPtr+0:0 | +| escape.cpp:135:9:135:17 | VariableAddress[passByRef] | passByRef+0:0 | +| escape.cpp:136:21:136:29 | VariableAddress[passByRef] | passByRef+0:0 | +| escape.cpp:138:9:138:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | +| escape.cpp:139:23:139:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | +| escape.cpp:141:9:141:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | +| escape.cpp:142:24:142:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | +| escape.cpp:144:9:144:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:145:23:145:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:147:9:147:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | +| escape.cpp:148:24:148:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | +| escape.cpp:150:9:150:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | +| escape.cpp:151:31:151:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | +| escape.cpp:153:9:153:18 | VariableAddress[passByRef2] | passByRef2+0:0 | +| escape.cpp:154:32:154:41 | VariableAddress[passByRef2] | passByRef2+0:0 | +| escape.cpp:156:9:156:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | +| escape.cpp:157:45:157:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | +| escape.cpp:159:9:159:18 | VariableAddress[passByRef3] | passByRef3+0:0 | +| escape.cpp:160:48:160:57 | VariableAddress[passByRef3] | passByRef3+0:0 | +| escape.cpp:162:9:162:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | +| escape.cpp:163:9:163:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | +| escape.cpp:164:10:164:14 | VariableAddress[no_b2] | no_b2+0:0 | +| escape.cpp:165:18:165:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | +| escape.cpp:165:31:165:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | +| escape.cpp:165:43:165:47 | VariableAddress[no_b2] | no_b2+0:0 | +| escape.cpp:167:9:167:18 | VariableAddress[passByRef6] | passByRef6+0:0 | +| escape.cpp:168:21:168:30 | VariableAddress[passByRef6] | passByRef6+0:0 | +| escape.cpp:170:9:170:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | +| escape.cpp:171:21:171:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | diff --git a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected index e69de29bb2d..966a7a40b96 100644 --- a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected @@ -0,0 +1,5 @@ +| escape.cpp:138:9:138:24 | no_ssa_passByPtr | +| escape.cpp:141:9:141:24 | no_ssa_passByRef | +| escape.cpp:144:9:144:28 | no_ssa_passByPtr_ret | +| escape.cpp:147:9:147:28 | no_ssa_passByRef_ret | +| escape.cpp:170:9:170:25 | no_ssa_passByRef7 | From 466e110338ad30cab33a596db705d0ceb6e062bb Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 17 Jan 2019 15:59:15 -0800 Subject: [PATCH 02/17] C++: add new interprocedural escape analysis --- .../aliased_ssa/Instruction.qll | 7 + .../aliased_ssa/internal/AliasAnalysis.qll | 79 ++++- .../cpp/ir/implementation/raw/Instruction.qll | 7 + .../unaliased_ssa/Instruction.qll | 7 + .../unaliased_ssa/internal/AliasAnalysis.qll | 79 ++++- .../ir/escape/points_to.expected | 327 +++++++++--------- .../test/library-tests/ir/escape/points_to.ql | 36 +- .../ir/escape/ssa_escape.expected | 5 - 8 files changed, 359 insertions(+), 188 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index fb25314f230..8335469612a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1310,6 +1310,13 @@ class CallInstruction extends Instruction { result = getAnOperand() } + /** + * Gets the `Function` that the call targets, if this is statically known. + */ + final Function getStaticCallTarget() { + result = getCallTarget().(FunctionInstruction).getFunctionSymbol() + } + /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 7ad949a1a8c..907fcf866e4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -62,7 +62,6 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { ) ) } - /** * If the result of instruction `instr` is an integer constant, returns the * value of that constant. Otherwise, returns unknown. @@ -143,7 +142,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { * Holds if any address held in operand number `tag` of instruction `instr` * escapes outside the domain of the analysis. */ -predicate operandEscapes(Operand operand) { + predicate operandEscapes(Operand operand) { // Conservatively assume that the address escapes unless one of the following // holds: not ( @@ -152,9 +151,66 @@ predicate operandEscapes(Operand operand) { // The address is propagated to the result of the instruction, but that // result does not itself escape. operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) + or + // The address is passed as an argument to a function from which it does not escape + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + not resultEscapesNonReturn(ipi) and + ( + not resultReturned(ipi) + or + not resultEscapes(operand.getUseInstruction()) + ) + ) ) } +predicate operandEscapesNonReturn(Operand operand) { + // Conservatively assume that the address escapes unless one of the following + // holds: + not ( + // The operand is used in a way that does not escape the instruction + operandIsConsumedWithoutEscaping(operand) or + // The address is propagated to the result of the instruction, but that + // result does not itself escape. + operandIsPropagated(operand, _) and + not resultEscapesNonReturn(operand.getUseInstruction()) + or + // The operand is used in a function call from which the operand does not escape + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + not resultEscapesNonReturn(ipi) and + not resultEscapesNonReturn(ci) + ) or + operand instanceof ReturnValueOperand + ) +} + +predicate operandReturned(Operand operand) { + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + resultReturned(ipi) and + resultReturned(ci) + ) + or + // The address is returned + operand instanceof ReturnValueOperand +} + +predicate resultReturned(Instruction instr) { + operandReturned(instr.getAUse()) +} + /** * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. @@ -164,6 +220,11 @@ predicate resultEscapes(Instruction instr) { operandEscapes(instr.getAUse()) } + predicate resultEscapesNonReturn(Instruction instr) { + // The result escapes if it has at least one use that escapes. + operandEscapesNonReturn(instr.getAUse()) +} + /** * Holds if the address of the specified local variable or parameter escapes the * domain of the analysis. @@ -176,7 +237,7 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { exists(VariableAddressInstruction instr | instr.getEnclosingFunctionIR() = funcIR and instr.getVariable() = var and - resultEscapes(instr) + resultEscapesNonReturn(instr) ) ) } @@ -207,7 +268,17 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) // If an operand is propagated, then the result points to the same variable, // offset by the bit offset from the propagation. resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and - operandIsPropagated(operand, propagatedBitOffset) and + ( + operandIsPropagated(operand, propagatedBitOffset) + or + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + resultReturned(ipi) and + propagatedBitOffset = Ints::unknown() + ) + ) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index fb25314f230..8335469612a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1310,6 +1310,13 @@ class CallInstruction extends Instruction { result = getAnOperand() } + /** + * Gets the `Function` that the call targets, if this is statically known. + */ + final Function getStaticCallTarget() { + result = getCallTarget().(FunctionInstruction).getFunctionSymbol() + } + /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index fb25314f230..8335469612a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1310,6 +1310,13 @@ class CallInstruction extends Instruction { result = getAnOperand() } + /** + * Gets the `Function` that the call targets, if this is statically known. + */ + final Function getStaticCallTarget() { + result = getCallTarget().(FunctionInstruction).getFunctionSymbol() + } + /** * Gets all of the arguments of the call, including the `this` pointer, if any. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 7ad949a1a8c..907fcf866e4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -62,7 +62,6 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { ) ) } - /** * If the result of instruction `instr` is an integer constant, returns the * value of that constant. Otherwise, returns unknown. @@ -143,7 +142,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { * Holds if any address held in operand number `tag` of instruction `instr` * escapes outside the domain of the analysis. */ -predicate operandEscapes(Operand operand) { + predicate operandEscapes(Operand operand) { // Conservatively assume that the address escapes unless one of the following // holds: not ( @@ -152,9 +151,66 @@ predicate operandEscapes(Operand operand) { // The address is propagated to the result of the instruction, but that // result does not itself escape. operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) + or + // The address is passed as an argument to a function from which it does not escape + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + not resultEscapesNonReturn(ipi) and + ( + not resultReturned(ipi) + or + not resultEscapes(operand.getUseInstruction()) + ) + ) ) } +predicate operandEscapesNonReturn(Operand operand) { + // Conservatively assume that the address escapes unless one of the following + // holds: + not ( + // The operand is used in a way that does not escape the instruction + operandIsConsumedWithoutEscaping(operand) or + // The address is propagated to the result of the instruction, but that + // result does not itself escape. + operandIsPropagated(operand, _) and + not resultEscapesNonReturn(operand.getUseInstruction()) + or + // The operand is used in a function call from which the operand does not escape + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + not resultEscapesNonReturn(ipi) and + not resultEscapesNonReturn(ci) + ) or + operand instanceof ReturnValueOperand + ) +} + +predicate operandReturned(Operand operand) { + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + resultReturned(ipi) and + resultReturned(ci) + ) + or + // The address is returned + operand instanceof ReturnValueOperand +} + +predicate resultReturned(Instruction instr) { + operandReturned(instr.getAUse()) +} + /** * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. @@ -164,6 +220,11 @@ predicate resultEscapes(Instruction instr) { operandEscapes(instr.getAUse()) } + predicate resultEscapesNonReturn(Instruction instr) { + // The result escapes if it has at least one use that escapes. + operandEscapesNonReturn(instr.getAUse()) +} + /** * Holds if the address of the specified local variable or parameter escapes the * domain of the analysis. @@ -176,7 +237,7 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { exists(VariableAddressInstruction instr | instr.getEnclosingFunctionIR() = funcIR and instr.getVariable() = var and - resultEscapes(instr) + resultEscapesNonReturn(instr) ) ) } @@ -207,7 +268,17 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) // If an operand is propagated, then the result points to the same variable, // offset by the bit offset from the propagation. resultPointsTo(operand.getDefinitionInstruction(), var, originalBitOffset) and - operandIsPropagated(operand, propagatedBitOffset) and + ( + operandIsPropagated(operand, propagatedBitOffset) + or + exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and + resultReturned(ipi) and + propagatedBitOffset = Ints::unknown() + ) + ) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) ) } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index 52aeb2df1e8..7add883d333 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,168 +1,159 @@ -| escape.cpp:6:5:6:20 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:6:27:6:30 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:7:3:7:15 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:7:11:7:14 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:10:5:10:22 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:10:29:10:32 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:11:3:11:14 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:11:10:11:13 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:14:6:14:18 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:14:25:14:28 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:15:3:15:14 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:15:10:15:13 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:18:6:18:20 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:18:27:18:30 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:19:3:19:14 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:19:10:19:13 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:22:36:22:39 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:23:17:23:20 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:26:38:26:41 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:27:19:27:22 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:30:6:30:16 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:30:23:30:26 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:30:34:30:37 | VariableAddress[no_q] | no_q+0:0 | -| escape.cpp:30:45:30:48 | VariableAddress[no_b] | no_b+0:0 | -| escape.cpp:31:7:31:10 | VariableAddress[no_b] | no_b+0:0 | -| escape.cpp:32:5:32:16 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:32:12:32:15 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:34:5:34:16 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:34:12:34:15 | VariableAddress[no_q] | no_q+0:0 | -| escape.cpp:38:6:38:20 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:40:3:40:14 | VariableAddress[#return] | #return+0:0 | -| escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:71:9:71:17 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:72:9:72:11 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:74:5:74:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:75:5:75:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:75:11:75:13 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:76:5:76:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:76:17:76:19 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:77:5:77:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:77:19:77:21 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:79:5:79:7 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:80:6:80:8 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:81:5:81:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:81:19:81:28 | PointerAdd[4] | no_+0:0 | -| escape.cpp:81:21:81:23 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:82:5:82:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:82:19:82:28 | PointerSub[4] | no_+0:0 | -| escape.cpp:82:21:82:23 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:83:5:83:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:83:19:83:26 | PointerAdd[4] | no_+0:0 | -| escape.cpp:83:24:83:26 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:84:10:84:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:86:13:86:15 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:89:15:89:17 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:90:10:90:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:90:16:90:18 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:90:22:90:24 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:93:10:93:12 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:95:13:95:15 | VariableAddress[no_] | no_+0:0 | -| escape.cpp:98:9:98:16 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:99:5:99:12 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:100:5:100:18 | Convert | no_Array+0:0 | -| escape.cpp:100:11:100:18 | Convert | no_Array+0:0 | -| escape.cpp:100:11:100:18 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:101:5:101:12 | Convert | no_Array+0:0 | -| escape.cpp:101:5:101:12 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:101:5:101:15 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:102:5:102:15 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:102:7:102:14 | Convert | no_Array+0:0 | -| escape.cpp:102:7:102:14 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:103:5:103:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:103:17:103:24 | Convert | no_Array+0:0 | -| escape.cpp:103:17:103:24 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:103:17:103:27 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:104:5:104:13 | VariableAddress[no_result] | no_result+0:0 | -| escape.cpp:104:17:104:27 | PointerAdd[4] | no_Array+20:0 | -| escape.cpp:104:19:104:26 | Convert | no_Array+0:0 | -| escape.cpp:104:19:104:26 | VariableAddress[no_Array] | no_Array+0:0 | -| escape.cpp:106:11:106:18 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:106:21:106:32 | FieldAddress[x] | no_Point+0:0 | -| escape.cpp:106:21:106:32 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:106:21:106:32 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:107:11:107:14 | VariableAddress[no_x] | no_x+0:0 | -| escape.cpp:107:18:107:25 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:107:27:107:27 | FieldAddress[x] | no_Point+0:0 | -| escape.cpp:108:5:108:12 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:108:14:108:14 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:108:18:108:21 | VariableAddress[no_x] | no_x+0:0 | -| escape.cpp:109:11:109:14 | VariableAddress[no_y] | no_y+0:0 | -| escape.cpp:109:20:109:27 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:109:31:109:31 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:110:7:110:14 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:110:18:110:18 | FieldAddress[y] | no_Point+4:0 | -| escape.cpp:110:22:110:25 | VariableAddress[no_y] | no_y+0:0 | -| escape.cpp:111:11:111:14 | VariableAddress[no_z] | no_z+0:0 | -| escape.cpp:111:21:111:28 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:111:30:111:30 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:112:8:112:15 | VariableAddress[no_Point] | no_Point+0:0 | -| escape.cpp:112:17:112:17 | FieldAddress[z] | no_Point+8:0 | -| escape.cpp:112:22:112:25 | VariableAddress[no_z] | no_z+0:0 | -| escape.cpp:114:13:114:22 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:115:16:115:16 | FieldAddress[b] | no_Derived+0:0 | -| escape.cpp:116:11:116:14 | VariableAddress[no_b] | no_b+0:0 | -| escape.cpp:116:18:116:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | -| escape.cpp:116:18:116:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | -| escape.cpp:116:18:116:27 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:116:29:116:29 | FieldAddress[b] | no_Derived+0:0 | -| escape.cpp:117:5:117:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | -| escape.cpp:117:5:117:14 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:117:16:117:17 | FieldAddress[i2] | no_Derived+16:0 | -| escape.cpp:118:11:118:15 | VariableAddress[no_i2] | no_i2+0:0 | -| escape.cpp:118:19:118:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | -| escape.cpp:118:19:118:28 | VariableAddress[no_Derived] | no_Derived+0:0 | -| escape.cpp:118:30:118:31 | FieldAddress[i2] | no_Derived+16:0 | -| escape.cpp:120:9:120:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | -| escape.cpp:121:10:121:13 | VariableAddress[no_p] | no_p+0:0 | -| escape.cpp:121:17:121:30 | Store | no_ssa_addrOf+0:0 | -| escape.cpp:121:18:121:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | -| escape.cpp:123:9:123:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | -| escape.cpp:124:10:124:13 | VariableAddress[no_r] | no_r+0:0 | -| escape.cpp:124:17:124:28 | Store | no_ssa_refTo+0:0 | -| escape.cpp:124:17:124:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | -| escape.cpp:126:9:126:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:10:127:15 | VariableAddress[no_rae] | no_rae+0:0 | -| escape.cpp:127:19:127:42 | Convert | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:19:127:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:19:127:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | -| escape.cpp:127:19:127:45 | Store | no_ssa_refToArrayElement+20:0 | -| escape.cpp:129:9:129:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | -| escape.cpp:130:11:130:15 | VariableAddress[no_ra] | no_ra+0:0 | -| escape.cpp:130:24:130:40 | Store | no_ssa_refToArray+0:0 | -| escape.cpp:130:24:130:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | -| escape.cpp:132:9:132:17 | VariableAddress[passByPtr] | passByPtr+0:0 | -| escape.cpp:133:20:133:28 | VariableAddress[passByPtr] | passByPtr+0:0 | -| escape.cpp:135:9:135:17 | VariableAddress[passByRef] | passByRef+0:0 | -| escape.cpp:136:21:136:29 | VariableAddress[passByRef] | passByRef+0:0 | -| escape.cpp:138:9:138:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | -| escape.cpp:139:23:139:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | -| escape.cpp:141:9:141:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | -| escape.cpp:142:24:142:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | -| escape.cpp:144:9:144:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:145:23:145:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:147:9:147:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | -| escape.cpp:148:24:148:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | -| escape.cpp:150:9:150:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | -| escape.cpp:151:31:151:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | -| escape.cpp:153:9:153:18 | VariableAddress[passByRef2] | passByRef2+0:0 | -| escape.cpp:154:32:154:41 | VariableAddress[passByRef2] | passByRef2+0:0 | -| escape.cpp:156:9:156:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | -| escape.cpp:157:45:157:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | -| escape.cpp:159:9:159:18 | VariableAddress[passByRef3] | passByRef3+0:0 | -| escape.cpp:160:48:160:57 | VariableAddress[passByRef3] | passByRef3+0:0 | -| escape.cpp:162:9:162:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | -| escape.cpp:163:9:163:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | -| escape.cpp:164:10:164:14 | VariableAddress[no_b2] | no_b2+0:0 | -| escape.cpp:165:18:165:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | -| escape.cpp:165:31:165:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | -| escape.cpp:165:43:165:47 | VariableAddress[no_b2] | no_b2+0:0 | -| escape.cpp:167:9:167:18 | VariableAddress[passByRef6] | passByRef6+0:0 | -| escape.cpp:168:21:168:30 | VariableAddress[passByRef6] | passByRef6+0:0 | -| escape.cpp:170:9:170:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | -| escape.cpp:171:21:171:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | +| escape.cpp:6:27:6:30 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:7:11:7:14 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:10:29:10:32 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:11:10:11:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:14:25:14:28 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:15:10:15:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:18:27:18:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:19:10:19:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:22:36:22:39 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:23:17:23:20 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:26:38:26:41 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:27:19:27:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:30:23:30:26 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:30:34:30:37 | VariableAddress[no_q] | no_q+0:0 | no_q+0:0 | +| escape.cpp:30:45:30:48 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | +| escape.cpp:31:7:31:10 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | +| escape.cpp:32:12:32:15 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:34:12:34:15 | VariableAddress[no_q] | no_q+0:0 | no_q+0:0 | +| escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:71:9:71:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:72:9:72:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:74:5:74:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:75:5:75:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:75:11:75:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:76:5:76:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:76:17:76:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:77:5:77:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:77:19:77:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:79:5:79:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:80:6:80:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:81:5:81:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:81:19:81:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:81:21:81:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:82:5:82:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:82:19:82:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:82:21:82:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:83:5:83:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:83:19:83:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:83:24:83:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:84:10:84:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:86:13:86:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:89:15:89:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:90:10:90:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:90:16:90:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:90:22:90:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:93:10:93:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:95:13:95:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:98:9:98:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:99:5:99:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:100:5:100:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:100:11:100:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:100:11:100:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:101:5:101:12 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:101:5:101:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:101:5:101:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:102:5:102:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:102:7:102:14 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:102:7:102:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:103:5:103:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:103:17:103:24 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:103:17:103:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:103:17:103:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:104:5:104:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:104:17:104:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:104:19:104:26 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:104:19:104:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:106:11:106:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:106:21:106:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:106:21:106:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:106:21:106:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:107:11:107:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:107:18:107:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:107:27:107:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:108:5:108:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:108:14:108:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:108:18:108:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:109:11:109:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:109:20:109:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:109:31:109:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:110:7:110:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:110:18:110:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:110:22:110:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:111:11:111:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:111:21:111:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:111:30:111:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:112:8:112:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:112:17:112:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:112:22:112:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:114:13:114:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:115:5:115:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:115:16:115:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:116:11:116:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | +| escape.cpp:116:18:116:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:116:18:116:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:116:18:116:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:116:29:116:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:117:5:117:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:117:5:117:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:117:16:117:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:118:11:118:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | +| escape.cpp:118:19:118:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:118:19:118:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:118:30:118:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:120:9:120:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:121:10:121:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:121:17:121:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:121:18:121:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:123:9:123:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:124:10:124:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:124:17:124:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:124:17:124:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:126:9:126:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:10:127:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | +| escape.cpp:127:19:127:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:19:127:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:127:19:127:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:127:19:127:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:129:9:129:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:130:11:130:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | +| escape.cpp:130:24:130:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:130:24:130:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:132:9:132:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:133:20:133:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:135:9:135:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:136:21:136:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:138:9:138:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:139:23:139:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:141:9:141:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:142:24:142:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:144:9:144:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:145:23:145:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:147:9:147:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:148:24:148:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:150:9:150:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:151:31:151:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:153:9:153:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:154:32:154:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:156:9:156:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:157:30:157:42 | Call | none | passByPtr3+? | +| escape.cpp:157:45:157:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:159:9:159:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:160:32:160:46 | Call | none | passByRef3+? | +| escape.cpp:160:48:160:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:162:9:162:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:163:9:163:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:164:10:164:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:165:18:165:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:165:31:165:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:165:43:165:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:167:9:167:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:168:5:168:19 | Call | none | passByRef6+? | +| escape.cpp:168:21:168:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:170:9:170:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:171:5:171:19 | Call | none | no_ssa_passByRef7+? | +| escape.cpp:171:21:171:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.ql b/cpp/ql/test/library-tests/ir/escape/points_to.ql index 06b5e746853..19d767ce58f 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.ql +++ b/cpp/ql/test/library-tests/ir/escape/points_to.ql @@ -1,11 +1,33 @@ import default -import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.AliasAnalysis -import semmle.code.cpp.ir.implementation.raw.IR +import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.AliasAnalysis as RawAA +import semmle.code.cpp.ir.implementation.raw.IR as Raw +import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis as UnAA +import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as Un +import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction -from Instruction instr, string pointsTo +from Raw::Instruction rawInstr, Un::Instruction unInstr, string rawPointsTo, string unPointsTo where - exists(IRVariable var, int bitOffset | - resultPointsTo(instr, var, bitOffset) and - pointsTo = var.toString() + getBitOffsetString(bitOffset) + rawInstr = getOldInstruction(unInstr) and + ( + exists(Variable var, int rawBitOffset, int unBitOffset | + RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and + rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and + UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and + unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset) + ) + or + exists(Variable var, int unBitOffset | + not RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), _) and + rawPointsTo = "none" and + UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), unBitOffset) and + unPointsTo = var.toString() + UnAA::getBitOffsetString(unBitOffset) + ) + or + exists(Variable var, int rawBitOffset | + RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and + rawPointsTo = var.toString() + RawAA::getBitOffsetString(rawBitOffset) and + not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and + unPointsTo = "none" + ) ) -select instr.getLocation().toString(), instr.getOperationString(), pointsTo +select rawInstr.getLocation().toString(), rawInstr.getOperationString(), rawPointsTo, unPointsTo diff --git a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected index 966a7a40b96..e69de29bb2d 100644 --- a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected @@ -1,5 +0,0 @@ -| escape.cpp:138:9:138:24 | no_ssa_passByPtr | -| escape.cpp:141:9:141:24 | no_ssa_passByRef | -| escape.cpp:144:9:144:28 | no_ssa_passByPtr_ret | -| escape.cpp:147:9:147:28 | no_ssa_passByRef_ret | -| escape.cpp:170:9:170:25 | no_ssa_passByRef7 | From 608917255404beb39927de35a0bc43b85193b623 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 22 Jan 2019 10:59:20 -0800 Subject: [PATCH 03/17] C++: escape analysis for `this` parameters --- .../aliased_ssa/internal/AliasAnalysis.qll | 52 +++- .../unaliased_ssa/internal/AliasAnalysis.qll | 52 +++- .../test/library-tests/ir/escape/escape.cpp | 35 +++ .../ir/escape/points_to.expected | 289 +++++++++--------- 4 files changed, 270 insertions(+), 158 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 907fcf866e4..667b8225a61 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -153,13 +153,19 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or // The address is passed as an argument to a function from which it does not escape - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - not resultEscapesNonReturn(ipi) and ( - not resultReturned(ipi) + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + not resultEscapesNonReturn(init) and + ( + not resultReturned(init) or not resultEscapes(operand.getUseInstruction()) ) @@ -179,11 +185,17 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - not resultEscapesNonReturn(ipi) and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or operand instanceof ReturnValueOperand @@ -203,6 +215,20 @@ predicate operandReturned(Operand operand) { resultReturned(ci) ) or + exists(CallInstruction ci, FunctionIR f, Instruction init | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + resultReturned(init) and + resultReturned(ci) + ) + or // The address is returned operand instanceof ReturnValueOperand } @@ -271,11 +297,17 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) ( operandIsPropagated(operand, propagatedBitOffset) or - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - resultReturned(ipi) and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + resultReturned(init) and propagatedBitOffset = Ints::unknown() ) ) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 907fcf866e4..667b8225a61 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -153,13 +153,19 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or // The address is passed as an argument to a function from which it does not escape - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - not resultEscapesNonReturn(ipi) and ( - not resultReturned(ipi) + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + not resultEscapesNonReturn(init) and + ( + not resultReturned(init) or not resultEscapes(operand.getUseInstruction()) ) @@ -179,11 +185,17 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - not resultEscapesNonReturn(ipi) and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or operand instanceof ReturnValueOperand @@ -203,6 +215,20 @@ predicate operandReturned(Operand operand) { resultReturned(ci) ) or + exists(CallInstruction ci, FunctionIR f, Instruction init | + ci = operand.getUseInstruction() and + f.getFunction() = ci.getStaticCallTarget() and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + resultReturned(init) and + resultReturned(ci) + ) + or // The address is returned operand instanceof ReturnValueOperand } @@ -271,11 +297,17 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) ( operandIsPropagated(operand, propagatedBitOffset) or - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | + exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - resultReturned(ipi) and + ( + init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunctionIR() = f and + operand instanceof ThisArgumentOperand + ) and + resultReturned(init) and propagatedBitOffset = Ints::unknown() ) ) and diff --git a/cpp/ql/test/library-tests/ir/escape/escape.cpp b/cpp/ql/test/library-tests/ir/escape/escape.cpp index 9a9d2884a9f..223377db035 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.cpp +++ b/cpp/ql/test/library-tests/ir/escape/escape.cpp @@ -66,6 +66,21 @@ struct Derived : Intermediate1, Intermediate2 { float d; }; +class C; + +void CEscapes(C *no_c); + +class C { +public: + void ThisEscapes() { + CEscapes(this); + } + + C *ThisReturned() { + return this; + } +}; + void Escape() { int no_result; @@ -169,4 +184,24 @@ void Escape() int no_ssa_passByRef7; ReturnReference(no_ssa_passByRef7); + + C no_ssa_c; + + no_ssa_c.ThisReturned(); + + C c; + + c.ThisEscapes(); + + C c2; + + CEscapes(&c2); + + C c3; + + c3.ThisReturned()->ThisEscapes(); + + C c4; + + CEscapes(c4.ThisReturned()); } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index 7add883d333..a188b1e401e 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -19,141 +19,154 @@ | escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | | escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | | escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:71:9:71:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:72:9:72:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:74:5:74:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:75:5:75:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:75:11:75:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:76:5:76:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:76:17:76:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:77:5:77:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:77:19:77:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:79:5:79:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:80:6:80:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:81:5:81:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:81:19:81:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:81:21:81:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:82:5:82:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:82:19:82:28 | PointerSub[4] | no_+0:0 | no_+0:0 | -| escape.cpp:82:21:82:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:83:5:83:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:83:19:83:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:83:24:83:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:84:10:84:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:86:13:86:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:89:15:89:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:90:10:90:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:90:16:90:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:90:22:90:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:93:10:93:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:95:13:95:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:98:9:98:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:99:5:99:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:100:5:100:18 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:100:11:100:18 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:100:11:100:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:101:5:101:12 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:101:5:101:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:101:5:101:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:102:5:102:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:102:7:102:14 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:102:7:102:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:103:5:103:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:103:17:103:24 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:103:17:103:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:103:17:103:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:104:5:104:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:104:17:104:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:104:19:104:26 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:104:19:104:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:106:11:106:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:106:21:106:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:106:21:106:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:106:21:106:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:107:11:107:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:107:18:107:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:107:27:107:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:108:5:108:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:108:14:108:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:108:18:108:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:109:11:109:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:109:20:109:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:109:31:109:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:110:7:110:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:110:18:110:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:110:22:110:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:111:11:111:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:111:21:111:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:111:30:111:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:112:8:112:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:112:17:112:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:112:22:112:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:114:13:114:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:115:5:115:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:115:16:115:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:116:11:116:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | -| escape.cpp:116:18:116:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:116:18:116:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:116:18:116:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:116:29:116:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:117:5:117:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:117:5:117:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:117:16:117:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:118:11:118:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | -| escape.cpp:118:19:118:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:118:19:118:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:118:30:118:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:120:9:120:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:121:10:121:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:121:17:121:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:121:18:121:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:123:9:123:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:124:10:124:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:124:17:124:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:124:17:124:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:126:9:126:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:10:127:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | -| escape.cpp:127:19:127:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:19:127:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:127:19:127:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | -| escape.cpp:127:19:127:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | -| escape.cpp:129:9:129:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:130:11:130:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | -| escape.cpp:130:24:130:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:130:24:130:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:132:9:132:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:133:20:133:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:135:9:135:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:136:21:136:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:138:9:138:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:139:23:139:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:141:9:141:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:142:24:142:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:144:9:144:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:145:23:145:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:147:9:147:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:148:24:148:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:150:9:150:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:151:31:151:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:153:9:153:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:154:32:154:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:156:9:156:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:157:30:157:42 | Call | none | passByPtr3+? | -| escape.cpp:157:45:157:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:159:9:159:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:160:32:160:46 | Call | none | passByRef3+? | -| escape.cpp:160:48:160:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:162:9:162:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:163:9:163:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | -| escape.cpp:164:10:164:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:165:18:165:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:165:31:165:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | -| escape.cpp:165:43:165:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:167:9:167:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:168:5:168:19 | Call | none | passByRef6+? | -| escape.cpp:168:21:168:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:170:9:170:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | -| escape.cpp:171:5:171:19 | Call | none | no_ssa_passByRef7+? | -| escape.cpp:171:21:171:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:86:9:86:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:87:9:87:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:89:5:89:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:90:5:90:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:90:11:90:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:91:5:91:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:91:17:91:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:92:5:92:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:92:19:92:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:94:5:94:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:95:6:95:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:96:5:96:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:96:19:96:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:96:21:96:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:97:5:97:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:97:19:97:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:97:21:97:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:98:5:98:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:98:19:98:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:98:24:98:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:99:10:99:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:101:13:101:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:104:15:104:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:105:10:105:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:105:16:105:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:105:22:105:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:108:10:108:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:110:13:110:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:113:9:113:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:114:5:114:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:115:5:115:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:115:11:115:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:115:11:115:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:116:5:116:12 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:116:5:116:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:116:5:116:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:117:5:117:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:117:7:117:14 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:117:7:117:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:118:5:118:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:118:17:118:24 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:118:17:118:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:118:17:118:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:119:5:119:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:119:17:119:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:119:19:119:26 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:119:19:119:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:121:11:121:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:121:21:121:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:121:21:121:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:121:21:121:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:122:11:122:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:122:18:122:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:122:27:122:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:123:5:123:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:123:14:123:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:123:18:123:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:124:11:124:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:124:20:124:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:124:31:124:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:125:7:125:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:125:18:125:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:125:22:125:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:126:11:126:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:126:21:126:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:126:30:126:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:127:8:127:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:127:17:127:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:127:22:127:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:129:13:129:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:130:5:130:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:130:5:130:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:130:5:130:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:130:16:130:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:131:11:131:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | +| escape.cpp:131:18:131:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:131:18:131:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:131:18:131:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:131:29:131:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:132:5:132:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:132:5:132:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:132:16:132:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:133:11:133:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | +| escape.cpp:133:19:133:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:133:19:133:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:133:30:133:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:135:9:135:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:136:10:136:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:136:17:136:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:136:18:136:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:138:9:138:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:139:10:139:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:139:17:139:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:139:17:139:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:141:9:141:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:142:10:142:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | +| escape.cpp:142:19:142:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:142:19:142:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:142:19:142:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:142:19:142:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:144:9:144:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:145:11:145:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | +| escape.cpp:145:24:145:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:145:24:145:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:147:9:147:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:148:20:148:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:150:9:150:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:151:21:151:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:153:9:153:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:154:23:154:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:156:9:156:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:157:24:157:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:159:9:159:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:160:23:160:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:162:9:162:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:163:24:163:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:165:9:165:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:166:31:166:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:168:9:168:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:169:32:169:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:171:9:171:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:172:30:172:42 | Call | none | passByPtr3+? | +| escape.cpp:172:45:172:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:174:9:174:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:175:32:175:46 | Call | none | passByRef3+? | +| escape.cpp:175:48:175:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:177:9:177:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:178:9:178:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:179:10:179:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:180:18:180:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:180:31:180:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:180:43:180:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:182:9:182:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:183:5:183:19 | Call | none | passByRef6+? | +| escape.cpp:183:21:183:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:185:9:185:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:186:5:186:19 | Call | none | no_ssa_passByRef7+? | +| escape.cpp:186:21:186:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:188:7:188:14 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | +| escape.cpp:190:5:190:12 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | +| escape.cpp:190:14:190:25 | Call | none | no_ssa_c+? | +| escape.cpp:192:7:192:7 | VariableAddress[c] | c+0:0 | c+0:0 | +| escape.cpp:194:5:194:5 | VariableAddress[c] | c+0:0 | c+0:0 | +| escape.cpp:196:7:196:8 | VariableAddress[c2] | c2+0:0 | c2+0:0 | +| escape.cpp:198:15:198:16 | VariableAddress[c2] | c2+0:0 | c2+0:0 | +| escape.cpp:200:7:200:8 | VariableAddress[c3] | c3+0:0 | c3+0:0 | +| escape.cpp:202:5:202:6 | VariableAddress[c3] | c3+0:0 | c3+0:0 | +| escape.cpp:202:8:202:19 | Call | none | c3+? | +| escape.cpp:204:7:204:8 | VariableAddress[c4] | c4+0:0 | c4+0:0 | +| escape.cpp:206:14:206:15 | VariableAddress[c4] | c4+0:0 | c4+0:0 | +| escape.cpp:206:17:206:28 | Call | none | c4+? | From 2c94a8887d189f7e8b5ce3b2a26405f6d534a139 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 28 Jan 2019 14:33:50 -0800 Subject: [PATCH 04/17] C++: test for virtual functions in escape analysis --- .../test/library-tests/ir/escape/escape.cpp | 36 ++ .../library-tests/ir/escape/escape.expected | 1 + .../ir/escape/points_to.expected | 314 +++++++++--------- .../ir/escape/ssa_escape.expected | 2 + 4 files changed, 202 insertions(+), 151 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/escape/escape.cpp b/cpp/ql/test/library-tests/ir/escape/escape.cpp index 223377db035..96931aeea2d 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.cpp +++ b/cpp/ql/test/library-tests/ir/escape/escape.cpp @@ -79,6 +79,25 @@ public: C *ThisReturned() { return this; } + + virtual C *Overridden() { + CEscapes(this); + return nullptr; + } +}; + +class OverrideReturns : C { +public: + virtual C *Overridden() { + return this; + } +}; + +class OverrideNone : C { +public: + virtual C *Overridden() { + return nullptr; + } }; void Escape() @@ -204,4 +223,21 @@ void Escape() C c4; CEscapes(c4.ThisReturned()); + + C c5; + + c5.Overridden(); + + OverrideReturns or1; + or1.Overridden(); + + OverrideReturns or2; + CEscapes(or2.Overridden()); + + OverrideNone on1; + on1.Overridden(); + + OverrideNone on2; + CEscapes(on2.Overridden()); } + diff --git a/cpp/ql/test/library-tests/ir/escape/escape.expected b/cpp/ql/test/library-tests/ir/escape/escape.expected index e69de29bb2d..60c7a226e16 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/escape.expected @@ -0,0 +1 @@ +| escape.cpp:237:18:237:20 | on1 | diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index a188b1e401e..9ff401bc4e0 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -19,154 +19,166 @@ | escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | | escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | | escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:86:9:86:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:87:9:87:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:89:5:89:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:90:5:90:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:90:11:90:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:91:5:91:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:91:17:91:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:92:5:92:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:92:19:92:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:94:5:94:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:95:6:95:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:96:5:96:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:96:19:96:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:96:21:96:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:97:5:97:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:97:19:97:28 | PointerSub[4] | no_+0:0 | no_+0:0 | -| escape.cpp:97:21:97:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:98:5:98:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:98:19:98:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:98:24:98:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:99:10:99:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:101:13:101:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:104:15:104:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:105:10:105:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:105:16:105:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:105:22:105:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:108:10:108:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:110:13:110:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:113:9:113:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:114:5:114:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:115:5:115:18 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:115:11:115:18 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:115:11:115:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:116:5:116:12 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:116:5:116:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:116:5:116:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:117:5:117:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:117:7:117:14 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:117:7:117:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:118:5:118:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:118:17:118:24 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:118:17:118:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:118:17:118:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:119:5:119:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:119:17:119:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:119:19:119:26 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:119:19:119:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:121:11:121:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:121:21:121:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:121:21:121:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:121:21:121:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:122:11:122:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:122:18:122:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:122:27:122:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:123:5:123:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:123:14:123:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:123:18:123:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:124:11:124:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:124:20:124:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:124:31:124:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:125:7:125:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:125:18:125:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:125:22:125:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:126:11:126:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:126:21:126:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:126:30:126:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:127:8:127:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:127:17:127:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:127:22:127:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:129:13:129:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:130:5:130:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:130:5:130:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:130:5:130:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:130:16:130:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:131:11:131:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | -| escape.cpp:131:18:131:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:131:18:131:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:131:18:131:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:131:29:131:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:132:5:132:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:132:5:132:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:132:16:132:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:133:11:133:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | -| escape.cpp:133:19:133:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:133:19:133:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:133:30:133:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:135:9:135:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:136:10:136:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:136:17:136:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:136:18:136:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:138:9:138:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:139:10:139:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:139:17:139:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:139:17:139:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:141:9:141:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:142:10:142:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | -| escape.cpp:142:19:142:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:142:19:142:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:142:19:142:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | -| escape.cpp:142:19:142:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | -| escape.cpp:144:9:144:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:145:11:145:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | -| escape.cpp:145:24:145:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:145:24:145:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:147:9:147:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:148:20:148:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:150:9:150:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:151:21:151:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:153:9:153:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:154:23:154:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:156:9:156:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:157:24:157:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:159:9:159:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:160:23:160:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:162:9:162:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:163:24:163:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:165:9:165:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:166:31:166:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:168:9:168:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:169:32:169:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:171:9:171:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:172:30:172:42 | Call | none | passByPtr3+? | -| escape.cpp:172:45:172:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:174:9:174:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:175:32:175:46 | Call | none | passByRef3+? | -| escape.cpp:175:48:175:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:177:9:177:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:178:9:178:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | -| escape.cpp:179:10:179:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:180:18:180:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:180:31:180:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | -| escape.cpp:180:43:180:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:182:9:182:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:183:5:183:19 | Call | none | passByRef6+? | -| escape.cpp:183:21:183:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:185:9:185:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | -| escape.cpp:186:5:186:19 | Call | none | no_ssa_passByRef7+? | -| escape.cpp:186:21:186:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | -| escape.cpp:188:7:188:14 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | -| escape.cpp:190:5:190:12 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | -| escape.cpp:190:14:190:25 | Call | none | no_ssa_c+? | -| escape.cpp:192:7:192:7 | VariableAddress[c] | c+0:0 | c+0:0 | -| escape.cpp:194:5:194:5 | VariableAddress[c] | c+0:0 | c+0:0 | -| escape.cpp:196:7:196:8 | VariableAddress[c2] | c2+0:0 | c2+0:0 | -| escape.cpp:198:15:198:16 | VariableAddress[c2] | c2+0:0 | c2+0:0 | -| escape.cpp:200:7:200:8 | VariableAddress[c3] | c3+0:0 | c3+0:0 | -| escape.cpp:202:5:202:6 | VariableAddress[c3] | c3+0:0 | c3+0:0 | -| escape.cpp:202:8:202:19 | Call | none | c3+? | -| escape.cpp:204:7:204:8 | VariableAddress[c4] | c4+0:0 | c4+0:0 | -| escape.cpp:206:14:206:15 | VariableAddress[c4] | c4+0:0 | c4+0:0 | -| escape.cpp:206:17:206:28 | Call | none | c4+? | +| escape.cpp:105:9:105:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:106:9:106:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:108:5:108:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:109:5:109:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:109:11:109:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:110:5:110:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:110:17:110:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:111:5:111:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:111:19:111:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:113:5:113:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:114:6:114:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:115:5:115:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:115:21:115:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:116:5:116:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:116:21:116:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:117:5:117:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:117:24:117:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:118:10:118:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:120:13:120:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:123:15:123:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:124:10:124:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:124:16:124:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:124:22:124:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:127:10:127:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:129:13:129:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | +| escape.cpp:132:9:132:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:133:5:133:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:134:11:134:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:135:5:135:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:136:7:136:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:137:5:137:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:137:17:137:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:138:5:138:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | +| escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:138:19:138:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:140:11:140:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:141:11:141:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:141:18:141:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:142:5:142:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:142:18:142:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | +| escape.cpp:143:11:143:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:143:20:143:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:7:144:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:22:144:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | +| escape.cpp:145:11:145:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:145:21:145:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:8:146:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:22:146:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | +| escape.cpp:148:13:148:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:11:150:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | +| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:151:5:151:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:152:11:152:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | +| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:152:19:152:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:154:9:154:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:155:10:155:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | +| escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:155:18:155:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:157:9:157:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:158:10:158:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | +| escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:158:17:158:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | +| escape.cpp:160:9:160:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:10:161:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | +| escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:19:161:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:163:9:163:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:164:11:164:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | +| escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:164:24:164:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:166:9:166:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:167:20:167:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:169:9:169:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:170:21:170:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:172:9:172:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:173:23:173:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:175:9:175:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:176:24:176:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:178:9:178:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:179:23:179:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:181:9:181:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:182:24:182:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:184:9:184:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:185:31:185:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:187:9:187:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:188:32:188:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | +| escape.cpp:190:9:190:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:191:30:191:42 | Call | none | passByPtr3+? | +| escape.cpp:191:45:191:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | +| escape.cpp:193:9:193:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:194:32:194:46 | Call | none | passByRef3+? | +| escape.cpp:194:48:194:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:196:9:196:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:197:9:197:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:198:10:198:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:199:18:199:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | +| escape.cpp:199:31:199:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:199:43:199:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:201:9:201:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:202:5:202:19 | Call | none | passByRef6+? | +| escape.cpp:202:21:202:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | +| escape.cpp:204:9:204:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+? | +| escape.cpp:205:21:205:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | +| escape.cpp:207:7:207:14 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | +| escape.cpp:209:5:209:12 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | +| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+? | +| escape.cpp:211:7:211:7 | VariableAddress[c] | c+0:0 | c+0:0 | +| escape.cpp:213:5:213:5 | VariableAddress[c] | c+0:0 | c+0:0 | +| escape.cpp:215:7:215:8 | VariableAddress[c2] | c2+0:0 | c2+0:0 | +| escape.cpp:217:15:217:16 | VariableAddress[c2] | c2+0:0 | c2+0:0 | +| escape.cpp:219:7:219:8 | VariableAddress[c3] | c3+0:0 | c3+0:0 | +| escape.cpp:221:5:221:6 | VariableAddress[c3] | c3+0:0 | c3+0:0 | +| escape.cpp:221:8:221:19 | Call | none | c3+? | +| escape.cpp:223:7:223:8 | VariableAddress[c4] | c4+0:0 | c4+0:0 | +| escape.cpp:225:14:225:15 | VariableAddress[c4] | c4+0:0 | c4+0:0 | +| escape.cpp:225:17:225:28 | Call | none | c4+? | +| escape.cpp:227:7:227:8 | VariableAddress[c5] | c5+0:0 | c5+0:0 | +| escape.cpp:229:5:229:6 | VariableAddress[c5] | c5+0:0 | c5+0:0 | +| escape.cpp:231:21:231:23 | VariableAddress[or1] | or1+0:0 | or1+0:0 | +| escape.cpp:232:5:232:7 | VariableAddress[or1] | or1+0:0 | or1+0:0 | +| escape.cpp:232:9:232:18 | Call | none | or1+? | +| escape.cpp:234:21:234:23 | VariableAddress[or2] | or2+0:0 | or2+0:0 | +| escape.cpp:235:14:235:16 | VariableAddress[or2] | or2+0:0 | or2+0:0 | +| escape.cpp:235:18:235:27 | Call | none | or2+? | +| escape.cpp:237:18:237:20 | VariableAddress[on1] | on1+0:0 | on1+0:0 | +| escape.cpp:238:5:238:7 | VariableAddress[on1] | on1+0:0 | on1+0:0 | +| escape.cpp:240:18:240:20 | VariableAddress[on2] | on2+0:0 | on2+0:0 | +| escape.cpp:241:14:241:16 | VariableAddress[on2] | on2+0:0 | on2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected index e69de29bb2d..df577707b57 100644 --- a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected @@ -0,0 +1,2 @@ +| escape.cpp:231:21:231:23 | or1 | +| escape.cpp:237:18:237:20 | on1 | From c70bd285de3b21102e507a97f4abbce2af743855 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 28 Jan 2019 15:05:04 -0800 Subject: [PATCH 05/17] C++: assume arguments to virtual functions escape --- .../ir/implementation/aliased_ssa/internal/AliasAnalysis.qll | 4 +++- .../implementation/unaliased_ssa/internal/AliasAnalysis.qll | 4 +++- cpp/ql/test/library-tests/ir/escape/escape.expected | 1 - cpp/ql/test/library-tests/ir/escape/ssa_escape.expected | 2 -- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 667b8225a61..fa29a8e4c9a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -152,7 +152,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // result does not itself escape. operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or - // The address is passed as an argument to a function from which it does not escape + // The operand is used in a function call from which the operand does not escape exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and @@ -163,6 +163,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { init.getEnclosingFunctionIR() = f and operand instanceof ThisArgumentOperand ) and + not exists(f.getFunction().getAnOverload()) and not resultEscapesNonReturn(init) and ( not resultReturned(init) @@ -195,6 +196,7 @@ predicate operandEscapesNonReturn(Operand operand) { init.getEnclosingFunctionIR() = f and operand instanceof ThisArgumentOperand ) and + not exists(f.getFunction().getAnOverload()) and not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 667b8225a61..fa29a8e4c9a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -152,7 +152,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // result does not itself escape. operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or - // The address is passed as an argument to a function from which it does not escape + // The operand is used in a function call from which the operand does not escape exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and f.getFunction() = ci.getStaticCallTarget() and @@ -163,6 +163,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { init.getEnclosingFunctionIR() = f and operand instanceof ThisArgumentOperand ) and + not exists(f.getFunction().getAnOverload()) and not resultEscapesNonReturn(init) and ( not resultReturned(init) @@ -195,6 +196,7 @@ predicate operandEscapesNonReturn(Operand operand) { init.getEnclosingFunctionIR() = f and operand instanceof ThisArgumentOperand ) and + not exists(f.getFunction().getAnOverload()) and not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or diff --git a/cpp/ql/test/library-tests/ir/escape/escape.expected b/cpp/ql/test/library-tests/ir/escape/escape.expected index 60c7a226e16..e69de29bb2d 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/escape.expected @@ -1 +0,0 @@ -| escape.cpp:237:18:237:20 | on1 | diff --git a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected index df577707b57..e69de29bb2d 100644 --- a/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected +++ b/cpp/ql/test/library-tests/ir/escape/ssa_escape.expected @@ -1,2 +0,0 @@ -| escape.cpp:231:21:231:23 | or1 | -| escape.cpp:237:18:237:20 | on1 | From 726f38c8021fe86f94ed39b247e95501486a5343 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 30 Jan 2019 15:52:58 -0800 Subject: [PATCH 06/17] C++: refactor alias analysis for performance --- .../aliased_ssa/internal/AliasAnalysis.qll | 50 ++++++++----------- .../unaliased_ssa/internal/AliasAnalysis.qll | 50 ++++++++----------- 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index fa29a8e4c9a..2acbe6c1947 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -155,15 +155,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // The operand is used in a function call from which the operand does not escape exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and - not exists(f.getFunction().getAnOverload()) and + isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and ( not resultReturned(init) @@ -186,17 +178,8 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, Instruction init | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and - not exists(f.getFunction().getAnOverload()) and + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or @@ -204,6 +187,7 @@ predicate operandEscapesNonReturn(Operand operand) { ) } + predicate operandReturned(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) @@ -217,16 +201,9 @@ predicate operandReturned(Operand operand) { resultReturned(ci) ) or - exists(CallInstruction ci, FunctionIR f, Instruction init | + exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and + isArgumentForParameter(ci, operand, init) and resultReturned(init) and resultReturned(ci) ) @@ -235,6 +212,21 @@ predicate operandReturned(Operand operand) { operand instanceof ReturnValueOperand } +predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { + exists(Function f | + ci = operand.getUseInstruction() and + f = ci.getStaticCallTarget() and + ( + init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunction() = f and + operand instanceof ThisArgumentOperand + ) and + not f.isVirtual() + ) +} + predicate resultReturned(Instruction instr) { operandReturned(instr.getAUse()) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index fa29a8e4c9a..2acbe6c1947 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -155,15 +155,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // The operand is used in a function call from which the operand does not escape exists(CallInstruction ci, FunctionIR f, Instruction init | ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and - not exists(f.getFunction().getAnOverload()) and + isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and ( not resultReturned(init) @@ -186,17 +178,8 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, Instruction init | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and - not exists(f.getFunction().getAnOverload()) and + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or @@ -204,6 +187,7 @@ predicate operandEscapesNonReturn(Operand operand) { ) } + predicate operandReturned(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) @@ -217,16 +201,9 @@ predicate operandReturned(Operand operand) { resultReturned(ci) ) or - exists(CallInstruction ci, FunctionIR f, Instruction init | + exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and + isArgumentForParameter(ci, operand, init) and resultReturned(init) and resultReturned(ci) ) @@ -235,6 +212,21 @@ predicate operandReturned(Operand operand) { operand instanceof ReturnValueOperand } +predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { + exists(Function f | + ci = operand.getUseInstruction() and + f = ci.getStaticCallTarget() and + ( + init.(InitializeParameterInstruction).getParameter() = f.getParameter(operand.(PositionalArgumentOperand).getIndex()) + or + init instanceof InitializeThisInstruction and + init.getEnclosingFunction() = f and + operand instanceof ThisArgumentOperand + ) and + not f.isVirtual() + ) +} + predicate resultReturned(Instruction instr) { operandReturned(instr.getAUse()) } From 6f76c133853d61a07fcc1ee82ca9bced7630d8e4 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 31 Jan 2019 13:32:24 -0800 Subject: [PATCH 07/17] C++: fix unused variable warning --- .../aliased_ssa/internal/AliasAnalysis.qll | 14 +++----------- .../unaliased_ssa/internal/AliasAnalysis.qll | 14 +++----------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 2acbe6c1947..f302c03ffcf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -153,7 +153,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, Instruction init | + exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and @@ -183,7 +183,7 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or - operand instanceof ReturnValueOperand + operand.getUseInstruction() instanceof ReturnValueInstruction ) } @@ -193,14 +193,6 @@ predicate operandReturned(Operand operand) { operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - resultReturned(ipi) and - resultReturned(ci) - ) - or exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and @@ -209,7 +201,7 @@ predicate operandReturned(Operand operand) { ) or // The address is returned - operand instanceof ReturnValueOperand + operand.getUseInstruction() instanceof ReturnValueInstruction } predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 2acbe6c1947..f302c03ffcf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -153,7 +153,7 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) or // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, FunctionIR f, Instruction init | + exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and not resultEscapesNonReturn(init) and @@ -183,7 +183,7 @@ predicate operandEscapesNonReturn(Operand operand) { not resultEscapesNonReturn(init) and not resultEscapesNonReturn(ci) ) or - operand instanceof ReturnValueOperand + operand.getUseInstruction() instanceof ReturnValueInstruction ) } @@ -193,14 +193,6 @@ predicate operandReturned(Operand operand) { operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned - exists(CallInstruction ci, FunctionIR f, InitializeParameterInstruction ipi | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ipi.getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) and - resultReturned(ipi) and - resultReturned(ci) - ) - or exists(CallInstruction ci, Instruction init | ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and @@ -209,7 +201,7 @@ predicate operandReturned(Operand operand) { ) or // The address is returned - operand instanceof ReturnValueOperand + operand.getUseInstruction() instanceof ReturnValueInstruction } predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { From 09321ee0625ea4bc332d8a9dc6f63b9914daca39 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 1 Mar 2019 10:07:55 -0800 Subject: [PATCH 08/17] C++: refactor escape analysis for performance --- .../aliased_ssa/internal/AliasAnalysis.qll | 113 +++++++++--------- .../unaliased_ssa/internal/AliasAnalysis.qll | 113 +++++++++--------- 2 files changed, 118 insertions(+), 108 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index f302c03ffcf..d779fe5c814 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -3,6 +3,8 @@ import cpp private import InputIR private import semmle.code.cpp.ir.internal.IntegerConstant as Ints +private import semmle.code.cpp.models.interfaces.Alias + private class IntValue = Ints::IntValue; /** @@ -60,8 +62,18 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { // Converting an address to a `bool` does not escape the address. instr.(ConvertInstruction).getResultType() instanceof BoolType ) - ) + ) or + // Some standard function arguments never escape + isNeverEscapesArgument(operand) } + +predicate operandEscapesDomain(Operand operand) { + not operandIsConsumedWithoutEscaping(operand) and + not operandIsPropagated(operand, _) and + not isArgumentForParameter(_, operand, _) and + not isOnlyEscapesViaReturnArgument(operand) +} + /** * If the result of instruction `instr` is an integer constant, returns the * value of that constant. Otherwise, returns unknown. @@ -133,58 +145,32 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // offset of the field. bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or // A copy propagates the source value. - operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 - ) - ) -} - -/** - * Holds if any address held in operand number `tag` of instruction `instr` - * escapes outside the domain of the analysis. - */ - predicate operandEscapes(Operand operand) { - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(operand) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) - or - // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and - isArgumentForParameter(ci, operand, init) and - not resultEscapesNonReturn(init) and - ( - not resultReturned(init) - or - not resultEscapes(operand.getUseInstruction()) - ) + operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 or + // Some functions are known to propagate an argument + isAlwaysReturnedArgument(operand) and bitOffset = 0 ) ) } predicate operandEscapesNonReturn(Operand operand) { - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(operand) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(operand, _) and - not resultEscapesNonReturn(operand.getUseInstruction()) - or - // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, Instruction init | - isArgumentForParameter(ci, operand, init) and - not resultEscapesNonReturn(init) and - not resultEscapesNonReturn(ci) - ) or - operand.getUseInstruction() instanceof ReturnValueInstruction + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, Instruction init | + ci = operand.getUseInstruction() and + isArgumentForParameter(ci, operand, init) and + ( + resultReturned(init) and + resultEscapesNonReturn(ci) + or + resultEscapesNonReturn(init) + ) ) + or + isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction()) + or + operandEscapesDomain(operand) } @@ -202,6 +188,8 @@ predicate operandReturned(Operand operand) { or // The address is returned operand.getUseInstruction() instanceof ReturnValueInstruction + or + isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) } predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { @@ -215,7 +203,29 @@ predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instructio init.getEnclosingFunction() = f and operand instanceof ThisArgumentOperand ) and - not f.isVirtual() + not f.isVirtual() and + not f instanceof AliasFunction + ) +} + +predicate isAlwaysReturnedArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex()) + ) +} + +predicate isOnlyEscapesViaReturnArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex()) + ) +} + +predicate isNeverEscapesArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex()) ) } @@ -227,12 +237,7 @@ predicate resultReturned(Instruction instr) { * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. */ -predicate resultEscapes(Instruction instr) { - // The result escapes if it has at least one use that escapes. - operandEscapes(instr.getAUse()) -} - - predicate resultEscapesNonReturn(Instruction instr) { +predicate resultEscapesNonReturn(Instruction instr) { // The result escapes if it has at least one use that escapes. operandEscapesNonReturn(instr.getAUse()) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index f302c03ffcf..d779fe5c814 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -3,6 +3,8 @@ import cpp private import InputIR private import semmle.code.cpp.ir.internal.IntegerConstant as Ints +private import semmle.code.cpp.models.interfaces.Alias + private class IntValue = Ints::IntValue; /** @@ -60,8 +62,18 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { // Converting an address to a `bool` does not escape the address. instr.(ConvertInstruction).getResultType() instanceof BoolType ) - ) + ) or + // Some standard function arguments never escape + isNeverEscapesArgument(operand) } + +predicate operandEscapesDomain(Operand operand) { + not operandIsConsumedWithoutEscaping(operand) and + not operandIsPropagated(operand, _) and + not isArgumentForParameter(_, operand, _) and + not isOnlyEscapesViaReturnArgument(operand) +} + /** * If the result of instruction `instr` is an integer constant, returns the * value of that constant. Otherwise, returns unknown. @@ -133,58 +145,32 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { // offset of the field. bitOffset = getFieldBitOffset(instr.(FieldAddressInstruction).getField()) or // A copy propagates the source value. - operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 - ) - ) -} - -/** - * Holds if any address held in operand number `tag` of instruction `instr` - * escapes outside the domain of the analysis. - */ - predicate operandEscapes(Operand operand) { - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(operand) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(operand, _) and not resultEscapes(operand.getUseInstruction()) - or - // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and - isArgumentForParameter(ci, operand, init) and - not resultEscapesNonReturn(init) and - ( - not resultReturned(init) - or - not resultEscapes(operand.getUseInstruction()) - ) + operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0 or + // Some functions are known to propagate an argument + isAlwaysReturnedArgument(operand) and bitOffset = 0 ) ) } predicate operandEscapesNonReturn(Operand operand) { - // Conservatively assume that the address escapes unless one of the following - // holds: - not ( - // The operand is used in a way that does not escape the instruction - operandIsConsumedWithoutEscaping(operand) or - // The address is propagated to the result of the instruction, but that - // result does not itself escape. - operandIsPropagated(operand, _) and - not resultEscapesNonReturn(operand.getUseInstruction()) - or - // The operand is used in a function call from which the operand does not escape - exists(CallInstruction ci, Instruction init | - isArgumentForParameter(ci, operand, init) and - not resultEscapesNonReturn(init) and - not resultEscapesNonReturn(ci) - ) or - operand.getUseInstruction() instanceof ReturnValueInstruction + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, Instruction init | + ci = operand.getUseInstruction() and + isArgumentForParameter(ci, operand, init) and + ( + resultReturned(init) and + resultEscapesNonReturn(ci) + or + resultEscapesNonReturn(init) + ) ) + or + isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction()) + or + operandEscapesDomain(operand) } @@ -202,6 +188,8 @@ predicate operandReturned(Operand operand) { or // The address is returned operand.getUseInstruction() instanceof ReturnValueInstruction + or + isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) } predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { @@ -215,7 +203,29 @@ predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instructio init.getEnclosingFunction() = f and operand instanceof ThisArgumentOperand ) and - not f.isVirtual() + not f.isVirtual() and + not f instanceof AliasFunction + ) +} + +predicate isAlwaysReturnedArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex()) + ) +} + +predicate isOnlyEscapesViaReturnArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex()) + ) +} + +predicate isNeverEscapesArgument(Operand operand) { + exists(AliasFunction f | + f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and + f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex()) ) } @@ -227,12 +237,7 @@ predicate resultReturned(Instruction instr) { * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. */ -predicate resultEscapes(Instruction instr) { - // The result escapes if it has at least one use that escapes. - operandEscapes(instr.getAUse()) -} - - predicate resultEscapesNonReturn(Instruction instr) { +predicate resultEscapesNonReturn(Instruction instr) { // The result escapes if it has at least one use that escapes. operandEscapesNonReturn(instr.getAUse()) } From a72cd23d1d34d4056921dccba4906b4211cd9a97 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 1 Mar 2019 12:21:55 -0800 Subject: [PATCH 09/17] C++: fix escape test failures --- .../aliased_ssa/internal/AliasAnalysis.qll | 3 ++- .../unaliased_ssa/internal/AliasAnalysis.qll | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index d779fe5c814..b733bc9a48b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -71,7 +71,8 @@ predicate operandEscapesDomain(Operand operand) { not operandIsConsumedWithoutEscaping(operand) and not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and - not isOnlyEscapesViaReturnArgument(operand) + not isOnlyEscapesViaReturnArgument(operand) and + not operand.getUseInstruction() instanceof ReturnValueInstruction } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index d779fe5c814..9621b0b9ab8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -71,7 +71,8 @@ predicate operandEscapesDomain(Operand operand) { not operandIsConsumedWithoutEscaping(operand) and not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and - not isOnlyEscapesViaReturnArgument(operand) + not isOnlyEscapesViaReturnArgument(operand) and + not operand.getUseInstruction() instanceof ReturnValueInstruction } /** @@ -208,21 +209,21 @@ predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instructio ) } -predicate isAlwaysReturnedArgument(Operand operand) { +private predicate isAlwaysReturnedArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex()) ) } -predicate isOnlyEscapesViaReturnArgument(Operand operand) { +private predicate isOnlyEscapesViaReturnArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex()) ) } -predicate isNeverEscapesArgument(Operand operand) { +private predicate isNeverEscapesArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex()) From 794a8954cda05a47396be656e0224571b5817c82 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sat, 2 Mar 2019 12:07:04 +0100 Subject: [PATCH 10/17] C++: Simplify automaticVariableAddressEscapes The `automaticVariableAddressEscapes` predicate got join-ordered badly in its `unaliased_ssa` version. These are the tuple counts on Wireshark, where one pipeline step is seen to have 716 million tuples: ``` [2019-03-02 11:29:41] (42s) Starting to evaluate predicate AliasAnalysis::automaticVariableAddressEscapes#2#f [2019-03-02 11:30:06] (67s) Tuple counts: 353419 ~0% {1} r1 = JOIN project#Instruction::VariableAddressInstruction#class#2#ff WITH AliasAnalysis::resultEscapesNonReturn#2#f ON project#Instruction::VariableAddressInstruction#class#2#ff.<0>=AliasAnalysis::resultEscapesNonReturn#2#f.<0> OUTPUT FIELDS {AliasAnalysis::resultEscapesNonReturn#2#f.<0>} 353419 ~0% {2} r2 = JOIN r1 WITH IRConstruction::Cached::getInstructionEnclosingFunctionIR#ff@staged_ext ON r1.<0>=IRConstruction::Cached::getInstructionEnclosingFunctionIR#ff@staged_ext.<0> OUTPUT FIELDS {IRConstruction::Cached::getInstructionEnclosingFunctionIR#ff@staged_ext.<1>,r1.<0>} 353419 ~0% {2} r3 = JOIN r2 WITH FunctionIR::FunctionIR::getFunction_dispred#3#ff ON r2.<0>=FunctionIR::FunctionIR::getFunction_dispred#3#ff.<0> OUTPUT FIELDS {FunctionIR::FunctionIR::getFunction_dispred#3#ff.<1>,r2.<1>} 716040298 ~0% {2} r4 = JOIN r3 WITH IRVariable::IRVariable#class#3#ff_10#join_rhs ON r3.<0>=IRVariable::IRVariable#class#3#ff_10#join_rhs.<0> OUTPUT FIELDS {IRVariable::IRVariable#class#3#ff_10#join_rhs.<1>,r3.<1>} 4480139 ~0% {2} r5 = JOIN r4 WITH IRVariable::IRAutomaticVariable#class#3#ff ON r4.<0>=IRVariable::IRAutomaticVariable#class#3#ff.<0> OUTPUT FIELDS {r4.<1>,r4.<0>} 66760 ~91% {1} r6 = JOIN r5 WITH Instruction::VariableInstruction::getVariable_dispred#2#ff ON r5.<0>=Instruction::VariableInstruction::getVariable_dispred#2#ff.<0> AND r5.<1>=Instruction::VariableInstruction::getVariable_dispred#2#ff.<1> OUTPUT FIELDS {r5.<1>} return r6 [2019-03-02 11:30:06] (67s) >>> Relation AliasAnalysis::automaticVariableAddressEscapes#2#f: 35531 rows using 0 MB ``` The predicate contained a cyclic join, which is always hard to optimize. I couldn't see a reason to join the `FunctionIR`, so I removed that part. The predicate is now fast, and there are no changes in the tests. --- .../aliased_ssa/internal/AliasAnalysis.qll | 14 +++++--------- .../unaliased_ssa/internal/AliasAnalysis.qll | 14 +++++--------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b733bc9a48b..c7410e21038 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -248,15 +248,11 @@ predicate resultEscapesNonReturn(Instruction instr) { * domain of the analysis. */ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { - exists(FunctionIR funcIR | - funcIR = var.getEnclosingFunctionIR() and - // The variable's address escapes if the result of any - // VariableAddressInstruction that computes the variable's address escapes. - exists(VariableAddressInstruction instr | - instr.getEnclosingFunctionIR() = funcIR and - instr.getVariable() = var and - resultEscapesNonReturn(instr) - ) + // The variable's address escapes if the result of any + // VariableAddressInstruction that computes the variable's address escapes. + exists(VariableAddressInstruction instr | + instr.getVariable() = var and + resultEscapesNonReturn(instr) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 9621b0b9ab8..13fa28ea9ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -248,15 +248,11 @@ predicate resultEscapesNonReturn(Instruction instr) { * domain of the analysis. */ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) { - exists(FunctionIR funcIR | - funcIR = var.getEnclosingFunctionIR() and - // The variable's address escapes if the result of any - // VariableAddressInstruction that computes the variable's address escapes. - exists(VariableAddressInstruction instr | - instr.getEnclosingFunctionIR() = funcIR and - instr.getVariable() = var and - resultEscapesNonReturn(instr) - ) + // The variable's address escapes if the result of any + // VariableAddressInstruction that computes the variable's address escapes. + exists(VariableAddressInstruction instr | + instr.getVariable() = var and + resultEscapesNonReturn(instr) ) } From 878502f82eb6dc9545d3b0930601e055730c0e61 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 4 Mar 2019 16:47:02 -0800 Subject: [PATCH 11/17] C++: remove duplicate logic --- .../aliased_ssa/internal/AliasAnalysis.qll | 37 +++++++------------ .../unaliased_ssa/internal/AliasAnalysis.qll | 31 +++++----------- 2 files changed, 23 insertions(+), 45 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index c7410e21038..969cf1b4699 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -48,7 +48,7 @@ private IntValue getFieldBitOffset(Field field) { * not result in any address held in that operand from escaping beyond the * instruction. */ -predicate operandIsConsumedWithoutEscaping(Operand operand) { +private predicate operandIsConsumedWithoutEscaping(Operand operand) { // The source/destination address of a Load/Store does not escape (but the // loaded/stored value could). operand instanceof AddressOperand or @@ -67,7 +67,7 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { isNeverEscapesArgument(operand) } -predicate operandEscapesDomain(Operand operand) { +private predicate operandEscapesDomain(Operand operand) { not operandIsConsumedWithoutEscaping(operand) and not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and @@ -110,7 +110,7 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { * `bitOffset`. If the address is propagated, but the offset is not known to be * a constant, then `bitOffset` is unknown. */ -predicate operandIsPropagated(Operand operand, IntValue bitOffset) { +private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { exists(Instruction instr | instr = operand.getUseInstruction() and ( @@ -153,13 +153,12 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { ) } -predicate operandEscapesNonReturn(Operand operand) { +private predicate operandEscapesNonReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and ( resultReturned(init) and @@ -174,14 +173,12 @@ predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } - -predicate operandReturned(Operand operand) { +private predicate operandReturned(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and resultReturned(init) and resultReturned(ci) @@ -193,7 +190,7 @@ predicate operandReturned(Operand operand) { isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) } -predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { +private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { exists(Function f | ci = operand.getUseInstruction() and f = ci.getStaticCallTarget() and @@ -209,28 +206,28 @@ predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instructio ) } -predicate isAlwaysReturnedArgument(Operand operand) { +private predicate isAlwaysReturnedArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterIsAlwaysReturned(operand.(PositionalArgumentOperand).getIndex()) ) } -predicate isOnlyEscapesViaReturnArgument(Operand operand) { +private predicate isOnlyEscapesViaReturnArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterEscapesOnlyViaReturn(operand.(PositionalArgumentOperand).getIndex()) ) } -predicate isNeverEscapesArgument(Operand operand) { +private predicate isNeverEscapesArgument(Operand operand) { exists(AliasFunction f | f = operand.getUseInstruction().(CallInstruction).getStaticCallTarget() and f.parameterNeverEscapes(operand.(PositionalArgumentOperand).getIndex()) ) } -predicate resultReturned(Instruction instr) { +private predicate resultReturned(Instruction instr) { operandReturned(instr.getAUse()) } @@ -238,7 +235,7 @@ predicate resultReturned(Instruction instr) { * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. */ -predicate resultEscapesNonReturn(Instruction instr) { +private predicate resultEscapesNonReturn(Instruction instr) { // The result escapes if it has at least one use that escapes. operandEscapesNonReturn(instr.getAUse()) } @@ -285,16 +282,8 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) ( operandIsPropagated(operand, propagatedBitOffset) or - exists(CallInstruction ci, FunctionIR f, Instruction init | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and resultReturned(init) and propagatedBitOffset = Ints::unknown() ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 13fa28ea9ac..969cf1b4699 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -48,7 +48,7 @@ private IntValue getFieldBitOffset(Field field) { * not result in any address held in that operand from escaping beyond the * instruction. */ -predicate operandIsConsumedWithoutEscaping(Operand operand) { +private predicate operandIsConsumedWithoutEscaping(Operand operand) { // The source/destination address of a Load/Store does not escape (but the // loaded/stored value could). operand instanceof AddressOperand or @@ -67,7 +67,7 @@ predicate operandIsConsumedWithoutEscaping(Operand operand) { isNeverEscapesArgument(operand) } -predicate operandEscapesDomain(Operand operand) { +private predicate operandEscapesDomain(Operand operand) { not operandIsConsumedWithoutEscaping(operand) and not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and @@ -110,7 +110,7 @@ IntValue getPointerBitOffset(PointerOffsetInstruction instr) { * `bitOffset`. If the address is propagated, but the offset is not known to be * a constant, then `bitOffset` is unknown. */ -predicate operandIsPropagated(Operand operand, IntValue bitOffset) { +private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { exists(Instruction instr | instr = operand.getUseInstruction() and ( @@ -153,13 +153,12 @@ predicate operandIsPropagated(Operand operand, IntValue bitOffset) { ) } -predicate operandEscapesNonReturn(Operand operand) { +private predicate operandEscapesNonReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultEscapesNonReturn(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and ( resultReturned(init) and @@ -174,14 +173,12 @@ predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } - -predicate operandReturned(Operand operand) { +private predicate operandReturned(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init | - ci = operand.getUseInstruction() and isArgumentForParameter(ci, operand, init) and resultReturned(init) and resultReturned(ci) @@ -193,7 +190,7 @@ predicate operandReturned(Operand operand) { isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) } -predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { +private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { exists(Function f | ci = operand.getUseInstruction() and f = ci.getStaticCallTarget() and @@ -230,7 +227,7 @@ private predicate isNeverEscapesArgument(Operand operand) { ) } -predicate resultReturned(Instruction instr) { +private predicate resultReturned(Instruction instr) { operandReturned(instr.getAUse()) } @@ -238,7 +235,7 @@ predicate resultReturned(Instruction instr) { * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. */ -predicate resultEscapesNonReturn(Instruction instr) { +private predicate resultEscapesNonReturn(Instruction instr) { // The result escapes if it has at least one use that escapes. operandEscapesNonReturn(instr.getAUse()) } @@ -285,16 +282,8 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) ( operandIsPropagated(operand, propagatedBitOffset) or - exists(CallInstruction ci, FunctionIR f, Instruction init | - ci = operand.getUseInstruction() and - f.getFunction() = ci.getStaticCallTarget() and - ( - init.(InitializeParameterInstruction).getParameter() = f.getFunction().getParameter(operand.(PositionalArgumentOperand).getIndex()) - or - init instanceof InitializeThisInstruction and - init.getEnclosingFunctionIR() = f and - operand instanceof ThisArgumentOperand - ) and + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and resultReturned(init) and propagatedBitOffset = Ints::unknown() ) From 97c11a5222062c51f30894fe1e8a597e45b39769 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 4 Mar 2019 17:14:13 -0800 Subject: [PATCH 12/17] C++: points-to for argument-returning calls --- .../aliased_ssa/internal/AliasAnalysis.qll | 31 ++++++++++++------- .../unaliased_ssa/internal/AliasAnalysis.qll | 31 ++++++++++++------- .../ir/escape/points_to.expected | 16 +++++----- 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 969cf1b4699..43d9551287b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -161,7 +161,7 @@ private predicate operandEscapesNonReturn(Operand operand) { exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and ( - resultReturned(init) and + resultReturned(init, _) and resultEscapesNonReturn(ci) or resultEscapesNonReturn(init) @@ -173,21 +173,29 @@ private predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } -private predicate operandReturned(Operand operand) { +private predicate operandReturned(Operand operand, IntValue bitOffset) { // The address is propagated to the result of the instruction, and that result itself is returned - operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) + exists(IntValue bitOffset1, IntValue bitOffset2 | + operandIsPropagated(operand, bitOffset1) and + resultReturned(operand.getUseInstruction(), bitOffset2) and + bitOffset = bitOffset1 + bitOffset2 + ) or // The operand is used in a function call which returns it, and the return value is then returned - exists(CallInstruction ci, Instruction init | + exists(CallInstruction ci, Instruction init, IntValue bitOffset1, IntValue bitOffset2 | isArgumentForParameter(ci, operand, init) and - resultReturned(init) and - resultReturned(ci) + resultReturned(init, bitOffset1) and + resultReturned(ci, bitOffset2) and + bitOffset = bitOffset1 + bitOffset2 + ) or // The address is returned - operand.getUseInstruction() instanceof ReturnValueInstruction + operand.getUseInstruction() instanceof ReturnValueInstruction and + bitOffset = 0 or - isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) + isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction(), _) and + bitOffset = Ints::unknown() } private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { @@ -227,8 +235,8 @@ private predicate isNeverEscapesArgument(Operand operand) { ) } -private predicate resultReturned(Instruction instr) { - operandReturned(instr.getAUse()) +private predicate resultReturned(Instruction instr, IntValue bitOffset) { + operandReturned(instr.getAUse(), bitOffset) } /** @@ -284,8 +292,7 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) or exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and - resultReturned(init) and - propagatedBitOffset = Ints::unknown() + resultReturned(init, propagatedBitOffset) ) ) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 969cf1b4699..43d9551287b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -161,7 +161,7 @@ private predicate operandEscapesNonReturn(Operand operand) { exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and ( - resultReturned(init) and + resultReturned(init, _) and resultEscapesNonReturn(ci) or resultEscapesNonReturn(init) @@ -173,21 +173,29 @@ private predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } -private predicate operandReturned(Operand operand) { +private predicate operandReturned(Operand operand, IntValue bitOffset) { // The address is propagated to the result of the instruction, and that result itself is returned - operandIsPropagated(operand, _) and resultReturned(operand.getUseInstruction()) + exists(IntValue bitOffset1, IntValue bitOffset2 | + operandIsPropagated(operand, bitOffset1) and + resultReturned(operand.getUseInstruction(), bitOffset2) and + bitOffset = bitOffset1 + bitOffset2 + ) or // The operand is used in a function call which returns it, and the return value is then returned - exists(CallInstruction ci, Instruction init | + exists(CallInstruction ci, Instruction init, IntValue bitOffset1, IntValue bitOffset2 | isArgumentForParameter(ci, operand, init) and - resultReturned(init) and - resultReturned(ci) + resultReturned(init, bitOffset1) and + resultReturned(ci, bitOffset2) and + bitOffset = bitOffset1 + bitOffset2 + ) or // The address is returned - operand.getUseInstruction() instanceof ReturnValueInstruction + operand.getUseInstruction() instanceof ReturnValueInstruction and + bitOffset = 0 or - isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction()) + isOnlyEscapesViaReturnArgument(operand) and resultReturned(operand.getUseInstruction(), _) and + bitOffset = Ints::unknown() } private predicate isArgumentForParameter(CallInstruction ci, Operand operand, Instruction init) { @@ -227,8 +235,8 @@ private predicate isNeverEscapesArgument(Operand operand) { ) } -private predicate resultReturned(Instruction instr) { - operandReturned(instr.getAUse()) +private predicate resultReturned(Instruction instr, IntValue bitOffset) { + operandReturned(instr.getAUse(), bitOffset) } /** @@ -284,8 +292,7 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) or exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and - resultReturned(init) and - propagatedBitOffset = Ints::unknown() + resultReturned(init, propagatedBitOffset) ) ) and bitOffset = Ints::add(originalBitOffset, propagatedBitOffset) diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index 9ff401bc4e0..b8f412c242d 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -140,10 +140,10 @@ | escape.cpp:187:9:187:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | | escape.cpp:188:32:188:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | | escape.cpp:190:9:190:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:191:30:191:42 | Call | none | passByPtr3+? | +| escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 | | escape.cpp:191:45:191:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | | escape.cpp:193:9:193:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:194:32:194:46 | Call | none | passByRef3+? | +| escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | | escape.cpp:194:48:194:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | | escape.cpp:196:9:196:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | | escape.cpp:197:9:197:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | @@ -152,32 +152,30 @@ | escape.cpp:199:31:199:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | | escape.cpp:199:43:199:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | | escape.cpp:201:9:201:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:202:5:202:19 | Call | none | passByRef6+? | +| escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | | escape.cpp:202:21:202:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:204:9:204:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | -| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+? | +| escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 | | escape.cpp:205:21:205:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | | escape.cpp:207:7:207:14 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | | escape.cpp:209:5:209:12 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | -| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+? | +| escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 | | escape.cpp:211:7:211:7 | VariableAddress[c] | c+0:0 | c+0:0 | | escape.cpp:213:5:213:5 | VariableAddress[c] | c+0:0 | c+0:0 | | escape.cpp:215:7:215:8 | VariableAddress[c2] | c2+0:0 | c2+0:0 | | escape.cpp:217:15:217:16 | VariableAddress[c2] | c2+0:0 | c2+0:0 | | escape.cpp:219:7:219:8 | VariableAddress[c3] | c3+0:0 | c3+0:0 | | escape.cpp:221:5:221:6 | VariableAddress[c3] | c3+0:0 | c3+0:0 | -| escape.cpp:221:8:221:19 | Call | none | c3+? | +| escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:223:7:223:8 | VariableAddress[c4] | c4+0:0 | c4+0:0 | | escape.cpp:225:14:225:15 | VariableAddress[c4] | c4+0:0 | c4+0:0 | -| escape.cpp:225:17:225:28 | Call | none | c4+? | +| escape.cpp:225:17:225:28 | Call | none | c4+0:0 | | escape.cpp:227:7:227:8 | VariableAddress[c5] | c5+0:0 | c5+0:0 | | escape.cpp:229:5:229:6 | VariableAddress[c5] | c5+0:0 | c5+0:0 | | escape.cpp:231:21:231:23 | VariableAddress[or1] | or1+0:0 | or1+0:0 | | escape.cpp:232:5:232:7 | VariableAddress[or1] | or1+0:0 | or1+0:0 | -| escape.cpp:232:9:232:18 | Call | none | or1+? | | escape.cpp:234:21:234:23 | VariableAddress[or2] | or2+0:0 | or2+0:0 | | escape.cpp:235:14:235:16 | VariableAddress[or2] | or2+0:0 | or2+0:0 | -| escape.cpp:235:18:235:27 | Call | none | or2+? | | escape.cpp:237:18:237:20 | VariableAddress[on1] | on1+0:0 | on1+0:0 | | escape.cpp:238:5:238:7 | VariableAddress[on1] | on1+0:0 | on1+0:0 | | escape.cpp:240:18:240:20 | VariableAddress[on2] | on2+0:0 | on2+0:0 | From 7e30ce0c09434cabd664dfc99c26e3b60ace4473 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 5 Mar 2019 10:54:26 -0800 Subject: [PATCH 13/17] C++: add phi node support to escape analysis --- .../aliased_ssa/internal/AliasAnalysis.qll | 34 +++++++++++++++++-- .../unaliased_ssa/internal/AliasAnalysis.qll | 34 +++++++++++++++++-- .../test/library-tests/ir/escape/escape.cpp | 16 +++++++-- .../ir/escape/points_to.expected | 20 ++++++++--- .../test/library-tests/ir/escape/points_to.ql | 3 +- 5 files changed, 94 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index 43d9551287b..db7fe197f87 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -72,7 +72,8 @@ private predicate operandEscapesDomain(Operand operand) { not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and - not operand.getUseInstruction() instanceof ReturnValueInstruction + not operand.getUseInstruction() instanceof ReturnValueInstruction and + not operand instanceof PhiOperand } /** @@ -161,7 +162,7 @@ private predicate operandEscapesNonReturn(Operand operand) { exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and ( - resultReturned(init, _) and + resultMayReachReturn(init) and resultEscapesNonReturn(ci) or resultEscapesNonReturn(init) @@ -170,9 +171,34 @@ private predicate operandEscapesNonReturn(Operand operand) { or isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction()) or + operand instanceof PhiOperand and + resultEscapesNonReturn(operand.getUseInstruction()) + or operandEscapesDomain(operand) } + +private predicate operandMayReachReturn(Operand operand) { + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and + resultMayReachReturn(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and + resultMayReachReturn(init) and + resultMayReachReturn(ci) + ) + or + // The address is returned + operand.getUseInstruction() instanceof ReturnValueInstruction + or + isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction()) + or + operand instanceof PhiOperand and + resultMayReachReturn(operand.getUseInstruction()) +} + private predicate operandReturned(Operand operand, IntValue bitOffset) { // The address is propagated to the result of the instruction, and that result itself is returned exists(IntValue bitOffset1, IntValue bitOffset2 | @@ -239,6 +265,10 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) { operandReturned(instr.getAUse(), bitOffset) } +private predicate resultMayReachReturn(Instruction instr) { + operandMayReachReturn(instr.getAUse()) +} + /** * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 43d9551287b..db7fe197f87 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -72,7 +72,8 @@ private predicate operandEscapesDomain(Operand operand) { not operandIsPropagated(operand, _) and not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and - not operand.getUseInstruction() instanceof ReturnValueInstruction + not operand.getUseInstruction() instanceof ReturnValueInstruction and + not operand instanceof PhiOperand } /** @@ -161,7 +162,7 @@ private predicate operandEscapesNonReturn(Operand operand) { exists(CallInstruction ci, Instruction init | isArgumentForParameter(ci, operand, init) and ( - resultReturned(init, _) and + resultMayReachReturn(init) and resultEscapesNonReturn(ci) or resultEscapesNonReturn(init) @@ -170,9 +171,34 @@ private predicate operandEscapesNonReturn(Operand operand) { or isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUseInstruction()) or + operand instanceof PhiOperand and + resultEscapesNonReturn(operand.getUseInstruction()) + or operandEscapesDomain(operand) } + +private predicate operandMayReachReturn(Operand operand) { + // The address is propagated to the result of the instruction, and that result itself is returned + operandIsPropagated(operand, _) and + resultMayReachReturn(operand.getUseInstruction()) + or + // The operand is used in a function call which returns it, and the return value is then returned + exists(CallInstruction ci, Instruction init | + isArgumentForParameter(ci, operand, init) and + resultMayReachReturn(init) and + resultMayReachReturn(ci) + ) + or + // The address is returned + operand.getUseInstruction() instanceof ReturnValueInstruction + or + isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUseInstruction()) + or + operand instanceof PhiOperand and + resultMayReachReturn(operand.getUseInstruction()) +} + private predicate operandReturned(Operand operand, IntValue bitOffset) { // The address is propagated to the result of the instruction, and that result itself is returned exists(IntValue bitOffset1, IntValue bitOffset2 | @@ -239,6 +265,10 @@ private predicate resultReturned(Instruction instr, IntValue bitOffset) { operandReturned(instr.getAUse(), bitOffset) } +private predicate resultMayReachReturn(Instruction instr) { + operandMayReachReturn(instr.getAUse()) +} + /** * Holds if any address held in the result of instruction `instr` escapes * outside the domain of the analysis. diff --git a/cpp/ql/test/library-tests/ir/escape/escape.cpp b/cpp/ql/test/library-tests/ir/escape/escape.cpp index 96931aeea2d..d1f7641e3b8 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.cpp +++ b/cpp/ql/test/library-tests/ir/escape/escape.cpp @@ -193,10 +193,10 @@ void Escape() int passByRef3; CallByReferenceParamEscape(ReturnReference(passByRef3)); - int passByPtr4; - int passByPtr5; + int no_ssa_passByPtr4; + int no_ssa_passByPtr5; bool no_b2 = false; - MaybeReturn(&passByPtr4, &passByPtr5, no_b2); + MaybeReturn(&no_ssa_passByPtr4, &no_ssa_passByPtr5, no_b2); int passByRef6; EscapeAndReturn(passByRef6); @@ -239,5 +239,15 @@ void Escape() OverrideNone on2; CEscapes(on2.Overridden()); + + int condEscape1, condEscape2; + + int *no_condTemp; + if(GetPointer()) { + no_condTemp = &condEscape1; + } else { + no_condTemp = &condEscape2; + } + CallByPointer(no_condTemp); } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index b8f412c242d..7d5ad820ad3 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -145,12 +145,12 @@ | escape.cpp:193:9:193:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | | escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | | escape.cpp:194:48:194:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:196:9:196:18 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:197:9:197:18 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | +| escape.cpp:196:9:196:25 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | +| escape.cpp:197:9:197:25 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | | escape.cpp:198:10:198:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:199:18:199:27 | VariableAddress[passByPtr4] | passByPtr4+0:0 | passByPtr4+0:0 | -| escape.cpp:199:31:199:40 | VariableAddress[passByPtr5] | passByPtr5+0:0 | passByPtr5+0:0 | -| escape.cpp:199:43:199:47 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | +| escape.cpp:199:18:199:34 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | +| escape.cpp:199:38:199:54 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | +| escape.cpp:199:57:199:61 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | | escape.cpp:201:9:201:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | | escape.cpp:202:21:202:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | @@ -180,3 +180,13 @@ | escape.cpp:238:5:238:7 | VariableAddress[on1] | on1+0:0 | on1+0:0 | | escape.cpp:240:18:240:20 | VariableAddress[on2] | on2+0:0 | on2+0:0 | | escape.cpp:241:14:241:16 | VariableAddress[on2] | on2+0:0 | on2+0:0 | +| escape.cpp:243:9:243:19 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:243:22:243:32 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:245:10:245:20 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | +| escape.cpp:247:2:247:12 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | +| escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:247:17:247:27 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:249:9:249:19 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | +| escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:249:24:249:34 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:251:19:251:29 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.ql b/cpp/ql/test/library-tests/ir/escape/points_to.ql index 19d767ce58f..1c89c48ee4e 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.ql +++ b/cpp/ql/test/library-tests/ir/escape/points_to.ql @@ -29,5 +29,6 @@ where not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and unPointsTo = "none" ) - ) + ) and + rawPointsTo != unPointsTo select rawInstr.getLocation().toString(), rawInstr.getOperationString(), rawPointsTo, unPointsTo From 17ad124c9ed282e8cd35ae9beebae06da6f7a80d Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 5 Mar 2019 11:06:22 -0800 Subject: [PATCH 14/17] C++: remove VariableAddress from points_to test --- .../ir/escape/points_to.expected | 145 ------------------ .../test/library-tests/ir/escape/points_to.ql | 4 +- 2 files changed, 2 insertions(+), 147 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index 7d5ad820ad3..f40460f4d91 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,192 +1,47 @@ -| escape.cpp:6:27:6:30 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:7:11:7:14 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:10:29:10:32 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:11:10:11:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:14:25:14:28 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:15:10:15:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:18:27:18:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:19:10:19:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:22:36:22:39 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:23:17:23:20 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:26:38:26:41 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:27:19:27:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:30:23:30:26 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:30:34:30:37 | VariableAddress[no_q] | no_q+0:0 | no_q+0:0 | -| escape.cpp:30:45:30:48 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | -| escape.cpp:31:7:31:10 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | -| escape.cpp:32:12:32:15 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | -| escape.cpp:34:12:34:15 | VariableAddress[no_q] | no_q+0:0 | no_q+0:0 | -| escape.cpp:38:27:38:30 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:39:19:39:22 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:40:10:40:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | -| escape.cpp:105:9:105:17 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:106:9:106:11 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:108:5:108:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:109:5:109:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:109:11:109:13 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:110:5:110:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:110:17:110:19 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:111:5:111:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | -| escape.cpp:111:19:111:21 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:113:5:113:7 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:114:6:114:8 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:115:5:115:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:115:21:115:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:116:5:116:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | -| escape.cpp:116:21:116:23 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:117:5:117:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | -| escape.cpp:117:24:117:26 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:118:10:118:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:120:13:120:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:123:15:123:17 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:124:10:124:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:124:16:124:18 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:124:22:124:24 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:127:10:127:12 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:129:13:129:15 | VariableAddress[no_] | no_+0:0 | no_+0:0 | -| escape.cpp:132:9:132:16 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:133:5:133:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:134:11:134:18 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:135:5:135:12 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:136:7:136:14 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:137:5:137:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | | escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:137:17:137:24 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | | escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:138:5:138:13 | VariableAddress[no_result] | no_result+0:0 | no_result+0:0 | | escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:138:19:138:26 | VariableAddress[no_Array] | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:140:11:140:18 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:141:11:141:14 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:141:18:141:25 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:142:5:142:12 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:142:18:142:21 | VariableAddress[no_x] | no_x+0:0 | no_x+0:0 | -| escape.cpp:143:11:143:14 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:143:20:143:27 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:144:7:144:14 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:144:22:144:25 | VariableAddress[no_y] | no_y+0:0 | no_y+0:0 | -| escape.cpp:145:11:145:14 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:145:21:145:28 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:146:8:146:15 | VariableAddress[no_Point] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:146:22:146:25 | VariableAddress[no_z] | no_z+0:0 | no_z+0:0 | -| escape.cpp:148:13:148:22 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:149:5:149:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:11:150:14 | VariableAddress[no_b] | no_b+0:0 | no_b+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:18:150:27 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:151:5:151:14 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:152:11:152:15 | VariableAddress[no_i2] | no_i2+0:0 | no_i2+0:0 | | escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:152:19:152:28 | VariableAddress[no_Derived] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:154:9:154:21 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:155:10:155:13 | VariableAddress[no_p] | no_p+0:0 | no_p+0:0 | | escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:155:18:155:30 | VariableAddress[no_ssa_addrOf] | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | -| escape.cpp:157:9:157:20 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:158:10:158:13 | VariableAddress[no_r] | no_r+0:0 | no_r+0:0 | | escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:158:17:158:28 | VariableAddress[no_ssa_refTo] | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | -| escape.cpp:160:9:160:32 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:161:10:161:15 | VariableAddress[no_rae] | no_rae+0:0 | no_rae+0:0 | | escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | -| escape.cpp:161:19:161:42 | VariableAddress[no_ssa_refToArrayElement] | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | | escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | -| escape.cpp:163:9:163:25 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:164:11:164:15 | VariableAddress[no_ra] | no_ra+0:0 | no_ra+0:0 | | escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:164:24:164:40 | VariableAddress[no_ssa_refToArray] | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | -| escape.cpp:166:9:166:17 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:167:20:167:28 | VariableAddress[passByPtr] | passByPtr+0:0 | passByPtr+0:0 | -| escape.cpp:169:9:169:17 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:170:21:170:29 | VariableAddress[passByRef] | passByRef+0:0 | passByRef+0:0 | -| escape.cpp:172:9:172:24 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:173:23:173:38 | VariableAddress[no_ssa_passByPtr] | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | -| escape.cpp:175:9:175:24 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:176:24:176:39 | VariableAddress[no_ssa_passByRef] | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | -| escape.cpp:178:9:178:28 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:179:23:179:42 | VariableAddress[no_ssa_passByPtr_ret] | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | -| escape.cpp:181:9:181:28 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:182:24:182:43 | VariableAddress[no_ssa_passByRef_ret] | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | -| escape.cpp:184:9:184:18 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:185:31:185:40 | VariableAddress[passByPtr2] | passByPtr2+0:0 | passByPtr2+0:0 | -| escape.cpp:187:9:187:18 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:188:32:188:41 | VariableAddress[passByRef2] | passByRef2+0:0 | passByRef2+0:0 | -| escape.cpp:190:9:190:18 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | | escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 | -| escape.cpp:191:45:191:54 | VariableAddress[passByPtr3] | passByPtr3+0:0 | passByPtr3+0:0 | -| escape.cpp:193:9:193:18 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | | escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | -| escape.cpp:194:48:194:57 | VariableAddress[passByRef3] | passByRef3+0:0 | passByRef3+0:0 | -| escape.cpp:196:9:196:25 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | -| escape.cpp:197:9:197:25 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | -| escape.cpp:198:10:198:14 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:199:18:199:34 | VariableAddress[no_ssa_passByPtr4] | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | -| escape.cpp:199:38:199:54 | VariableAddress[no_ssa_passByPtr5] | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | -| escape.cpp:199:57:199:61 | VariableAddress[no_b2] | no_b2+0:0 | no_b2+0:0 | -| escape.cpp:201:9:201:18 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | -| escape.cpp:202:21:202:30 | VariableAddress[passByRef6] | passByRef6+0:0 | passByRef6+0:0 | -| escape.cpp:204:9:204:25 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | | escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 | -| escape.cpp:205:21:205:37 | VariableAddress[no_ssa_passByRef7] | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | -| escape.cpp:207:7:207:14 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | -| escape.cpp:209:5:209:12 | VariableAddress[no_ssa_c] | no_ssa_c+0:0 | no_ssa_c+0:0 | | escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 | -| escape.cpp:211:7:211:7 | VariableAddress[c] | c+0:0 | c+0:0 | -| escape.cpp:213:5:213:5 | VariableAddress[c] | c+0:0 | c+0:0 | -| escape.cpp:215:7:215:8 | VariableAddress[c2] | c2+0:0 | c2+0:0 | -| escape.cpp:217:15:217:16 | VariableAddress[c2] | c2+0:0 | c2+0:0 | -| escape.cpp:219:7:219:8 | VariableAddress[c3] | c3+0:0 | c3+0:0 | -| escape.cpp:221:5:221:6 | VariableAddress[c3] | c3+0:0 | c3+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | -| escape.cpp:223:7:223:8 | VariableAddress[c4] | c4+0:0 | c4+0:0 | -| escape.cpp:225:14:225:15 | VariableAddress[c4] | c4+0:0 | c4+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | -| escape.cpp:227:7:227:8 | VariableAddress[c5] | c5+0:0 | c5+0:0 | -| escape.cpp:229:5:229:6 | VariableAddress[c5] | c5+0:0 | c5+0:0 | -| escape.cpp:231:21:231:23 | VariableAddress[or1] | or1+0:0 | or1+0:0 | -| escape.cpp:232:5:232:7 | VariableAddress[or1] | or1+0:0 | or1+0:0 | -| escape.cpp:234:21:234:23 | VariableAddress[or2] | or2+0:0 | or2+0:0 | -| escape.cpp:235:14:235:16 | VariableAddress[or2] | or2+0:0 | or2+0:0 | -| escape.cpp:237:18:237:20 | VariableAddress[on1] | on1+0:0 | on1+0:0 | -| escape.cpp:238:5:238:7 | VariableAddress[on1] | on1+0:0 | on1+0:0 | -| escape.cpp:240:18:240:20 | VariableAddress[on2] | on2+0:0 | on2+0:0 | -| escape.cpp:241:14:241:16 | VariableAddress[on2] | on2+0:0 | on2+0:0 | -| escape.cpp:243:9:243:19 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 | -| escape.cpp:243:22:243:32 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 | -| escape.cpp:245:10:245:20 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | -| escape.cpp:247:2:247:12 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | -| escape.cpp:247:17:247:27 | VariableAddress[condEscape1] | condEscape1+0:0 | condEscape1+0:0 | -| escape.cpp:249:9:249:19 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | -| escape.cpp:249:24:249:34 | VariableAddress[condEscape2] | condEscape2+0:0 | condEscape2+0:0 | -| escape.cpp:251:19:251:29 | VariableAddress[no_condTemp] | no_condTemp+0:0 | no_condTemp+0:0 | diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.ql b/cpp/ql/test/library-tests/ir/escape/points_to.ql index 1c89c48ee4e..04dbf0e0060 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.ql +++ b/cpp/ql/test/library-tests/ir/escape/points_to.ql @@ -8,6 +8,7 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction from Raw::Instruction rawInstr, Un::Instruction unInstr, string rawPointsTo, string unPointsTo where rawInstr = getOldInstruction(unInstr) and + not rawInstr instanceof Raw::VariableAddressInstruction and ( exists(Variable var, int rawBitOffset, int unBitOffset | RawAA::resultPointsTo(rawInstr, Raw::getIRUserVariable(_, var), rawBitOffset) and @@ -29,6 +30,5 @@ where not UnAA::resultPointsTo(unInstr, Un::getIRUserVariable(_, var), _) and unPointsTo = "none" ) - ) and - rawPointsTo != unPointsTo + ) select rawInstr.getLocation().toString(), rawInstr.getOperationString(), rawPointsTo, unPointsTo From ef836c39bb16ebb0a88e7fea0c4588e8e0bb9841 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 7 Mar 2019 10:18:25 -0800 Subject: [PATCH 15/17] C++: respond to PR comments --- .../ir/implementation/aliased_ssa/internal/AliasAnalysis.qll | 5 ++--- .../implementation/unaliased_ssa/internal/AliasAnalysis.qll | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index db7fe197f87..fbeeb0ad5ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -177,7 +177,6 @@ private predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } - private predicate operandMayReachReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and @@ -204,7 +203,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { exists(IntValue bitOffset1, IntValue bitOffset2 | operandIsPropagated(operand, bitOffset1) and resultReturned(operand.getUseInstruction(), bitOffset2) and - bitOffset = bitOffset1 + bitOffset2 + bitOffset = Ints::add(bitOffset1, bitOffset2) ) or // The operand is used in a function call which returns it, and the return value is then returned @@ -212,7 +211,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { isArgumentForParameter(ci, operand, init) and resultReturned(init, bitOffset1) and resultReturned(ci, bitOffset2) and - bitOffset = bitOffset1 + bitOffset2 + bitOffset = Ints::add(bitOffset1, bitOffset2) ) or diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index db7fe197f87..fbeeb0ad5ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -177,7 +177,6 @@ private predicate operandEscapesNonReturn(Operand operand) { operandEscapesDomain(operand) } - private predicate operandMayReachReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned operandIsPropagated(operand, _) and @@ -204,7 +203,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { exists(IntValue bitOffset1, IntValue bitOffset2 | operandIsPropagated(operand, bitOffset1) and resultReturned(operand.getUseInstruction(), bitOffset2) and - bitOffset = bitOffset1 + bitOffset2 + bitOffset = Ints::add(bitOffset1, bitOffset2) ) or // The operand is used in a function call which returns it, and the return value is then returned @@ -212,7 +211,7 @@ private predicate operandReturned(Operand operand, IntValue bitOffset) { isArgumentForParameter(ci, operand, init) and resultReturned(init, bitOffset1) and resultReturned(ci, bitOffset2) and - bitOffset = bitOffset1 + bitOffset2 + bitOffset = Ints::add(bitOffset1, bitOffset2) ) or From 8a2a4678d85da90e80f579021b5c9c777d66b924 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 7 Mar 2019 13:06:05 -0800 Subject: [PATCH 16/17] C++: accept dataflow test change --- .../library-tests/dataflow/dataflow-tests/test_diff.expected | 1 - .../test/library-tests/dataflow/dataflow-tests/test_ir.expected | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 1eccb0fedf1..f0fc017b75c 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -1,4 +1,3 @@ -| test.cpp:66:30:66:36 | test.cpp:71:8:71:9 | AST only | | test.cpp:89:28:89:34 | test.cpp:92:8:92:14 | IR only | | test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only | | test.cpp:109:9:109:14 | test.cpp:110:10:110:12 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 5e3d4970bd7..069a5099c4f 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -6,6 +6,7 @@ | test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source | | test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source | | test.cpp:58:10:58:10 | Load: t | test.cpp:50:14:50:19 | Call: call to source | +| test.cpp:71:8:71:9 | Load: x4 | test.cpp:66:30:66:36 | InitializeParameter: source1 | | test.cpp:76:8:76:9 | Load: u1 | test.cpp:75:7:75:8 | Uninitialized: definition of u1 | | test.cpp:84:8:84:18 | Load: ... ? ... : ... | test.cpp:83:7:83:8 | Uninitialized: definition of u2 | | test.cpp:86:8:86:9 | Load: i1 | test.cpp:83:7:83:8 | Uninitialized: definition of u2 | From 07bc9ca26c73ce7b642b6916ae9fc723a04c617a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 7 Mar 2019 13:13:11 -0800 Subject: [PATCH 17/17] C++: fix whitespace --- .../ir/implementation/aliased_ssa/internal/AliasAnalysis.qll | 4 ++-- .../implementation/unaliased_ssa/internal/AliasAnalysis.qll | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index fbeeb0ad5ac..0ccbcd381bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -179,8 +179,8 @@ private predicate operandEscapesNonReturn(Operand operand) { private predicate operandMayReachReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned - operandIsPropagated(operand, _) and - resultMayReachReturn(operand.getUseInstruction()) + operandIsPropagated(operand, _) and + resultMayReachReturn(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init | diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index fbeeb0ad5ac..0ccbcd381bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -179,8 +179,8 @@ private predicate operandEscapesNonReturn(Operand operand) { private predicate operandMayReachReturn(Operand operand) { // The address is propagated to the result of the instruction, and that result itself is returned - operandIsPropagated(operand, _) and - resultMayReachReturn(operand.getUseInstruction()) + operandIsPropagated(operand, _) and + resultMayReachReturn(operand.getUseInstruction()) or // The operand is used in a function call which returns it, and the return value is then returned exists(CallInstruction ci, Instruction init |