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 "error/s2n_errno.h"
19 : : #include "utils/s2n_blob.h"
20 : : #include "utils/s2n_mem.h"
21 : : #include "utils/s2n_safety.h"
22 : :
23 : : S2N_RESULT s2n_stuffer_validate(const struct s2n_stuffer *stuffer)
24 : 536013749 : {
25 : : /**
26 : : * Note that we do not assert any properties on the tainted field,
27 : : * as any boolean value in that field is valid.
28 : : */
29 [ + + ][ + - ]: 536013749 : RESULT_ENSURE_REF(stuffer);
30 [ + + ]: 536013739 : RESULT_GUARD(s2n_blob_validate(&stuffer->blob));
31 [ # # ][ - + ]: 536013738 : RESULT_DEBUG_ENSURE(S2N_IMPLIES(stuffer->growable, stuffer->alloced), S2N_ERR_SAFETY);
[ + + ][ + - ]
32 : :
33 : : /* <= is valid because we can have a fully written/read stuffer */
34 [ # # ][ - + ]: 536013738 : RESULT_DEBUG_ENSURE(stuffer->high_water_mark <= stuffer->blob.size, S2N_ERR_SAFETY);
35 [ + - ][ + + ]: 536013738 : RESULT_DEBUG_ENSURE(stuffer->write_cursor <= stuffer->high_water_mark, S2N_ERR_SAFETY);
36 [ + - ][ + + ]: 536013736 : RESULT_DEBUG_ENSURE(stuffer->read_cursor <= stuffer->write_cursor, S2N_ERR_SAFETY);
37 : 536013735 : return S2N_RESULT_OK;
38 : 536013736 : }
39 : :
40 : : S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation)
41 : 390330 : {
42 : : /**
43 : : * Note that we need two dereferences here to decrease proof complexity
44 : : * for CBMC (see https://github.com/awslabs/s2n/issues/2290). We can roll back
45 : : * this change once CBMC can handle common subexpression elimination.
46 : : */
47 [ - + ][ # # ]: 390330 : RESULT_ENSURE_REF(reservation);
48 : 390330 : const struct s2n_stuffer_reservation reserve_obj = *reservation;
49 [ + + ]: 390330 : RESULT_GUARD(s2n_stuffer_validate(reserve_obj.stuffer));
50 : 390329 : const struct s2n_stuffer stuffer_obj = *(reserve_obj.stuffer);
51 : :
52 : : /* Verify that write_cursor + length can be represented as a uint32_t without overflow */
53 [ - + ][ # # ]: 390329 : RESULT_ENSURE_LTE(reserve_obj.write_cursor, UINT32_MAX - reserve_obj.length);
54 : : /* The entire reservation must fit between the stuffer read and write cursors */
55 [ + + ][ + - ]: 390329 : RESULT_ENSURE_LTE(reserve_obj.write_cursor + reserve_obj.length, stuffer_obj.write_cursor);
56 [ # # ][ - + ]: 390326 : RESULT_ENSURE_GTE(reserve_obj.write_cursor, stuffer_obj.read_cursor);
57 : :
58 : 390326 : return S2N_RESULT_OK;
59 : 390326 : }
60 : :
61 : : /**
62 : : * Initialize a stuffer to reference some data `in`.
63 : : *
64 : : * `stuffer` will not own the data, and the caller is responsible for ensuring that
65 : : * the data pointed to by `in` outlives `stuffer`.
66 : : */
67 : : int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in)
68 : 18831097 : {
69 [ + - ][ + + ]: 18831097 : POSIX_ENSURE_MUT(stuffer);
70 [ + + ][ + + ]: 18831096 : POSIX_PRECONDITION(s2n_blob_validate(in));
71 : 18831094 : stuffer->blob = *in;
72 : 18831094 : stuffer->read_cursor = 0;
73 : 18831094 : stuffer->write_cursor = 0;
74 : 18831094 : stuffer->high_water_mark = 0;
75 : 18831094 : stuffer->alloced = 0;
76 : 18831094 : stuffer->growable = 0;
77 : 18831094 : stuffer->tainted = 0;
78 [ - + ][ + - ]: 18831094 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
79 : 18831094 : return S2N_SUCCESS;
80 : 18831094 : }
81 : :
82 : : int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in)
83 : 120712 : {
84 [ - + ][ # # ]: 120712 : POSIX_ENSURE_REF(in);
85 [ - + ]: 120712 : POSIX_GUARD(s2n_stuffer_init(stuffer, in));
86 [ - + ]: 120712 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, in->size));
87 : 120712 : return S2N_SUCCESS;
88 : 120712 : }
89 : :
90 : : int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
91 : 7376867 : {
92 [ - + ][ # # ]: 7376867 : POSIX_ENSURE_REF(stuffer);
93 : 7376867 : *stuffer = (struct s2n_stuffer){ 0 };
94 [ - + ]: 7376867 : POSIX_GUARD(s2n_alloc(&stuffer->blob, size));
95 [ - + ]: 7376867 : POSIX_GUARD(s2n_stuffer_init(stuffer, &stuffer->blob));
96 : :
97 : 7376867 : stuffer->alloced = 1;
98 : :
99 [ - + ][ + - ]: 7376867 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
100 : 7376867 : return S2N_SUCCESS;
101 : 7376867 : }
102 : :
103 : : int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
104 : 7351792 : {
105 [ - + ]: 7351792 : POSIX_GUARD(s2n_stuffer_alloc(stuffer, size));
106 : :
107 : 7351792 : stuffer->growable = 1;
108 : :
109 [ - + ][ + - ]: 7351792 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
110 : 7351792 : return S2N_SUCCESS;
111 : 7351792 : }
112 : :
113 : : int s2n_stuffer_free(struct s2n_stuffer *stuffer)
114 : 8358842 : {
115 [ - + ][ + - ]: 8358842 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
116 [ + + ]: 8358842 : if (stuffer->alloced) {
117 [ - + ]: 4068925 : POSIX_GUARD(s2n_free(&stuffer->blob));
118 : 4068925 : }
119 : 8358842 : *stuffer = (struct s2n_stuffer){ 0 };
120 : 8358842 : return S2N_SUCCESS;
121 : 8358842 : }
122 : :
123 : : int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer)
124 : 10 : {
125 [ - + ][ + - ]: 10 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
126 [ + - ]: 10 : if (stuffer->alloced) {
127 [ - + ]: 10 : POSIX_GUARD(s2n_free_without_wipe(&stuffer->blob));
128 : 10 : }
129 : 10 : *stuffer = (struct s2n_stuffer){ 0 };
130 : 10 : return S2N_SUCCESS;
131 : 10 : }
132 : :
133 : : int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size)
134 : 13850222 : {
135 [ - + ][ + - ]: 13850222 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
136 [ - + ][ # # ]: 13850222 : POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
137 [ - + ][ # # ]: 13850222 : POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
138 : :
139 [ + + ]: 13850222 : if (size == stuffer->blob.size) {
140 : 6919207 : return S2N_SUCCESS;
141 : 6919207 : }
142 : :
143 [ + + ]: 6931015 : if (size == 0) {
144 : 3308702 : s2n_stuffer_wipe(stuffer);
145 : 3308702 : return s2n_free(&stuffer->blob);
146 : 3308702 : }
147 : :
148 [ + + ]: 3622313 : if (size < stuffer->blob.size) {
149 [ # # ][ - + ]: 75 : POSIX_CHECKED_MEMSET(stuffer->blob.data + size, S2N_WIPE_PATTERN, (stuffer->blob.size - size));
[ + - ]
150 [ - + ]: 75 : if (stuffer->read_cursor > size) {
151 : 0 : stuffer->read_cursor = size;
152 : 0 : }
153 [ - + ]: 75 : if (stuffer->write_cursor > size) {
154 : 0 : stuffer->write_cursor = size;
155 : 0 : }
156 [ - + ]: 75 : if (stuffer->high_water_mark > size) {
157 : 0 : stuffer->high_water_mark = size;
158 : 0 : }
159 : 75 : stuffer->blob.size = size;
160 [ - + ][ + - ]: 75 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
161 : 75 : return S2N_SUCCESS;
162 : 75 : }
163 : :
164 [ - + ]: 3622238 : POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
165 [ - + ][ + - ]: 3622238 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
166 : 3622238 : return S2N_SUCCESS;
167 : 3622238 : }
168 : :
169 : : int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size)
170 : 963379 : {
171 [ - + ][ + - ]: 963379 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
172 [ + + ]: 963379 : if (stuffer->blob.data == NULL) {
173 [ - + ][ # # ]: 15996 : POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
174 [ + + ][ + - ]: 15996 : POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
175 [ - + ]: 15995 : POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
176 : 15995 : }
177 [ - + ][ + - ]: 963378 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
178 : 963378 : return S2N_SUCCESS;
179 : 963378 : }
180 : :
181 : : /**
182 : : * Reset read and write progress.
183 : : *
184 : : * This sets the read and write cursors to zero.
185 : : */
186 : : int s2n_stuffer_rewrite(struct s2n_stuffer *stuffer)
187 : 4525066 : {
188 [ - + ][ + - ]: 4525066 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
189 : 4525066 : stuffer->write_cursor = 0;
190 : 4525066 : stuffer->read_cursor = 0;
191 [ - + ][ + - ]: 4525066 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
192 : 4525066 : return S2N_SUCCESS;
193 : 4525066 : }
194 : :
195 : : int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size)
196 : 542311 : {
197 [ - + ][ + - ]: 542311 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
198 [ + + ][ + - ]: 542311 : POSIX_ENSURE(stuffer->read_cursor >= size, S2N_ERR_STUFFER_OUT_OF_DATA);
199 : 542306 : stuffer->read_cursor -= size;
200 [ - + ][ + - ]: 542306 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
201 : 542306 : return S2N_SUCCESS;
202 : 542306 : }
203 : :
204 : : /**
205 : : * Reset read progress.
206 : : *
207 : : * This sets the read cursor to zero.
208 : : */
209 : : int s2n_stuffer_reread(struct s2n_stuffer *stuffer)
210 : 8663784 : {
211 [ - + ][ + - ]: 8663784 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
212 : 8663784 : stuffer->read_cursor = 0;
213 : 8663784 : return S2N_SUCCESS;
214 : 8663784 : }
215 : :
216 : : /**
217 : : * wipe the last `size` bytes of previously written data
218 : : */
219 : : int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t size)
220 : 510245 : {
221 [ - + ][ + - ]: 510245 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
222 [ + + ]: 510245 : uint32_t wipe_size = S2N_MIN(size, stuffer->write_cursor);
223 : :
224 : 510245 : stuffer->write_cursor -= wipe_size;
225 [ + + ]: 510245 : stuffer->read_cursor = S2N_MIN(stuffer->read_cursor, stuffer->write_cursor);
226 [ - + ][ # # ]: 510245 : POSIX_CHECKED_MEMSET(stuffer->blob.data + stuffer->write_cursor, S2N_WIPE_PATTERN, wipe_size);
[ + + ]
227 : :
228 [ - + ][ + - ]: 510245 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
229 : 510245 : return S2N_SUCCESS;
230 : 510245 : }
231 : :
232 : : bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer)
233 : 249165 : {
234 [ + - ][ + + ]: 249165 : return stuffer && (stuffer->read_cursor == stuffer->write_cursor) && !stuffer->tainted;
[ + + ]
235 : 249165 : }
236 : :
237 : : int s2n_stuffer_wipe(struct s2n_stuffer *stuffer)
238 : 41497314 : {
239 [ - + ][ + - ]: 41497314 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
240 [ + + ]: 41497314 : if (!s2n_stuffer_is_wiped(stuffer)) {
241 [ # # ][ - + ]: 10743866 : POSIX_CHECKED_MEMSET(stuffer->blob.data, S2N_WIPE_PATTERN, stuffer->high_water_mark);
[ + - ]
242 : 10743866 : }
243 : :
244 : 41497314 : stuffer->tainted = 0;
245 : 41497314 : stuffer->write_cursor = 0;
246 : 41497314 : stuffer->read_cursor = 0;
247 : 41497314 : stuffer->high_water_mark = 0;
248 [ - + ][ + - ]: 41497314 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
249 : 41497314 : return S2N_SUCCESS;
250 : 41497314 : }
251 : :
252 : : int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n)
253 : 36763707 : {
254 [ - + ][ + + ]: 36763707 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
255 [ + - ][ + + ]: 36763707 : POSIX_ENSURE(s2n_stuffer_data_available(stuffer) >= n, S2N_ERR_STUFFER_OUT_OF_DATA);
256 : :
257 : 36747064 : stuffer->read_cursor += n;
258 : 36747064 : return S2N_SUCCESS;
259 : 36763707 : }
260 : :
261 : : void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len)
262 : 4840523 : {
263 [ + + ]: 4840523 : PTR_GUARD_POSIX(s2n_stuffer_skip_read(stuffer, data_len));
264 : :
265 : 4840520 : stuffer->tainted = 1;
266 : :
267 [ + - ]: 4840520 : return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - data_len) : NULL;
268 : 4840523 : }
269 : :
270 : : int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
271 : 146734 : {
272 [ # # ][ - + ]: 146734 : POSIX_ENSURE_REF(out);
273 : :
274 : 146734 : return s2n_stuffer_read_bytes(stuffer, out->data, out->size);
275 : 146734 : }
276 : :
277 : : int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
278 : 181903 : {
279 [ - + ]: 181903 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, out->size));
280 : :
281 [ + - ]: 181903 : void *ptr = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - out->size) : NULL;
282 [ # # ][ - + ]: 181903 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, out->size), S2N_ERR_NULL);
[ + - ]
283 : :
284 [ - + ][ # # ]: 181903 : POSIX_CHECKED_MEMCPY(out->data, ptr, out->size);
[ + - ]
285 [ # # ][ - + ]: 181903 : POSIX_CHECKED_MEMSET(ptr, 0, out->size);
[ + - ]
286 : :
287 : 181903 : return S2N_SUCCESS;
288 : 181903 : }
289 : :
290 : : int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
291 : 23503129 : {
292 [ + - ][ + + ]: 23503129 : POSIX_ENSURE_REF(data);
293 [ + + ][ + + ]: 23503127 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
294 [ + + ]: 23503126 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
295 [ - + ][ # # ]: 23486494 : POSIX_ENSURE_REF(stuffer->blob.data);
296 : 23486494 : void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
297 : :
298 [ - + ][ # # ]: 23486494 : POSIX_CHECKED_MEMCPY(data, ptr, size);
[ + + ]
299 : :
300 : 23486494 : return S2N_SUCCESS;
301 : 23486494 : }
302 : :
303 : : int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
304 : 8021 : {
305 [ - + ]: 8021 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
306 [ - + ][ # # ]: 8021 : POSIX_ENSURE_REF(stuffer->blob.data);
307 : 8021 : void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
308 : :
309 [ - + ][ # # ]: 8021 : POSIX_CHECKED_MEMCPY(data, ptr, size);
[ + - ]
310 [ - + ][ # # ]: 8021 : POSIX_CHECKED_MEMSET(ptr, 0, size);
[ + - ]
311 : :
312 : 8021 : return S2N_SUCCESS;
313 : 8021 : }
314 : :
315 : : int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n)
316 : 61105495 : {
317 [ - + ][ + + ]: 61105495 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
318 [ + + ]: 61105495 : POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, n));
319 : 61088016 : stuffer->write_cursor += n;
320 [ + + ]: 61088016 : stuffer->high_water_mark = S2N_MAX(stuffer->write_cursor, stuffer->high_water_mark);
321 [ - + ][ + + ]: 61088016 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
322 : 61088016 : return S2N_SUCCESS;
323 : 61088016 : }
324 : :
325 : : void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len)
326 : 7278942 : {
327 [ + + ]: 7278942 : PTR_GUARD_POSIX(s2n_stuffer_skip_write(stuffer, data_len));
328 : :
329 : 7278941 : stuffer->tainted = 1;
330 : :
331 [ + - ]: 7278941 : return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - data_len) : NULL;
332 : 7278942 : }
333 : :
334 : : int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in)
335 : 577759 : {
336 [ + + ][ + + ]: 577759 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
337 [ - + ][ + - ]: 577757 : POSIX_PRECONDITION(s2n_blob_validate(in));
338 : 577757 : return s2n_stuffer_write_bytes(stuffer, in->data, in->size);
339 : 577757 : }
340 : :
341 : : int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *data, const uint32_t size)
342 : 25711872 : {
343 [ + + ]: 25711872 : if (size == 0) {
344 : 129192 : return S2N_SUCCESS;
345 : 129192 : }
346 : :
347 [ # # ][ - + ]: 25582680 : POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_SAFETY);
[ + - ]
348 [ - + ][ + - ]: 25582680 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
349 [ + + ]: 25582680 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, size));
350 : :
351 : 25565207 : void *ptr = stuffer->blob.data + stuffer->write_cursor - size;
352 [ # # ][ - + ]: 25565207 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
[ + - ]
353 : :
354 [ + + ]: 25565207 : if (ptr == data) {
355 [ - + ][ + - ]: 8757 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
356 : 8757 : return S2N_SUCCESS;
357 : 8757 : }
358 : :
359 [ - + ][ # # ]: 25556450 : POSIX_CHECKED_MEMCPY(ptr, data, size);
[ + - ]
360 : :
361 [ - + ][ + - ]: 25556450 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
362 : 25556450 : return S2N_SUCCESS;
363 : 25556450 : }
364 : :
365 : : int s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count, uint32_t offs,
366 : : uint32_t size)
367 : 3608675 : {
368 [ - + ][ + - ]: 3608675 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
369 [ - + ][ # # ]: 3608675 : POSIX_ENSURE_REF(iov);
370 : 3608675 : void *ptr = s2n_stuffer_raw_write(stuffer, size);
371 [ # # ][ + + ]: 3608675 : POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
[ + - ]
372 : :
373 : 3608675 : size_t size_left = size, to_skip = offs;
374 [ + + ]: 3640130 : for (size_t i = 0; i < iov_count; i++) {
375 [ + + ]: 3640037 : if (to_skip >= iov[i].iov_len) {
376 : 31371 : to_skip -= iov[i].iov_len;
377 : 31371 : continue;
378 : 31371 : }
379 : 3608666 : size_t iov_len_op = iov[i].iov_len - to_skip;
380 [ - + ][ # # ]: 3608666 : POSIX_ENSURE_LTE(iov_len_op, UINT32_MAX);
381 : 3608666 : uint32_t iov_len = (uint32_t) iov_len_op;
382 [ + + ]: 3608666 : uint32_t iov_size_to_take = S2N_MIN(size_left, iov_len);
383 [ - + ][ # # ]: 3608666 : POSIX_ENSURE_REF(iov[i].iov_base);
384 [ - + ][ # # ]: 3608666 : POSIX_ENSURE_LT(to_skip, iov[i].iov_len);
385 [ - + ][ # # ]: 3608666 : POSIX_CHECKED_MEMCPY(ptr, ((uint8_t *) (iov[i].iov_base)) + to_skip, iov_size_to_take);
[ + - ]
386 : 3608666 : size_left -= iov_size_to_take;
387 [ + + ]: 3608666 : if (size_left == 0) {
388 : 3608582 : break;
389 : 3608582 : }
390 : 84 : ptr = (void *) ((uint8_t *) ptr + iov_size_to_take);
391 : 84 : to_skip = 0;
392 : 84 : }
393 : :
394 : 3608675 : return S2N_SUCCESS;
395 : 3608675 : }
396 : :
397 : : static int s2n_stuffer_copy_impl(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
398 : 7458849 : {
399 [ - + ]: 7458849 : POSIX_GUARD(s2n_stuffer_skip_read(from, len));
400 [ - + ]: 7458849 : POSIX_GUARD(s2n_stuffer_skip_write(to, len));
401 : :
402 [ + - ]: 7458849 : uint8_t *from_ptr = (from->blob.data) ? (from->blob.data + from->read_cursor - len) : NULL;
403 [ + - ]: 7458849 : uint8_t *to_ptr = (to->blob.data) ? (to->blob.data + to->write_cursor - len) : NULL;
404 : :
405 [ # # ][ - + ]: 7458849 : POSIX_CHECKED_MEMCPY(to_ptr, from_ptr, len);
[ + + ]
406 : :
407 : 7458849 : return S2N_SUCCESS;
408 : 7458849 : }
409 : :
410 : : int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n)
411 : 62158577 : {
412 [ - + ][ + + ]: 62158577 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
413 [ + + ]: 62158577 : if (s2n_stuffer_space_remaining(stuffer) < n) {
414 [ + + ][ + - ]: 3509072 : POSIX_ENSURE(stuffer->growable, S2N_ERR_STUFFER_IS_FULL);
415 : : /* Always grow a stuffer by at least 1k */
416 [ + + ]: 3491592 : const uint32_t growth = S2N_MAX(n - s2n_stuffer_space_remaining(stuffer), S2N_MIN_STUFFER_GROWTH_IN_BYTES);
417 : 3491592 : uint32_t new_size = 0;
418 [ - + ]: 3491592 : POSIX_GUARD(s2n_add_overflow(stuffer->blob.size, growth, &new_size));
419 [ - + ]: 3491592 : POSIX_GUARD(s2n_stuffer_resize(stuffer, new_size));
420 : 3491592 : }
421 [ - + ][ + + ]: 62141097 : POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
422 : 62141097 : return S2N_SUCCESS;
423 : 62141097 : }
424 : :
425 : : /* Copies "len" bytes from "from" to "to".
426 : : * If the copy cannot succeed (i.e. there are either not enough bytes available, or there is not enough space to write them
427 : : * restore the old value of the stuffer */
428 : : int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
429 : 7458849 : {
430 : 7458849 : const uint32_t orig_read_cursor = from->read_cursor;
431 : 7458849 : const uint32_t orig_write_cursor = to->write_cursor;
432 : :
433 [ - + ]: 7458849 : if (s2n_stuffer_copy_impl(from, to, len) < 0) {
434 : 0 : from->read_cursor = orig_read_cursor;
435 : 0 : to->write_cursor = orig_write_cursor;
436 : 0 : S2N_ERROR_PRESERVE_ERRNO();
437 : 0 : }
438 : :
439 : 7458849 : return S2N_SUCCESS;
440 : 7458849 : }
441 : :
442 : : int s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out)
443 : 23 : {
444 [ - + ][ + - ]: 23 : POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
445 [ - + ][ # # ]: 23 : POSIX_ENSURE_REF(out);
446 [ - + ]: 23 : POSIX_GUARD(s2n_realloc(out, s2n_stuffer_data_available(stuffer)));
447 : :
448 [ + - ]: 23 : if (s2n_stuffer_data_available(stuffer) > 0) {
449 [ - + ][ # # ]: 23 : POSIX_CHECKED_MEMCPY(out->data, stuffer->blob.data + stuffer->read_cursor, s2n_stuffer_data_available(stuffer));
[ + - ]
450 : 23 : }
451 : :
452 [ - + ][ + - ]: 23 : POSIX_POSTCONDITION(s2n_blob_validate(out));
453 : 23 : return S2N_SUCCESS;
454 : 23 : }
455 : :
456 : : int s2n_stuffer_shift(struct s2n_stuffer *stuffer)
457 : 572 : {
458 [ + - ][ + + ]: 572 : POSIX_ENSURE_REF(stuffer);
459 : 571 : struct s2n_stuffer copy = *stuffer;
460 [ - + ]: 571 : POSIX_GUARD(s2n_stuffer_rewrite(©));
461 : :
462 : 571 : uint8_t *data = stuffer->blob.data;
463 : : /* Adding 0 to a NULL value is undefined behavior */
464 [ + + ]: 571 : if (stuffer->read_cursor != 0) {
465 : 569 : data += stuffer->read_cursor;
466 : 569 : }
467 : :
468 : 571 : uint32_t data_size = s2n_stuffer_data_available(stuffer);
469 [ - + ]: 571 : POSIX_GUARD(s2n_stuffer_write_bytes(©, data, data_size));
470 : 571 : *stuffer = copy;
471 : 571 : return S2N_SUCCESS;
472 : 571 : }
|