1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdint.h>
4 #include <stdio.h>
5
6 /* Wanalyzer-out-of-bounds tests for buffer overflows. */
7
8 /* Avoid folding of memcpy. */
9 typedef void * (*memcpy_t) (void *dst, const void *src, size_t n);
10
11 static memcpy_t __attribute__((noinline))
12 get_memcpy (void)
13 {
14 return memcpy;
15 }
16
17
18 /* Taken from CWE-787. */
19 void test1 (void)
20 {
21 int id_sequence[3];
22
23 id_sequence[0] = 123;
24 id_sequence[1] = 234;
25 id_sequence[2] = 345;
26 id_sequence[3] = 456; /* { dg-line test1 } */
27
28 /* { dg-warning "stack-based buffer overflow" "warning" { target *-*-* } test1 } */
29 /* { dg-message "write of 4 bytes to beyond the end of 'id_sequence'" "num bad bytes note" { target *-*-* } test1 } */
30 /* { dg-message "valid subscripts for 'id_sequence' are '\\\[0\\\]' to '\\\[2\\\]'" "valid subscript note" { target *-*-* } test1 } */
31 }
32
33 void test2 (void)
34 {
35 int n = 4;
36 int arr[4];
37
38 for (int i = n - 1; i >= 0; i--)
39 arr[i] = i;
40 }
41
42 void test3 (void)
43 {
44 int n = 4;
45 int arr[4];
46
47 for (int i = n; i >= 0; i--)
48 arr[i] = i; /* { dg-line test3 } */
49
50 /* { dg-warning "stack-based buffer overflow" "warning" { target *-*-* } test3 } */
51 /* { dg-message "write of 4 bytes to beyond the end of 'arr'" "num bad bytes note" { target *-*-* } test3 } */
52 /* { dg-message "valid subscripts for 'arr' are '\\\[0\\\]' to '\\\[3\\\]'" "valid subscript note" { target *-*-* } test3 } */
53 }
54
55 void test4 (void)
56 {
57 int *arr = malloc (4 * sizeof (int));
58 if (!arr)
59 return;
60
61 int *last_el = arr + 3;
62 *last_el = 3;
63
64 free (arr);
65 }
66
67 void test5 (void)
68 {
69 int *arr = malloc (4 * sizeof (int));
70 if (!arr)
71 return;
72
73 int *last_el = arr + 4;
74 *last_el = 4; /* { dg-line test5 } */
75
76 free (arr);
77 /* { dg-warning "heap-based buffer overflow" "warning" { target *-*-* } test5 } */
78 /* { dg-message "" "note" { target *-*-* } test5 } */
79 }
80
81 /* Taken from "A Provenance-aware Memory Object Model for C". */
82 int y = 2, x = 1; /* { dg-message "capacity" } */
83 void test6 (void)
84 {
85 int *p = &x + 1;
86 int *q = &y;
87 printf ("Addresses: p=% p q=% p \n" , (void *) p, (void *) q);
88 if (memcmp (&p , &q , sizeof (p)) == 0)
89 {
90 *p = 11; /* { dg-line test6b } */
91 printf ("x=%d y=%d *p=%d *q=%d\n" , x, y, *p, *q); /* { dg-line test6c } */
92 }
93
94 /* { dg-warning "buffer overflow" "warning" { target *-*-* } test6b } */
95 /* { dg-message "" "note" { target *-*-* } test6b } */
96 /* { dg-warning "buffer over-read" "warning" { target *-*-* } test6c } */
97 /* { dg-message "" "note" { target *-*-* } test6c } */
98 }
99
100 extern int is_valid (void);
101
102 int returnChunkSize (void *ptr)
103 {
104 /* If chunk info is valid, return the size of usable memory,
105 else, return -1 to indicate an error. */
106 return is_valid () ? sizeof (*ptr) : -1;
107 }
108
109 /* Taken from CWE-787. */
110 void test7 (void)
111 {
112 memcpy_t fn = get_memcpy ();
113
114 int destBuf[4];
115 int srcBuf[4];
116 fn (destBuf, srcBuf, returnChunkSize (destBuf)); /* { dg-line test7 } */
117
118 // TODO: Should we handle widening_svalues as a follow-up?
119 /* { dg-warning "over-read" "warning" { xfail *-*-* } test7 } */
120 /* { dg-warning "use of uninitialized value" "uninit warning" { target *-*-* } test7 } */
121 /* { dg-warning "overflow" "warning" { xfail *-*-* } test7 } */
122 }