Skip to content

Commit 6f146a6

Browse files
committed
Add regression tests for the memory analyzer
These test have been used as driving example for the memory analyzer. They test basic functionality and handling of cycles in structs.
1 parent cfeb257 commit 6f146a6

File tree

13 files changed

+398
-0
lines changed

13 files changed

+398
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This file test array support in the memory-analyzer.
5+
/// A more detailed description of the test idea is in example3.h.
6+
/// setup() prepares the data structure.
7+
/// manipulate_data() is the hook used for the test,
8+
/// where gdb reaches the breakpoint.
9+
/// main() is just the required boilerplate around this methods,
10+
/// to make the compiled result executable.
11+
12+
#include "arrays.h"
13+
14+
#include <stdio.h>
15+
#include <stdlib.h>
16+
#include <string.h>
17+
18+
void setup()
19+
{
20+
test_struct = malloc(sizeof(struct a_typet));
21+
for(int i = 0; i < 10; i++)
22+
{
23+
test_struct->config[i] = i + 10;
24+
}
25+
for(int i = 0; i < 10; i++)
26+
{
27+
test_struct->values[i] = 0xf3;
28+
}
29+
for(int i = 10; i < 20; i++)
30+
{
31+
test_struct->values[i] = 0x3f;
32+
}
33+
for(int i = 20; i < 30; i++)
34+
{
35+
test_struct->values[i] = 0x01;
36+
}
37+
for(int i = 30; i < 40; i++)
38+
{
39+
test_struct->values[i] = 0x01;
40+
}
41+
for(int i = 40; i < 50; i++)
42+
{
43+
test_struct->values[i] = 0xff;
44+
}
45+
for(int i = 50; i < 60; i++)
46+
{
47+
test_struct->values[i] = 0x00;
48+
}
49+
for(int i = 60; i < 70; i++)
50+
{
51+
test_struct->values[i] = 0xab;
52+
}
53+
messaget option1 = {.text = "accept"};
54+
for(int i = 0; i < 4; i++)
55+
{
56+
char *value = malloc(sizeof(char *));
57+
sprintf(value, "unique%i", i);
58+
entryt your_options = {
59+
.id = 1, .options[0] = option1, .options[1].text = value};
60+
your_options.id = i + 12;
61+
test_struct->childs[i].id = your_options.id;
62+
test_struct->childs[i].options[0] = your_options.options[0];
63+
test_struct->childs[i].options[1].text = your_options.options[1].text;
64+
}
65+
test_struct->initalized = true;
66+
}
67+
68+
int manipulate_data()
69+
{
70+
for(int i = 0; i < 4; i++)
71+
{
72+
free(test_struct->childs[i].options[1].text);
73+
test_struct->childs[i].options[1].text = "decline";
74+
}
75+
}
76+
77+
int main()
78+
{
79+
setup();
80+
manipulate_data();
81+
return 0;
82+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// Example3 test explicitly the array support.
5+
/// It ensures, that arrays are handled right.
6+
/// The different typedefs have been used, to make sure the memory-analyzer
7+
/// is aware of the different appeareances in the gdb responses.
8+
9+
#include <stdbool.h>
10+
11+
struct a_sub_sub_typet
12+
{
13+
char *text;
14+
};
15+
16+
typedef struct a_sub_sub_typet messaget;
17+
18+
struct a_sub_typet
19+
{
20+
int id;
21+
messaget options[2];
22+
};
23+
24+
struct a_typet
25+
{
26+
int config[10];
27+
bool initalized;
28+
unsigned char values[70];
29+
struct a_sub_typet childs[4];
30+
} * test_struct;
31+
32+
typedef struct a_sub_typet entryt;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
CORE
2+
arrays.exe
3+
--breakpoint manipulate_data --symbols test_struct
4+
analyzing symbol: test_struct
5+
GENERATED CODE:
6+
\{
7+
char id_1\[7l\]="accept";
8+
char id_2\[8l\]="unique0";
9+
char id_3\[8l\]="unique1";
10+
char id_4\[8l\]="unique2";
11+
char id_5\[8l\]="unique3";
12+
struct a_typet id_0=\{ .config=\{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 \}, .initalized=false,
13+
.values=\{ 243, 243, 243, 243, 243, 243, 243, 243, 243, 243, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171 \}, .childs=\{ \{ .id=12, .options=\{ \{ .text=\(char \*\)&id_1 \}, \{ .text=\(char \*\)&id_2 \} \} \},
14+
\{ .id=13, .options=\{ \{ .text=\(char \*\)&id_1 \}, \{ .text=\(char \*\)&id_3 \} \} \},
15+
\{ .id=14, .options=\{ \{ .text=\(char \*\)&id_1 \}, \{ .text=\(char \*\)&id_4 \} \} \},
16+
\{ .id=15, .options=\{ \{ .text=\(char \*\)&id_1 \}, \{ .text=\(char \*\)&id_5 \} \} \} \} \};
17+
test_struct = &id_0;
18+
\}
19+
--
20+
--
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/bin/bash
2+
3+
MEMORYANALYZER="../../../src/memory-analyzer/memory-analyzer"
4+
5+
set -e
6+
7+
NAME=${5%.exe}
8+
9+
goto-gcc -g -o $NAME.exe $NAME.c
10+
$MEMORYANALYZER $@
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This example deals with cyclic data structures,
5+
/// see comment in example2.h explaining why this is necessary.
6+
/// add_element is just declared as a helper method for cycle construction.
7+
/// process_buffer isn't supposed to do meaningfull stuff.
8+
/// It is the hook for the gdb breakpoint used in the test.
9+
/// free_buffer just does clean up, if you run this.
10+
11+
#include "cycles.h"
12+
void add_element(char *content)
13+
{
14+
cycle_buffer_entry_t *new_entry = malloc(sizeof(cycle_buffer_entry_t));
15+
new_entry->data = content;
16+
if(buffer.end && buffer.start)
17+
{
18+
new_entry->next = buffer.start;
19+
buffer.end->next = new_entry;
20+
buffer.end = new_entry;
21+
}
22+
else
23+
{
24+
new_entry->next = new_entry;
25+
buffer.end = new_entry;
26+
buffer.start = new_entry;
27+
}
28+
}
29+
30+
int process_buffer()
31+
{
32+
return 0;
33+
}
34+
35+
void free_buffer()
36+
{
37+
cycle_buffer_entry_t *current;
38+
cycle_buffer_entry_t *free_next;
39+
if(buffer.start)
40+
{
41+
current = buffer.start->next;
42+
while(current != buffer.start)
43+
{
44+
free_next = current;
45+
current = current->next;
46+
free(free_next);
47+
}
48+
free(current);
49+
}
50+
}
51+
52+
int main()
53+
{
54+
add_element("snow");
55+
add_element("sun");
56+
add_element("rain");
57+
add_element("thunder storm");
58+
59+
process_buffer();
60+
free_buffer();
61+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// Example2 deals with cycles in datastructures.
5+
///
6+
/// While it is common that some datastructures contain cylces,
7+
/// it is necessary that the memory-analyzer does recognize them.
8+
/// Otherwise it would follow the datastructures pointer establishing
9+
/// the cycle for ever and never terminate execution.
10+
/// The cycle_buffer described below contains a cycle.
11+
/// As long as this regression test works, cycle introduced by using pointers
12+
/// are handle the correct way.
13+
14+
#include <stdlib.h>
15+
typedef struct cycle_buffer_entry
16+
{
17+
char *data;
18+
struct cycle_buffer_entry *next;
19+
} cycle_buffer_entry_t;
20+
21+
struct cycle_buffer
22+
{
23+
cycle_buffer_entry_t *start;
24+
struct cycle_buffer_entry *end;
25+
};
26+
27+
struct cycle_buffer buffer;
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
CORE
2+
cycles.exe
3+
--breakpoint process_buffer --symbols buffer
4+
analyzing symbol: buffer
5+
GENERATED CODE:
6+
\{
7+
char id_1\[5l\]="snow";
8+
char id_3\[4l\]="sun";
9+
char id_5\[5l\]="rain";
10+
char id_7\[14l\]="thunder storm";
11+
struct cycle_buffer_entry id_6=\{ .data=\(char \*\)&id_7, .next=\(\(struct cycle_buffer_entry \*\)NULL\) \};
12+
struct cycle_buffer_entry id_4=\{ .data=\(char \*\)&id_5, .next=&id_6 \};
13+
struct cycle_buffer_entry id_2=\{ .data=\(char \*\)&id_3, .next=&id_4 \};
14+
struct cycle_buffer_entry id_0=\{ .data=\(char \*\)&id_1, .next=&id_2 \};
15+
buffer.start = &id_0;
16+
buffer.end = &id_6;
17+
\(\*\(\*\(\*\(\*buffer.start\).next\).next\).next\).next = &id_0;
18+
\}
19+
--
20+
--
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This is just a basic example.
5+
/// Pointer references are tested and ensured, that for example f and f_1 are
6+
/// pointing to the same int value location after running memory-analyzer.
7+
8+
#include "primitive_types.h"
9+
int my_function(char *s)
10+
{
11+
int a = 10;
12+
g->a = a;
13+
g->b = s;
14+
return 0;
15+
}
16+
17+
int main(int argc, char **argv)
18+
{
19+
char *test;
20+
21+
e = 17;
22+
23+
f = malloc(sizeof(int));
24+
f = &e;
25+
f_1 = f;
26+
27+
h = "test";
28+
29+
g = malloc(sizeof(struct mapping_things));
30+
d.a = 4;
31+
d.c = -32;
32+
test = "test2";
33+
34+
d.b = test;
35+
36+
my_function(test);
37+
38+
free(g);
39+
free(f);
40+
41+
return 0;
42+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// Example1 is just demonstrating, that the tool works in general.
5+
/// A small struct and a few primitive pointers are declared in the global
6+
/// namespace. These are assigned with values before calling my_function
7+
/// and then, it is tested that this global state can be reconstructed before
8+
/// calling my_function. As long as this example work basic functionallity is
9+
/// provided.
10+
11+
#include <stdlib.h>
12+
13+
struct mapping_things
14+
{
15+
int a;
16+
char *b;
17+
int c;
18+
};
19+
20+
typedef struct mapping_things other_things;
21+
22+
other_things d;
23+
int e;
24+
int *f;
25+
int *f_1;
26+
struct mapping_things *g;
27+
char *h;
28+
int my_function(char *s);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CORE
2+
primitive_types.exe
3+
--breakpoint my_function --symbols e,f,f_1,d,g,h
4+
analyzing symbol: e
5+
analyzing symbol: f
6+
analyzing symbol: f_1
7+
analyzing symbol: d
8+
analyzing symbol: g
9+
analyzing symbol: h
10+
GENERATED CODE:
11+
\{
12+
e = 17;
13+
f = &e;
14+
f_1 = &e;
15+
char id_0\[6l\]="test2";
16+
d.a = 4;
17+
d.b = \(char \*\)&id_0;
18+
d.c = -32;
19+
struct mapping_things id_1=\{ .a=0, .b=\(\(char \*\)NULL\), .c=0 \};
20+
g = &id_1;
21+
char id_2\[5l\]="test";
22+
h = \(char \*\)&id_2;
23+
}
24+
^EXIT=0
25+
^SIGNAL=0
26+
--
27+
--
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE
2+
void_pointer.exe
3+
--breakpoint void_pointer.c:17 --symbols a_void_pointer,a_second_void_pointer,a_third_void_pointer,blob
4+
analyzing symbol: blob
5+
GENERATED CODE:
6+
\{
7+
a_void_pointer = NULL;
8+
char id_0\[12l\]="test_string";
9+
a_second_void_pointer = \(char \*\)&id_0;
10+
char id_1\[7ul\]=\{ -13, -13, 'H', -1, '\\\\', '\\\\', -1 \};
11+
a_third_void_pointer = \(char \*\)&id_1;
12+
blob.size = 7;
13+
blob.data = \(char \*\)&id_1;
14+
\}
15+
--
16+
--
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//Copyright 2018 Author: Malte Mues <[email protected]>
2+
3+
/// \file
4+
/// This file initializes some void pointer in different styles.
5+
/// Later the memory-analyzer tries to reconstruct the content.
6+
7+
#include "void_pointer.h"
8+
int main()
9+
{
10+
char *char_pointer = "test_string";
11+
a_second_void_pointer = char_pointer;
12+
char bytes[] = {0xf3, 0xf3, 0x48, 0xff, 0x5c, 0x5c, 0xff};
13+
a_third_void_pointer = &bytes;
14+
15+
blob.data = bytes;
16+
blob.size = sizeof(bytes);
17+
return 0;
18+
}

0 commit comments

Comments
 (0)