Experimental library that tracks the length of memory.

For each pointer, we start tracking (starting from the allocation or an array declaration)
1) how long is the chunk of memory allocated
2) where the current pointer is in this chunk of memory.
This information might not always exist, but when it does, it is reliable.
Currently only works intraprocedurally.
This commit is contained in:
Cornelius Riemenschneider
2020-04-28 13:41:53 +02:00
parent 55cd0fac5c
commit e6d193294a
4 changed files with 394 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
| test.cpp:15:8:15:11 | Load: aptr | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
| test.cpp:19:8:19:8 | Load: a | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
| test.cpp:21:8:21:8 | Load: a | VNLength(Chi: ptr) | -1 | ZeroOffset | 0 |
| test.cpp:23:8:23:8 | Load: a | VNLength(Chi: ptr) | 1 | ZeroOffset | 0 |
| test.cpp:25:8:25:8 | Load: a | VNLength(Mul: ... * ...) | 0 | ZeroOffset | 0 |
| test.cpp:27:8:27:8 | Load: c | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
| test.cpp:28:8:28:24 | Convert: (unsigned char *)... | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
| test.cpp:30:8:30:8 | Load: v | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
| test.cpp:34:8:34:12 | Convert: array to pointer conversion | ZeroLength | 100 | ZeroOffset | 0 |
| test.cpp:37:10:37:10 | Load: b | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
| test.cpp:44:8:44:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
| test.cpp:53:10:53:10 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
| test.cpp:56:10:56:10 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 3 |
| test.cpp:63:10:63:14 | CopyValue: & ... | VNLength(InitializeParameter: count) | 0 | OpOffset(Load: i) | 0 |
| test.cpp:66:8:66:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
| test.cpp:68:8:68:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 3 |
| test.cpp:70:8:70:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
| test.cpp:72:8:72:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
| test.cpp:74:8:74:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | -10 |
| test.cpp:76:8:76:8 | Load: a | VNLength(InitializeParameter: count) | 1 | ZeroOffset | 0 |
| test.cpp:78:8:78:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Load: count) | 0 |
| test.cpp:80:8:80:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Load: count) | 1 |
| test.cpp:85:8:85:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 0 |
| test.cpp:87:8:87:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 1 |

View File

@@ -0,0 +1,8 @@
import cpp
import experimental.library.ArrayLengthAnalysis
from Instruction array, Length length, int delta, Offset offset, int offsetDelta
where
knownArrayLength(array, length, delta, offset, offsetDelta) and
array.getAUse() instanceof ArgumentOperand
select array, length, delta, offset, offsetDelta

View File

@@ -0,0 +1,88 @@
void *malloc(unsigned long);
void sink(...);
typedef struct A {
int a;
int b;
char * c;
} A;
void test1(unsigned int count) {
if (count < 1) {
return;
}
A* aptr = (A *) malloc(sizeof(A) * count);
sink(aptr); // (count, 0, Zero, 0)
unsigned int* ptr = &count;
sink(ptr); // (Zero, 1, Zero, 0) TODO none, as the feature is not implemented
int* a = (int *) malloc(sizeof(int) * count);
sink(a); // (count, 0, Zero, 0)
a = (int *) malloc(sizeof(int) * (count - 1));
sink(a); // (count, -1, Zero, 0)
a = (int *) malloc(sizeof(int) * (count + 1));
sink(a); // (count, 1, Zero, 0)
a = (int *) malloc(sizeof(int) * (2 * count));
sink(a); // (2*count, 0, Zero, 0)
char* c = (char *)malloc(count);
sink(c); // /count, 0, Zero, 0)
sink((unsigned char*)c); // (count, 0, Zero, 0)
void* v = c;
sink(v); // (count, 0, Zero, 0)
v = malloc(count);
sink((char *)v); // none, as we don't track void* allocations
int stack[100];
sink(stack); // (Zero, 100, Zero, 0)
for(unsigned int i = 0; i < count; ++i) {
int* b = (int*) malloc(sizeof(int) * count);
sink(b); // (count, 0, Zero, 0)
}
}
void test2(unsigned int count, bool b) {
int* a = (int *) malloc(sizeof(int) * count);
a = a + 2;
sink(a); // (count, 0, Zero, 2)
for(unsigned int i = 2; i < count; ++i) {
sink(a); // none
a++;
sink(a); // none
}
a = (int*) malloc(sizeof(int) * count);
if (b) {
a += 2;
sink(a); // (count, 0, Zero, 2)
} else {
a += 3;
sink(a); // (count, 0, Zero, 2)
}
sink(a); // none
a -= 2;
sink(a); // none
a = (int*) malloc(sizeof(int) * count);
for(unsigned int i = 0; i < count; i++) {
sink(&a[i]); // (count, 0, i, 0)
}
a = (int*) malloc(sizeof(int) * count);
sink(a); // (count, 0, Zero, 0)
a += 3;
sink(a); // (count, 0, Zero, 3)
a -= 1;
sink(a); // (count, 0, Zero, 2)
a -= 2;
sink(a); // (count, 0, Zero, 0)
a -= 10;
sink(a); // (count, 0, Zero, -10)
a = (int*) malloc(sizeof(int) * (count + 1));
sink(a); // (count, 1, Zero, 0)
a += count;
sink(a); // (count, 1, count, 0);
a += 1;
sink(a); // (count, 1, count, 1);
a -= count;
sink(a); // none
a = (int*) malloc(sizeof(int) * (count + 1));
a += count + 1;
sink(a); // TODO, should be (count, 1, count, 1), but is (count, 1, count + 1, 0)
a += 1;
sink(a); // TODO, should be (count, 1, count, 2), but is (count, 1, count + 1, 1)
}