Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "stuffer/s2n_stuffer.h"
17 : :
18 : : #include <sys/param.h>
19 : :
20 : : #include "error/s2n_errno.h"
21 : : #include "utils/s2n_blob.h"
22 : : #include "utils/s2n_mem.h"
23 : : #include "utils/s2n_safety.h"
24 : :
25 : : S2N_RESULT s2n_stuffer_validate(const struct s2n_stuffer *stuffer)
26 : 587224060 : {
27 : : /**
28 : : * Note that we do not assert any properties on the tainted field,
29 : : * as any boolean value in that field is valid.
30 : : */
31 [ + + ][ + - ]: 587224060 : RESULT_ENSURE_REF(stuffer);
32 [ + + ]: 587224050 : RESULT_GUARD(s2n_blob_validate(&stuffer->blob));
33 [ # # ][ - + ]: 587224049 : RESULT_DEBUG_ENSURE(S2N_IMPLIES(stuffer->growable, stuffer->alloced), S2N_ERR_SAFETY);
[ + + ][ + - ]
34 : :
35 : : /* <= is valid because we can have a fully written/read stuffer */
36 [ # # ][ - + ]: 587224049 : RESULT_DEBUG_ENSURE(stuffer->high_water_mark <= stuffer->blob.size, S2N_ERR_SAFETY);
37 [ + - ][ + + ]: 587224049 : RESULT_DEBUG_ENSURE(stuffer->write_cursor <= stuffer->high_water_mark, S2N_ERR_SAFETY);
38 [ + - ][ + + ]: 587224047 : RESULT_DEBUG_ENSURE(stuffer->read_cursor <= stuffer->write_cursor, S2N_ERR_SAFETY);
39 : 587224046 : return S2N_RESULT_OK;
40 : 587224047 : }
41 : :
42 : : S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation)
43 : 359613 : {
44 : : /**
45 : : * Note that we need two dereferences here to decrease proof complexity
46 : : * for CBMC (see https://github.com/awslabs/s2n/issues/2290). We can roll back
47 : : * this change once CBMC can handle common subexpression elimination.
48 : : */
49 [ - + ][ # # ]: 359613 : RESULT_ENSURE_REF(reservation);
50 : 359613 : const struct s2n_stuffer_reservation reserve_obj = *reservation;
51 [ + + ]: 359613 : RESULT_GUARD(s2n_stuffer_validate(reserve_obj.stuffer));
52 : 359612 : const struct s2n_stuffer stuffer_obj = *(reserve_obj.stuffer);
53 : :
54 : : /* Verify that write_cursor + length can be represented as a uint32_t without overflow */
55 [ - + ][ # # ]: 359612 : RESULT_ENSURE_LTE(reserve_obj.write_cursor, UINT32_MAX - reserve_obj.length);
56 : : /* The entire reservation must fit between the stuffer read and write cursors */
57 [ + + ][ + - ]: 359612 : RESULT_ENSURE_LTE(reserve_obj.write_cursor + reserve_obj.length, stuffer_obj.write_cursor);
58 [ # # ][ - + ]: 359609 : RESULT_ENSURE_GTE(reserve_obj.write_cursor, stuffer_obj.read_cursor);
59 : :
60 : 359609 : return S2N_RESULT_OK;
61 : 359609 : }
62 : :
63 : : int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in)
64 : 20535037 : {
65 [ + - ][ + + ]: 20535037 : POSIX_ENSURE_MUT(stuffer);
66 [ + + ][ + + ]: 20535036 : POSIX_PRECONDITION(s2n_blob_validate(in));
67 : 20535034 : stuffer->blob = *in;
68 : 20535034 : stuffer->read_cursor = 0;
69 : 20535034 : stuffer->write_cursor = 0;
70 : 20535034 : stuffer->high_water_mark = 0;
71 : 20535034 : stuffer->alloced = 0;
72 : 20535034 : stuffer->growable = 0;
73 : 20535034 : stuffer->tainted = 0;
74 [ - + ][ + + ]: 20535034 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
75 : 20535034 : return S2N_SUCCESS;
76 : 20535034 : }
77 : :
78 : : int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in)
79 : 119925 : {
80 [ - + ][ # # ]: 119925 : POSIX_ENSURE_REF(in);
81 [ - + ]: 119925 : POSIX_GUARD(s2n_stuffer_init(stuffer, in));
82 [ - + ]: 119925 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, in->size));
83 : 119925 : return S2N_SUCCESS;
84 : 119925 : }
85 : :
86 : : int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
87 : 7365733 : {
88 [ - + ][ # # ]: 7365733 : POSIX_ENSURE_REF(stuffer);
89 : 7365733 : *stuffer = (struct s2n_stuffer){ 0 };
90 [ - + ]: 7365733 : POSIX_GUARD(s2n_alloc(&stuffer->blob, size));
91 [ - + ]: 7365733 : POSIX_GUARD(s2n_stuffer_init(stuffer, &stuffer->blob));
92 : :
93 : 7365733 : stuffer->alloced = 1;
94 : :
95 [ - + ][ + - ]: 7365733 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
96 : 7365733 : return S2N_SUCCESS;
97 : 7365733 : }
98 : :
99 : : int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
100 : 7342117 : {
101 [ - + ]: 7342117 : POSIX_GUARD(s2n_stuffer_alloc(stuffer, size));
102 : :
103 : 7342117 : stuffer->growable = 1;
104 : :
105 [ - + ][ + - ]: 7342117 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
106 : 7342117 : return S2N_SUCCESS;
107 : 7342117 : }
108 : :
109 : : int s2n_stuffer_free(struct s2n_stuffer *stuffer)
110 : 8358416 : {
111 [ - + ][ + - ]: 8358416 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
112 [ + + ]: 8358416 : if (stuffer->alloced) {
113 [ - + ]: 4058868 : POSIX_GUARD(s2n_free(&stuffer->blob));
114 : 4058868 : }
115 : 8358416 : *stuffer = (struct s2n_stuffer){ 0 };
116 : 8358416 : return S2N_SUCCESS;
117 : 8358416 : }
118 : :
119 : : int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer)
120 : 10 : {
121 [ - + ][ + - ]: 10 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
122 [ + - ]: 10 : if (stuffer->alloced) {
123 [ - + ]: 10 : POSIX_GUARD(s2n_free_without_wipe(&stuffer->blob));
124 : 10 : }
125 : 10 : *stuffer = (struct s2n_stuffer){ 0 };
126 : 10 : return S2N_SUCCESS;
127 : 10 : }
128 : :
129 : : int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size)
130 : 13842848 : {
131 [ - + ][ + - ]: 13842848 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
132 [ # # ][ - + ]: 13842848 : POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
133 [ - + ][ # # ]: 13842848 : POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
134 : :
135 [ + + ]: 13842848 : if (size == stuffer->blob.size) {
136 : 6913647 : return S2N_SUCCESS;
137 : 6913647 : }
138 : :
139 [ + + ]: 6929201 : if (size == 0) {
140 : 3310317 : s2n_stuffer_wipe(stuffer);
141 : 3310317 : return s2n_free(&stuffer->blob);
142 : 3310317 : }
143 : :
144 [ + + ]: 3618884 : if (size < stuffer->blob.size) {
145 [ - + ][ # # ]: 75 : POSIX_CHECKED_MEMSET(stuffer->blob.data + size, S2N_WIPE_PATTERN, (stuffer->blob.size - size));
[ + - ]
146 [ - + ]: 75 : if (stuffer->read_cursor > size) {
147 : 0 : stuffer->read_cursor = size;
148 : 0 : }
149 [ - + ]: 75 : if (stuffer->write_cursor > size) {
150 : 0 : stuffer->write_cursor = size;
151 : 0 : }
152 [ - + ]: 75 : if (stuffer->high_water_mark > size) {
153 : 0 : stuffer->high_water_mark = size;
154 : 0 : }
155 : 75 : stuffer->blob.size = size;
156 [ - + ][ + - ]: 75 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
157 : 75 : return S2N_SUCCESS;
158 : 75 : }
159 : :
160 [ - + ]: 3618809 : POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
161 [ - + ][ + - ]: 3618809 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
162 : 3618809 : return S2N_SUCCESS;
163 : 3618809 : }
164 : :
165 : : int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size)
166 : 857736 : {
167 [ - + ][ + - ]: 857736 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
168 [ + + ]: 857736 : if (stuffer->blob.data == NULL) {
169 [ - + ][ # # ]: 17568 : POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
170 [ + - ][ + + ]: 17568 : POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
171 [ - + ]: 17567 : POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
172 : 17567 : }
173 [ - + ][ + - ]: 857735 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
174 : 857735 : return S2N_SUCCESS;
175 : 857735 : }
176 : :
177 : : int s2n_stuffer_rewrite(struct s2n_stuffer *stuffer)
178 : 4488958 : {
179 [ - + ][ + - ]: 4488958 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
180 : 4488958 : stuffer->write_cursor = 0;
181 : 4488958 : stuffer->read_cursor = 0;
182 [ - + ][ + - ]: 4488958 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
183 : 4488958 : return S2N_SUCCESS;
184 : 4488958 : }
185 : :
186 : : int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size)
187 : 538919 : {
188 [ - + ][ + - ]: 538919 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
189 [ + + ][ + - ]: 538919 : POSIX_ENSURE(stuffer->read_cursor >= size, S2N_ERR_STUFFER_OUT_OF_DATA);
190 : 538914 : stuffer->read_cursor -= size;
191 [ - + ][ + - ]: 538914 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
192 : 538914 : return S2N_SUCCESS;
193 : 538914 : }
194 : :
195 : : int s2n_stuffer_reread(struct s2n_stuffer *stuffer)
196 : 8972272 : {
197 [ - + ][ + - ]: 8972272 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
198 : 8972272 : stuffer->read_cursor = 0;
199 : 8972272 : return S2N_SUCCESS;
200 : 8972272 : }
201 : :
202 : : int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t size)
203 : 513222 : {
204 [ - + ][ + - ]: 513222 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
205 : 513222 : uint32_t wipe_size = MIN(size, stuffer->write_cursor);
206 : :
207 : 513222 : stuffer->write_cursor -= wipe_size;
208 : 513222 : stuffer->read_cursor = MIN(stuffer->read_cursor, stuffer->write_cursor);
209 [ - + ][ # # ]: 513222 : POSIX_CHECKED_MEMSET(stuffer->blob.data + stuffer->write_cursor, S2N_WIPE_PATTERN, wipe_size);
[ + + ]
210 : :
211 [ - + ][ + - ]: 513222 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
212 : 513222 : return S2N_SUCCESS;
213 : 513222 : }
214 : :
215 : : bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer)
216 : 266655 : {
217 [ + - ][ + + ]: 266655 : return stuffer && (stuffer->read_cursor == stuffer->write_cursor) && !stuffer->tainted;
[ + + ]
218 : 266655 : }
219 : :
220 : : int s2n_stuffer_wipe(struct s2n_stuffer *stuffer)
221 : 41482575 : {
222 [ - + ][ + + ]: 41482575 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
223 [ + + ]: 41482575 : if (!s2n_stuffer_is_wiped(stuffer)) {
224 [ # # ][ - + ]: 10745550 : POSIX_CHECKED_MEMSET(stuffer->blob.data, S2N_WIPE_PATTERN, stuffer->high_water_mark);
[ + - ]
225 : 10745550 : }
226 : :
227 : 41482575 : stuffer->tainted = 0;
228 : 41482575 : stuffer->write_cursor = 0;
229 : 41482575 : stuffer->read_cursor = 0;
230 : 41482575 : stuffer->high_water_mark = 0;
231 [ - + ][ + + ]: 41482575 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
232 : 41482575 : return S2N_SUCCESS;
233 : 41482575 : }
234 : :
235 : : int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n)
236 : 36800720 : {
237 [ - + ][ + + ]: 36800720 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
238 [ + + ][ + - ]: 36800720 : POSIX_ENSURE(s2n_stuffer_data_available(stuffer) >= n, S2N_ERR_STUFFER_OUT_OF_DATA);
239 : :
240 : 36784051 : stuffer->read_cursor += n;
241 : 36784051 : return S2N_SUCCESS;
242 : 36800720 : }
243 : :
244 : : void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len)
245 : 5048924 : {
246 [ + + ]: 5048924 : PTR_GUARD_POSIX(s2n_stuffer_skip_read(stuffer, data_len));
247 : :
248 : 5048921 : stuffer->tainted = 1;
249 : :
250 [ + - ]: 5048921 : return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - data_len) : NULL;
251 : 5048924 : }
252 : :
253 : : int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
254 : 145783 : {
255 [ - + ][ # # ]: 145783 : POSIX_ENSURE_REF(out);
256 : :
257 : 145783 : return s2n_stuffer_read_bytes(stuffer, out->data, out->size);
258 : 145783 : }
259 : :
260 : : int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
261 : 193812 : {
262 [ - + ]: 193812 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, out->size));
263 : :
264 [ + - ]: 193812 : void *ptr = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - out->size) : NULL;
265 [ # # ][ - + ]: 193812 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, out->size), S2N_ERR_NULL);
[ + - ]
266 : :
267 [ - + ][ # # ]: 193812 : POSIX_CHECKED_MEMCPY(out->data, ptr, out->size);
[ + - ]
268 [ - + ][ # # ]: 193812 : POSIX_CHECKED_MEMSET(ptr, 0, out->size);
[ + - ]
269 : :
270 : 193812 : return S2N_SUCCESS;
271 : 193812 : }
272 : :
273 : : int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
274 : 23457453 : {
275 [ + - ][ + + ]: 23457453 : POSIX_ENSURE_REF(data);
276 [ + + ][ + + ]: 23457451 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
277 [ + + ]: 23457450 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
278 [ - + ][ # # ]: 23440792 : POSIX_ENSURE_REF(stuffer->blob.data);
279 : 23440792 : void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
280 : :
281 [ - + ][ # # ]: 23440792 : POSIX_CHECKED_MEMCPY(data, ptr, size);
[ + + ]
282 : :
283 : 23440792 : return S2N_SUCCESS;
284 : 23440792 : }
285 : :
286 : : int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
287 : 7483 : {
288 [ - + ]: 7483 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
289 [ - + ][ # # ]: 7483 : POSIX_ENSURE_REF(stuffer->blob.data);
290 : 7483 : void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
291 : :
292 [ - + ][ # # ]: 7483 : POSIX_CHECKED_MEMCPY(data, ptr, size);
[ + - ]
293 [ - + ][ # # ]: 7483 : POSIX_CHECKED_MEMSET(ptr, 0, size);
[ + - ]
294 : :
295 : 7483 : return S2N_SUCCESS;
296 : 7483 : }
297 : :
298 : : int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n)
299 : 68712135 : {
300 [ - + ][ + + ]: 68712135 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
301 [ + + ]: 68712135 : POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, n));
302 : 68694659 : stuffer->write_cursor += n;
303 : 68694659 : stuffer->high_water_mark = MAX(stuffer->write_cursor, stuffer->high_water_mark);
304 [ - + ][ + + ]: 68694659 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
305 : 68694659 : return S2N_SUCCESS;
306 : 68694659 : }
307 : :
308 : : void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len)
309 : 7265679 : {
310 [ + + ]: 7265679 : PTR_GUARD_POSIX(s2n_stuffer_skip_write(stuffer, data_len));
311 : :
312 : 7265678 : stuffer->tainted = 1;
313 : :
314 [ + - ]: 7265678 : return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - data_len) : NULL;
315 : 7265679 : }
316 : :
317 : : int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in)
318 : 539815 : {
319 [ + + ][ + + ]: 539815 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
320 [ - + ][ + - ]: 539813 : POSIX_PRECONDITION(s2n_blob_validate(in));
321 : 539813 : return s2n_stuffer_write_bytes(stuffer, in->data, in->size);
322 : 539813 : }
323 : :
324 : : int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *data, const uint32_t size)
325 : 37415575 : {
326 [ + + ]: 37415575 : if (size == 0) {
327 : 119445 : return S2N_SUCCESS;
328 : 119445 : }
329 : :
330 [ # # ][ + + ]: 37296130 : POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_SAFETY);
[ + - ]
331 [ - + ][ + + ]: 37296130 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
332 [ + + ]: 37296130 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, size));
333 : :
334 : 37278660 : void *ptr = stuffer->blob.data + stuffer->write_cursor - size;
335 [ # # ][ + + ]: 37278660 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
[ + - ]
336 : :
337 [ + + ]: 37278660 : if (ptr == data) {
338 [ - + ][ + - ]: 7592 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
339 : 7592 : return S2N_SUCCESS;
340 : 7592 : }
341 : :
342 [ - + ][ # # ]: 37271068 : POSIX_CHECKED_MEMCPY(ptr, data, size);
[ + + ]
343 : :
344 [ - + ][ + + ]: 37271068 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
345 : 37271068 : return S2N_SUCCESS;
346 : 37271068 : }
347 : :
348 : : int s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count, uint32_t offs,
349 : : uint32_t size)
350 : 3603040 : {
351 [ - + ][ + - ]: 3603040 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
352 [ - + ][ # # ]: 3603040 : POSIX_ENSURE_REF(iov);
353 : 3603040 : void *ptr = s2n_stuffer_raw_write(stuffer, size);
354 [ # # ][ + + ]: 3603040 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
[ + - ]
355 : :
356 : 3603040 : size_t size_left = size, to_skip = offs;
357 [ + + ]: 3634495 : for (size_t i = 0; i < iov_count; i++) {
358 [ + + ]: 3634402 : if (to_skip >= iov[i].iov_len) {
359 : 31371 : to_skip -= iov[i].iov_len;
360 : 31371 : continue;
361 : 31371 : }
362 : 3603031 : size_t iov_len_op = iov[i].iov_len - to_skip;
363 [ - + ][ # # ]: 3603031 : POSIX_ENSURE_LTE(iov_len_op, UINT32_MAX);
364 : 3603031 : uint32_t iov_len = (uint32_t) iov_len_op;
365 : 3603031 : uint32_t iov_size_to_take = MIN(size_left, iov_len);
366 [ - + ][ # # ]: 3603031 : POSIX_ENSURE_REF(iov[i].iov_base);
367 [ - + ][ # # ]: 3603031 : POSIX_ENSURE_LT(to_skip, iov[i].iov_len);
368 [ - + ][ # # ]: 3603031 : POSIX_CHECKED_MEMCPY(ptr, ((uint8_t *) (iov[i].iov_base)) + to_skip, iov_size_to_take);
[ + - ]
369 : 3603031 : size_left -= iov_size_to_take;
370 [ + + ]: 3603031 : if (size_left == 0) {
371 : 3602947 : break;
372 : 3602947 : }
373 : 84 : ptr = (void *) ((uint8_t *) ptr + iov_size_to_take);
374 : 84 : to_skip = 0;
375 : 84 : }
376 : :
377 : 3603040 : return S2N_SUCCESS;
378 : 3603040 : }
379 : :
380 : : static int s2n_stuffer_copy_impl(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
381 : 7337605 : {
382 [ - + ]: 7337605 : POSIX_GUARD(s2n_stuffer_skip_read(from, len));
383 [ - + ]: 7337605 : POSIX_GUARD(s2n_stuffer_skip_write(to, len));
384 : :
385 [ + - ]: 7337605 : uint8_t *from_ptr = (from->blob.data) ? (from->blob.data + from->read_cursor - len) : NULL;
386 [ + - ]: 7337605 : uint8_t *to_ptr = (to->blob.data) ? (to->blob.data + to->write_cursor - len) : NULL;
387 : :
388 [ # # ][ - + ]: 7337605 : POSIX_CHECKED_MEMCPY(to_ptr, from_ptr, len);
[ + + ]
389 : :
390 : 7337605 : return S2N_SUCCESS;
391 : 7337605 : }
392 : :
393 : : int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n)
394 : 69659425 : {
395 [ - + ][ + + ]: 69659425 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
396 [ + + ]: 69659425 : if (s2n_stuffer_space_remaining(stuffer) < n) {
397 [ + + ][ + - ]: 3507516 : POSIX_ENSURE(stuffer->growable, S2N_ERR_STUFFER_IS_FULL);
398 : : /* Always grow a stuffer by at least 1k */
399 : 3490039 : const uint32_t growth = MAX(n - s2n_stuffer_space_remaining(stuffer), S2N_MIN_STUFFER_GROWTH_IN_BYTES);
400 : 3490039 : uint32_t new_size = 0;
401 [ - + ]: 3490039 : POSIX_GUARD(s2n_add_overflow(stuffer->blob.size, growth, &new_size));
402 [ - + ]: 3490039 : POSIX_GUARD(s2n_stuffer_resize(stuffer, new_size));
403 : 3490039 : }
404 [ - + ][ + + ]: 69641948 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
405 : 69641948 : return S2N_SUCCESS;
406 : 69641948 : }
407 : :
408 : : /* Copies "len" bytes from "from" to "to".
409 : : * If the copy cannot succeed (i.e. there are either not enough bytes available, or there is not enough space to write them
410 : : * restore the old value of the stuffer */
411 : : int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
412 : 7337605 : {
413 : 7337605 : const uint32_t orig_read_cursor = from->read_cursor;
414 : 7337605 : const uint32_t orig_write_cursor = to->write_cursor;
415 : :
416 [ - + ]: 7337605 : if (s2n_stuffer_copy_impl(from, to, len) < 0) {
417 : 0 : from->read_cursor = orig_read_cursor;
418 : 0 : to->write_cursor = orig_write_cursor;
419 : 0 : S2N_ERROR_PRESERVE_ERRNO();
420 : 0 : }
421 : :
422 : 7337605 : return S2N_SUCCESS;
423 : 7337605 : }
424 : :
425 : : int s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out)
426 : 23 : {
427 [ - + ][ + - ]: 23 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
428 [ # # ][ - + ]: 23 : POSIX_ENSURE_REF(out);
429 [ - + ]: 23 : POSIX_GUARD(s2n_realloc(out, s2n_stuffer_data_available(stuffer)));
430 : :
431 [ + - ]: 23 : if (s2n_stuffer_data_available(stuffer) > 0) {
432 [ - + ][ # # ]: 23 : POSIX_CHECKED_MEMCPY(out->data, stuffer->blob.data + stuffer->read_cursor, s2n_stuffer_data_available(stuffer));
[ + - ]
433 : 23 : }
434 : :
435 [ - + ][ + - ]: 23 : POSIX_POSTCONDITION(s2n_blob_validate(out));
436 : 23 : return S2N_SUCCESS;
437 : 23 : }
438 : :
439 : : int s2n_stuffer_shift(struct s2n_stuffer *stuffer)
440 : 508 : {
441 [ + - ][ + + ]: 508 : POSIX_ENSURE_REF(stuffer);
442 : 507 : struct s2n_stuffer copy = *stuffer;
443 [ - + ]: 507 : POSIX_GUARD(s2n_stuffer_rewrite(©));
444 : :
445 : 507 : uint8_t *data = stuffer->blob.data;
446 : : /* Adding 0 to a NULL value is undefined behavior */
447 [ + + ]: 507 : if (stuffer->read_cursor != 0) {
448 : 505 : data += stuffer->read_cursor;
449 : 505 : }
450 : :
451 : 507 : uint32_t data_size = s2n_stuffer_data_available(stuffer);
452 [ - + ]: 507 : POSIX_GUARD(s2n_stuffer_write_bytes(©, data, data_size));
453 : 507 : *stuffer = copy;
454 : 507 : return S2N_SUCCESS;
455 : 507 : }
|