Branch data Line data Source code
1 : : /*
2 : : Copyright 2019 David Robillard <http://drobilla.net>
3 : :
4 : : Permission to use, copy, modify, and/or distribute this software for any
5 : : purpose with or without fee is hereby granted, provided that the above
6 : : copyright notice and this permission notice appear in all copies.
7 : :
8 : : THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 : : WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 : : MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 : : ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 : : WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 : : ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 : : OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 : : */
16 : :
17 : : #include "lv2/atom/atom-test-utils.c"
18 : : #include "lv2/atom/atom.h"
19 : : #include "lv2/atom/forge.h"
20 : : #include "lv2/atom/util.h"
21 : : #include "lv2/urid/urid.h"
22 : :
23 : : #include <assert.h>
24 : : #include <stdint.h>
25 : : #include <stdlib.h>
26 : : #include <string.h>
27 : :
28 : : static int
29 : 1 : test_string_overflow(void)
30 : : {
31 : : #define MAX_CHARS 15
32 : :
33 : : static const size_t capacity = sizeof(LV2_Atom_String) + MAX_CHARS + 1;
34 : : static const char* str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
35 : :
36 : 1 : uint8_t* buf = (uint8_t*)malloc(capacity);
37 : 1 : LV2_URID_Map map = { NULL, urid_map };
38 : : LV2_Atom_Forge forge;
39 : 1 : lv2_atom_forge_init(&forge, &map);
40 : :
41 : : // Check that writing increasingly long strings fails at the right point
42 [ + + ]: 16 : for (size_t count = 0; count < MAX_CHARS; ++count) {
43 : 15 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
44 : :
45 : : const LV2_Atom_Forge_Ref ref =
46 : 15 : lv2_atom_forge_string(&forge, str, count);
47 [ - + ]: 15 : if (!ref) {
48 : 0 : return test_fail("Failed to write %zu byte string\n", count);
49 : : }
50 : : }
51 : :
52 : : // Failure writing to an exactly full forge
53 : 1 : LV2_Atom_Forge_Ref ref = 0;
54 [ - + ]: 1 : if ((ref = lv2_atom_forge_string(&forge, str, MAX_CHARS + 1))) {
55 : 0 : return test_fail("Successfully wrote past end of buffer\n");
56 : : }
57 : :
58 : : // Failure writing body after successfully writing header
59 : 1 : lv2_atom_forge_set_buffer(&forge, buf, sizeof(LV2_Atom) + 1);
60 [ - + ]: 1 : if ((ref = lv2_atom_forge_string(&forge, "AB", 2))) {
61 : 0 : return test_fail("Successfully wrote atom header past end\n");
62 : : }
63 : :
64 : 1 : free(buf);
65 : 1 : return 0;
66 : : }
67 : :
68 : : static int
69 : 1 : test_literal_overflow(void)
70 : : {
71 : : static const size_t capacity = sizeof(LV2_Atom_Literal) + 2;
72 : :
73 : 1 : uint8_t* buf = (uint8_t*)malloc(capacity);
74 : 1 : LV2_URID_Map map = { NULL, urid_map };
75 : 1 : LV2_Atom_Forge_Ref ref = 0;
76 : : LV2_Atom_Forge forge;
77 : 1 : lv2_atom_forge_init(&forge, &map);
78 : :
79 : : // Failure in atom header
80 : 1 : lv2_atom_forge_set_buffer(&forge, buf, 1);
81 [ - + ]: 1 : if ((ref = lv2_atom_forge_literal(&forge, "A", 1, 0, 0))) {
82 : 0 : return test_fail("Successfully wrote atom header past end\n");
83 : : }
84 : :
85 : : // Failure in literal header
86 : 1 : lv2_atom_forge_set_buffer(&forge, buf, sizeof(LV2_Atom) + 1);
87 [ - + ]: 1 : if ((ref = lv2_atom_forge_literal(&forge, "A", 1, 0, 0))) {
88 : 0 : return test_fail("Successfully wrote literal header past end\n");
89 : : }
90 : :
91 : : // Success (only room for one character + null terminator)
92 : 1 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
93 [ - + ]: 1 : if (!(ref = lv2_atom_forge_literal(&forge, "A", 1, 0, 0))) {
94 : 0 : return test_fail("Failed to write small enough literal\n");
95 : : }
96 : :
97 : : // Failure in body
98 : 1 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
99 [ - + ]: 1 : if ((ref = lv2_atom_forge_literal(&forge, "AB", 2, 0, 0))) {
100 : 0 : return test_fail("Successfully wrote literal body past end\n");
101 : : }
102 : :
103 : 1 : free(buf);
104 : 1 : return 0;
105 : : }
106 : :
107 : : static int
108 : 1 : test_sequence_overflow(void)
109 : : {
110 : : static const size_t size = sizeof(LV2_Atom_Sequence) + 6 * sizeof(LV2_Atom);
111 : 1 : LV2_URID_Map map = { NULL, urid_map };
112 : :
113 : : // Test over a range that fails in the sequence header and event components
114 [ + + ]: 64 : for (size_t capacity = 1; capacity < size; ++capacity) {
115 : 63 : uint8_t* buf = (uint8_t*)malloc(capacity);
116 : :
117 : : LV2_Atom_Forge forge;
118 : 63 : lv2_atom_forge_init(&forge, &map);
119 : 63 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
120 : :
121 : : LV2_Atom_Forge_Frame frame;
122 : : LV2_Atom_Forge_Ref ref =
123 : 63 : lv2_atom_forge_sequence_head(&forge, &frame, 0);
124 : :
125 [ + + ][ - + ]: 63 : assert(capacity >= sizeof(LV2_Atom_Sequence) || !frame.ref);
126 [ + + ][ - + ]: 63 : assert(capacity >= sizeof(LV2_Atom_Sequence) || !ref);
127 : :
128 : 63 : lv2_atom_forge_frame_time(&forge, 0);
129 : 63 : lv2_atom_forge_int(&forge, 42);
130 : 63 : lv2_atom_forge_pop(&forge, &frame);
131 : :
132 : 63 : free(buf);
133 : : }
134 : :
135 : 1 : return 0;
136 : : }
137 : :
138 : : static int
139 : 1 : test_vector_head_overflow(void)
140 : : {
141 : : static const size_t size = sizeof(LV2_Atom_Vector) + 3 * sizeof(LV2_Atom);
142 : 1 : LV2_URID_Map map = { NULL, urid_map };
143 : :
144 : : // Test over a range that fails in the vector header and elements
145 [ + + ]: 40 : for (size_t capacity = 1; capacity < size; ++capacity) {
146 : 39 : uint8_t* buf = (uint8_t*)malloc(capacity);
147 : :
148 : : LV2_Atom_Forge forge;
149 : 39 : lv2_atom_forge_init(&forge, &map);
150 : 39 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
151 : :
152 : : LV2_Atom_Forge_Frame frame;
153 : 39 : LV2_Atom_Forge_Ref ref = lv2_atom_forge_vector_head(
154 : : &forge, &frame, sizeof(int32_t), forge.Int);
155 : :
156 [ + + ][ - + ]: 39 : assert(capacity >= sizeof(LV2_Atom_Vector) || !frame.ref);
157 [ + + ][ - + ]: 39 : assert(capacity >= sizeof(LV2_Atom_Vector) || !ref);
158 : :
159 : 39 : lv2_atom_forge_int(&forge, 1);
160 : 39 : lv2_atom_forge_int(&forge, 2);
161 : 39 : lv2_atom_forge_int(&forge, 3);
162 : 39 : lv2_atom_forge_pop(&forge, &frame);
163 : :
164 : 39 : free(buf);
165 : : }
166 : :
167 : 1 : return 0;
168 : : }
169 : :
170 : : static int
171 : 1 : test_vector_overflow(void)
172 : : {
173 : : static const size_t size = sizeof(LV2_Atom_Vector) + 3 * sizeof(LV2_Atom);
174 : : static const int32_t vec[] = { 1, 2, 3 };
175 : 1 : LV2_URID_Map map = { NULL, urid_map };
176 : :
177 : : // Test over a range that fails in the vector header and elements
178 [ + + ]: 40 : for (size_t capacity = 1; capacity < size; ++capacity) {
179 : 39 : uint8_t* buf = (uint8_t*)malloc(capacity);
180 : :
181 : : LV2_Atom_Forge forge;
182 : 39 : lv2_atom_forge_init(&forge, &map);
183 : 39 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
184 : :
185 : 39 : LV2_Atom_Forge_Ref ref = lv2_atom_forge_vector(
186 : : &forge, sizeof(int32_t), forge.Int, 3, vec);
187 : :
188 [ + + ][ - + ]: 39 : assert(capacity >= sizeof(LV2_Atom_Vector) || !ref);
189 : :
190 : 39 : free(buf);
191 : : }
192 : :
193 : 1 : return 0;
194 : : }
195 : :
196 : : static int
197 : 1 : test_tuple_overflow(void)
198 : : {
199 : : static const size_t size = sizeof(LV2_Atom_Tuple) + 3 * sizeof(LV2_Atom);
200 : 1 : LV2_URID_Map map = { NULL, urid_map };
201 : :
202 : : // Test over a range that fails in the tuple header and elements
203 [ + + ]: 32 : for (size_t capacity = 1; capacity < size; ++capacity) {
204 : 31 : uint8_t* buf = (uint8_t*)malloc(capacity);
205 : :
206 : : LV2_Atom_Forge forge;
207 : 31 : lv2_atom_forge_init(&forge, &map);
208 : 31 : lv2_atom_forge_set_buffer(&forge, buf, capacity);
209 : :
210 : : LV2_Atom_Forge_Frame frame;
211 : 31 : LV2_Atom_Forge_Ref ref = lv2_atom_forge_tuple(&forge, &frame);
212 : :
213 [ + + ][ - + ]: 31 : assert(capacity >= sizeof(LV2_Atom_Tuple) || !frame.ref);
214 [ + + ][ - + ]: 31 : assert(capacity >= sizeof(LV2_Atom_Tuple) || !ref);
215 : :
216 : 31 : lv2_atom_forge_int(&forge, 1);
217 : 31 : lv2_atom_forge_float(&forge, 2.0f);
218 : 31 : lv2_atom_forge_string(&forge, "three", 5);
219 : 31 : lv2_atom_forge_pop(&forge, &frame);
220 : :
221 : 31 : free(buf);
222 : : }
223 : :
224 : 1 : return 0;
225 : : }
226 : :
227 : : int
228 : 1 : main(void)
229 : : {
230 [ + - + - ]: 3 : const int ret = test_string_overflow() || test_literal_overflow() ||
231 [ + - + - ]: 3 : test_sequence_overflow() || test_vector_head_overflow() ||
232 [ + - ][ - + ]: 3 : test_vector_overflow() || test_tuple_overflow();
233 : :
234 : 1 : free_urid_map();
235 : :
236 : 1 : return ret;
237 : : }
|