1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
#include "analyzer-decls.h"
#define NULL ((void *)0)
typedef __SIZE_TYPE__ size_t;
void test_terminated (void)
{
__analyzer_eval (__analyzer_get_strlen ("abc") == 3); /* { dg-warning "TRUE" } */
}
void test_unterminated (void)
{
char buf[3] = "abc";
__analyzer_get_strlen (buf); /* { dg-warning "stack-based buffer over-read" } */
/* { dg-message "out-of-bounds read at byte 3 but 'buf' ends at byte 3" "bad read event" { target *-*-* } .-1 } */
/* { dg-message "while looking for null terminator for argument 1 \\('&buf'\\) of '__analyzer_get_strlen'..." "null terminator event" { target *-*-* } .-2 } */
}
void test_embedded_nuls (void)
{
/* 0123 456 78. */
char buf[9] = "abc\0pq\0xy"; /* unterminated. */
__analyzer_eval (__analyzer_get_strlen (buf) == 3); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 1) == 2); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 2) == 1); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 3) == 0); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 4) == 2); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 5) == 1); /* { dg-warning "TRUE" } */
__analyzer_eval (__analyzer_get_strlen (buf + 6) == 0); /* { dg-warning "TRUE" } */
__analyzer_get_strlen (buf + 7); /* { dg-warning "stack-based buffer over-read" } */
/* { dg-message "while looking for null terminator for argument 1 \\('<unknown>'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
// TODO: fix the "<unknown>" here?
}
void test_before_start_of_buffer (void)
{
const char *buf = "abc";
__analyzer_get_strlen (buf - 1); /* { dg-warning "buffer under-read" } */
/* { dg-message "while looking for null terminator for argument 1 \\('<unknown>'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
// TODO: fix the "<unknown>" here?
}
void test_after_end_of_buffer (void)
{
const char *buf = "abc";
__analyzer_get_strlen (buf + 4); /* { dg-warning "buffer over-read" } */
/* { dg-message "while looking for null terminator for argument 1 \\('<unknown>'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
// TODO: fix the "<unknown>" here?
}
void test_fully_initialized_but_unterminated (void)
{
char buf[3];
buf[0] = 'a';
buf[1] = 'b';
buf[2] = 'c';
__analyzer_get_strlen (buf); /* { dg-warning "stack-based buffer over-read" } */
/* { dg-message "while looking for null terminator for argument 1 \\('&buf'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
}
void test_uninitialized (void)
{
char buf[16];
__analyzer_get_strlen (buf); /* { dg-warning "use of uninitialized value 'buf\\\[0\\\]'" } */
/* { dg-message "while looking for null terminator for argument 1 \\('&buf'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
}
void test_partially_initialized (void)
{
char buf[16];
buf[0] = 'a';
__analyzer_get_strlen (buf); /* { dg-warning "use of uninitialized value 'buf\\\[1\\\]'" } */
/* { dg-message "while looking for null terminator for argument 1 \\('&buf'\\) of '__analyzer_get_strlen'..." "event" { target *-*-* } .-1 } */
}
char *test_dynamic_1 (void)
{
const char *kvstr = "NAME=value";
size_t len = __builtin_strlen (kvstr);
char *ptr = __builtin_malloc (len + 1);
if (!ptr)
return NULL;
__builtin_memcpy (ptr, kvstr, len);
ptr[len] = '\0';
__analyzer_eval (__analyzer_get_strlen (ptr) == 10); /* { dg-warning "UNKNOWN" } */
// TODO: should be TRUE
return ptr;
}
char *test_dynamic_2 (void)
{
const char *kvstr = "NAME=value";
size_t len = __builtin_strlen (kvstr);
char *ptr = __builtin_malloc (len + 1);
if (!ptr)
return NULL;
__builtin_memcpy (ptr, kvstr, len);
/* Missing termination. */
__analyzer_get_strlen (ptr); /* { dg-warning "use of uninitialized value '&buf'" "" { xfail *-*-* } } */
// TODO (xfail)
return ptr;
}
char *test_dynamic_3 (const char *src)
{
size_t len = __builtin_strlen (src);
char *ptr = __builtin_malloc (len + 1);
if (!ptr)
return NULL;
__builtin_memcpy (ptr, src, len);
ptr[len] = '\0';
__analyzer_eval (__analyzer_get_strlen (ptr) == len); /* { dg-warning "UNKNOWN" } */
// TODO: should get TRUE for this
return ptr;
}
char *test_dynamic_4 (const char *src)
{
size_t len = __builtin_strlen (src);
char *ptr = __builtin_malloc (len + 1);
if (!ptr)
return NULL;
__builtin_memcpy (ptr, src, len);
/* Missing termination. */
__analyzer_get_strlen (ptr); /* { dg-warning "use of uninitialized value 'buf\\\[len\\\]'" "" { xfail *-*-* } } */
// TODO (xfail)
return ptr;
}
void test_symbolic_ptr (const char *ptr)
{
__analyzer_describe (0, __analyzer_get_strlen (ptr)); /* { dg-warning "CONJURED" } */
}
void test_symbolic_offset (size_t idx)
{
__analyzer_describe (0, __analyzer_get_strlen ("abc" + idx)); /* { dg-warning "CONJURED" } */
}
void test_casts (void)
{
int i = 42;
const char *p = (const char *)&i;
__analyzer_eval (__analyzer_get_strlen (p) == 0); /* { dg-warning "UNKNOWN" } */
__analyzer_eval (__analyzer_get_strlen (p + 1) == 0); /* { dg-warning "UNKNOWN" } */
}
void test_filled_nonzero (void)
{
char buf[10];
__builtin_memset (buf, 'a', 10);
__analyzer_get_strlen (buf); /* { dg-warning "stack-based buffer over-read" "" { xfail *-*-* } } */
}
void test_filled_zero (void)
{
char buf[10];
__builtin_memset (buf, 0, 10);
__analyzer_eval (__analyzer_get_strlen (buf) == 0); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
/* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
__analyzer_eval (__analyzer_get_strlen (buf + 1) == 0); /* { dg-warning "TRUE" "correct" { xfail *-*-* } } */
/* { dg-bogus "UNKNOWN" "status quo" { xfail *-*-* } .-1 } */
}
void test_filled_symbolic (int c)
{
char buf[10];
__builtin_memset (buf, c, 10);
__analyzer_eval (__analyzer_get_strlen (buf) == 0); /* { dg-warning "UNKNOWN" } */
}
|