LCOV - code coverage report
Current view: top level - stuffer - s2n_stuffer.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 297 307 96.7 %
Date: 2026-08-22 07:27:53 Functions: 32 32 100.0 %
Branches: 261 466 56.0 %

           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                 :  533968166 : {
      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 [ +  + ][ +  - ]:  533968166 :     RESULT_ENSURE_REF(stuffer);
      30         [ +  + ]:  533968156 :     RESULT_GUARD(s2n_blob_validate(&stuffer->blob));
      31 [ #  # ][ -  + ]:  533968155 :     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 [ #  # ][ -  + ]:  533968155 :     RESULT_DEBUG_ENSURE(stuffer->high_water_mark <= stuffer->blob.size, S2N_ERR_SAFETY);
      35 [ +  - ][ +  + ]:  533968155 :     RESULT_DEBUG_ENSURE(stuffer->write_cursor <= stuffer->high_water_mark, S2N_ERR_SAFETY);
      36 [ +  - ][ +  + ]:  533968153 :     RESULT_DEBUG_ENSURE(stuffer->read_cursor <= stuffer->write_cursor, S2N_ERR_SAFETY);
      37                 :  533968152 :     return S2N_RESULT_OK;
      38                 :  533968153 : }
      39                 :            : 
      40                 :            : S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation)
      41                 :     389286 : {
      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 [ -  + ][ #  # ]:     389286 :     RESULT_ENSURE_REF(reservation);
      48                 :     389286 :     const struct s2n_stuffer_reservation reserve_obj = *reservation;
      49         [ +  + ]:     389286 :     RESULT_GUARD(s2n_stuffer_validate(reserve_obj.stuffer));
      50                 :     389285 :     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 [ -  + ][ #  # ]:     389285 :     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 [ +  + ][ +  - ]:     389285 :     RESULT_ENSURE_LTE(reserve_obj.write_cursor + reserve_obj.length, stuffer_obj.write_cursor);
      56 [ #  # ][ -  + ]:     389282 :     RESULT_ENSURE_GTE(reserve_obj.write_cursor, stuffer_obj.read_cursor);
      57                 :            : 
      58                 :     389282 :     return S2N_RESULT_OK;
      59                 :     389282 : }
      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                 :   18829400 : {
      69 [ +  - ][ +  + ]:   18829400 :     POSIX_ENSURE_MUT(stuffer);
      70 [ +  + ][ +  + ]:   18829399 :     POSIX_PRECONDITION(s2n_blob_validate(in));
      71                 :   18829397 :     stuffer->blob = *in;
      72                 :   18829397 :     stuffer->read_cursor = 0;
      73                 :   18829397 :     stuffer->write_cursor = 0;
      74                 :   18829397 :     stuffer->high_water_mark = 0;
      75                 :   18829397 :     stuffer->alloced = 0;
      76                 :   18829397 :     stuffer->growable = 0;
      77                 :   18829397 :     stuffer->tainted = 0;
      78 [ -  + ][ +  - ]:   18829397 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
      79                 :   18829397 :     return S2N_SUCCESS;
      80                 :   18829397 : }
      81                 :            : 
      82                 :            : int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in)
      83                 :     120665 : {
      84 [ -  + ][ #  # ]:     120665 :     POSIX_ENSURE_REF(in);
      85         [ -  + ]:     120665 :     POSIX_GUARD(s2n_stuffer_init(stuffer, in));
      86         [ -  + ]:     120665 :     POSIX_GUARD(s2n_stuffer_skip_write(stuffer, in->size));
      87                 :     120665 :     return S2N_SUCCESS;
      88                 :     120665 : }
      89                 :            : 
      90                 :            : int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
      91                 :    7376423 : {
      92 [ -  + ][ #  # ]:    7376423 :     POSIX_ENSURE_REF(stuffer);
      93                 :    7376423 :     *stuffer = (struct s2n_stuffer){ 0 };
      94         [ -  + ]:    7376423 :     POSIX_GUARD(s2n_alloc(&stuffer->blob, size));
      95         [ -  + ]:    7376423 :     POSIX_GUARD(s2n_stuffer_init(stuffer, &stuffer->blob));
      96                 :            : 
      97                 :    7376423 :     stuffer->alloced = 1;
      98                 :            : 
      99 [ -  + ][ +  - ]:    7376423 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     100                 :    7376423 :     return S2N_SUCCESS;
     101                 :    7376423 : }
     102                 :            : 
     103                 :            : int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
     104                 :    7351415 : {
     105         [ -  + ]:    7351415 :     POSIX_GUARD(s2n_stuffer_alloc(stuffer, size));
     106                 :            : 
     107                 :    7351415 :     stuffer->growable = 1;
     108                 :            : 
     109 [ -  + ][ +  - ]:    7351415 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     110                 :    7351415 :     return S2N_SUCCESS;
     111                 :    7351415 : }
     112                 :            : 
     113                 :            : int s2n_stuffer_free(struct s2n_stuffer *stuffer)
     114                 :    8357949 : {
     115 [ -  + ][ +  - ]:    8357949 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     116         [ +  + ]:    8357949 :     if (stuffer->alloced) {
     117         [ -  + ]:    4068505 :         POSIX_GUARD(s2n_free(&stuffer->blob));
     118                 :    4068505 :     }
     119                 :    8357949 :     *stuffer = (struct s2n_stuffer){ 0 };
     120                 :    8357949 :     return S2N_SUCCESS;
     121                 :    8357949 : }
     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                 :   13849886 : {
     135 [ -  + ][ +  - ]:   13849886 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     136 [ -  + ][ #  # ]:   13849886 :     POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
     137 [ -  + ][ #  # ]:   13849886 :     POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
     138                 :            : 
     139         [ +  + ]:   13849886 :     if (size == stuffer->blob.size) {
     140                 :    6919053 :         return S2N_SUCCESS;
     141                 :    6919053 :     }
     142                 :            : 
     143         [ +  + ]:    6930833 :     if (size == 0) {
     144                 :    3308674 :         s2n_stuffer_wipe(stuffer);
     145                 :    3308674 :         return s2n_free(&stuffer->blob);
     146                 :    3308674 :     }
     147                 :            : 
     148         [ +  + ]:    3622159 :     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         [ -  + ]:    3622084 :     POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
     165 [ -  + ][ +  - ]:    3622084 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     166                 :    3622084 :     return S2N_SUCCESS;
     167                 :    3622084 : }
     168                 :            : 
     169                 :            : int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size)
     170                 :     804193 : {
     171 [ -  + ][ +  - ]:     804193 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     172         [ +  + ]:     804193 :     if (stuffer->blob.data == NULL) {
     173 [ -  + ][ #  # ]:      15972 :         POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
     174 [ +  + ][ +  - ]:      15972 :         POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
     175         [ -  + ]:      15971 :         POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
     176                 :      15971 :     }
     177 [ -  + ][ +  - ]:     804192 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     178                 :     804192 :     return S2N_SUCCESS;
     179                 :     804192 : }
     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                 :    4490137 : {
     188 [ -  + ][ +  + ]:    4490137 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     189                 :    4490137 :     stuffer->write_cursor = 0;
     190                 :    4490137 :     stuffer->read_cursor = 0;
     191 [ -  + ][ +  + ]:    4490137 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     192                 :    4490137 :     return S2N_SUCCESS;
     193                 :    4490137 : }
     194                 :            : 
     195                 :            : int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size)
     196                 :     541815 : {
     197 [ -  + ][ +  - ]:     541815 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     198 [ +  + ][ +  - ]:     541815 :     POSIX_ENSURE(stuffer->read_cursor >= size, S2N_ERR_STUFFER_OUT_OF_DATA);
     199                 :     541810 :     stuffer->read_cursor -= size;
     200 [ -  + ][ +  - ]:     541810 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     201                 :     541810 :     return S2N_SUCCESS;
     202                 :     541810 : }
     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                 :    8504033 : {
     211 [ -  + ][ +  - ]:    8504033 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     212                 :    8504033 :     stuffer->read_cursor = 0;
     213                 :    8504033 :     return S2N_SUCCESS;
     214                 :    8504033 : }
     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                 :     510065 : {
     221 [ -  + ][ +  - ]:     510065 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     222         [ +  + ]:     510065 :     uint32_t wipe_size = S2N_MIN(size, stuffer->write_cursor);
     223                 :            : 
     224                 :     510065 :     stuffer->write_cursor -= wipe_size;
     225         [ +  + ]:     510065 :     stuffer->read_cursor = S2N_MIN(stuffer->read_cursor, stuffer->write_cursor);
     226 [ -  + ][ #  # ]:     510065 :     POSIX_CHECKED_MEMSET(stuffer->blob.data + stuffer->write_cursor, S2N_WIPE_PATTERN, wipe_size);
                 [ +  + ]
     227                 :            : 
     228 [ -  + ][ +  - ]:     510065 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     229                 :     510065 :     return S2N_SUCCESS;
     230                 :     510065 : }
     231                 :            : 
     232                 :            : bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer)
     233                 :     249042 : {
     234 [ +  - ][ +  + ]:     249042 :     return stuffer && (stuffer->read_cursor == stuffer->write_cursor) && !stuffer->tainted;
                 [ +  + ]
     235                 :     249042 : }
     236                 :            : 
     237                 :            : int s2n_stuffer_wipe(struct s2n_stuffer *stuffer)
     238                 :   41496242 : {
     239 [ -  + ][ +  + ]:   41496242 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     240         [ +  + ]:   41496242 :     if (!s2n_stuffer_is_wiped(stuffer)) {
     241 [ #  # ][ -  + ]:   10743251 :         POSIX_CHECKED_MEMSET(stuffer->blob.data, S2N_WIPE_PATTERN, stuffer->high_water_mark);
                 [ +  - ]
     242                 :   10743251 :     }
     243                 :            : 
     244                 :   41496242 :     stuffer->tainted = 0;
     245                 :   41496242 :     stuffer->write_cursor = 0;
     246                 :   41496242 :     stuffer->read_cursor = 0;
     247                 :   41496242 :     stuffer->high_water_mark = 0;
     248 [ -  + ][ +  + ]:   41496242 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     249                 :   41496242 :     return S2N_SUCCESS;
     250                 :   41496242 : }
     251                 :            : 
     252                 :            : int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n)
     253                 :   36595518 : {
     254 [ -  + ][ +  + ]:   36595518 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     255 [ +  - ][ +  + ]:   36595518 :     POSIX_ENSURE(s2n_stuffer_data_available(stuffer) >= n, S2N_ERR_STUFFER_OUT_OF_DATA);
     256                 :            : 
     257                 :   36578875 :     stuffer->read_cursor += n;
     258                 :   36578875 :     return S2N_SUCCESS;
     259                 :   36595518 : }
     260                 :            : 
     261                 :            : void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len)
     262                 :    4838903 : {
     263         [ +  + ]:    4838903 :     PTR_GUARD_POSIX(s2n_stuffer_skip_read(stuffer, data_len));
     264                 :            : 
     265                 :    4838900 :     stuffer->tainted = 1;
     266                 :            : 
     267         [ +  - ]:    4838900 :     return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - data_len) : NULL;
     268                 :    4838903 : }
     269                 :            : 
     270                 :            : int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
     271                 :     146676 : {
     272 [ #  # ][ -  + ]:     146676 :     POSIX_ENSURE_REF(out);
     273                 :            : 
     274                 :     146676 :     return s2n_stuffer_read_bytes(stuffer, out->data, out->size);
     275                 :     146676 : }
     276                 :            : 
     277                 :            : int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
     278                 :     181902 : {
     279         [ -  + ]:     181902 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, out->size));
     280                 :            : 
     281         [ +  - ]:     181902 :     void *ptr = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - out->size) : NULL;
     282 [ #  # ][ -  + ]:     181902 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, out->size), S2N_ERR_NULL);
                 [ +  - ]
     283                 :            : 
     284 [ -  + ][ #  # ]:     181902 :     POSIX_CHECKED_MEMCPY(out->data, ptr, out->size);
                 [ +  - ]
     285 [ #  # ][ -  + ]:     181902 :     POSIX_CHECKED_MEMSET(ptr, 0, out->size);
                 [ +  - ]
     286                 :            : 
     287                 :     181902 :     return S2N_SUCCESS;
     288                 :     181902 : }
     289                 :            : 
     290                 :            : int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
     291                 :   23497792 : {
     292 [ +  - ][ +  + ]:   23497792 :     POSIX_ENSURE_REF(data);
     293 [ +  + ][ +  + ]:   23497790 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     294         [ +  + ]:   23497789 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
     295 [ -  + ][ #  # ]:   23481157 :     POSIX_ENSURE_REF(stuffer->blob.data);
     296                 :   23481157 :     void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
     297                 :            : 
     298 [ -  + ][ #  # ]:   23481157 :     POSIX_CHECKED_MEMCPY(data, ptr, size);
                 [ +  + ]
     299                 :            : 
     300                 :   23481157 :     return S2N_SUCCESS;
     301                 :   23481157 : }
     302                 :            : 
     303                 :            : int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
     304                 :       8001 : {
     305         [ -  + ]:       8001 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
     306 [ -  + ][ #  # ]:       8001 :     POSIX_ENSURE_REF(stuffer->blob.data);
     307                 :       8001 :     void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
     308                 :            : 
     309 [ -  + ][ #  # ]:       8001 :     POSIX_CHECKED_MEMCPY(data, ptr, size);
                 [ +  - ]
     310 [ -  + ][ #  # ]:       8001 :     POSIX_CHECKED_MEMSET(ptr, 0, size);
                 [ +  - ]
     311                 :            : 
     312                 :       8001 :     return S2N_SUCCESS;
     313                 :       8001 : }
     314                 :            : 
     315                 :            : int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n)
     316                 :   60885838 : {
     317 [ -  + ][ +  + ]:   60885838 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     318         [ +  + ]:   60885838 :     POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, n));
     319                 :   60868363 :     stuffer->write_cursor += n;
     320         [ +  + ]:   60868363 :     stuffer->high_water_mark = S2N_MAX(stuffer->write_cursor, stuffer->high_water_mark);
     321 [ -  + ][ +  + ]:   60868363 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     322                 :   60868363 :     return S2N_SUCCESS;
     323                 :   60868363 : }
     324                 :            : 
     325                 :            : void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len)
     326                 :    7278688 : {
     327         [ +  + ]:    7278688 :     PTR_GUARD_POSIX(s2n_stuffer_skip_write(stuffer, data_len));
     328                 :            : 
     329                 :    7278687 :     stuffer->tainted = 1;
     330                 :            : 
     331         [ +  - ]:    7278687 :     return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - data_len) : NULL;
     332                 :    7278688 : }
     333                 :            : 
     334                 :            : int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in)
     335                 :     576392 : {
     336 [ +  + ][ +  + ]:     576392 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     337 [ -  + ][ +  - ]:     576390 :     POSIX_PRECONDITION(s2n_blob_validate(in));
     338                 :     576390 :     return s2n_stuffer_write_bytes(stuffer, in->data, in->size);
     339                 :     576390 : }
     340                 :            : 
     341                 :            : int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *data, const uint32_t size)
     342                 :   25657402 : {
     343         [ +  + ]:   25657402 :     if (size == 0) {
     344                 :     128981 :         return S2N_SUCCESS;
     345                 :     128981 :     }
     346                 :            : 
     347 [ #  # ][ -  + ]:   25528421 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_SAFETY);
                 [ +  - ]
     348 [ -  + ][ +  + ]:   25528421 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     349         [ +  + ]:   25528421 :     POSIX_GUARD(s2n_stuffer_skip_write(stuffer, size));
     350                 :            : 
     351                 :   25510952 :     void *ptr = stuffer->blob.data + stuffer->write_cursor - size;
     352 [ #  # ][ +  + ]:   25510952 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
                 [ +  - ]
     353                 :            : 
     354         [ +  + ]:   25510952 :     if (ptr == data) {
     355 [ -  + ][ +  - ]:       8726 :         POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     356                 :       8726 :         return S2N_SUCCESS;
     357                 :       8726 :     }
     358                 :            : 
     359 [ -  + ][ #  # ]:   25502226 :     POSIX_CHECKED_MEMCPY(ptr, data, size);
                 [ +  + ]
     360                 :            : 
     361 [ -  + ][ +  + ]:   25502226 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     362                 :   25502226 :     return S2N_SUCCESS;
     363                 :   25502226 : }
     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                 :    3608551 : {
     368 [ -  + ][ +  - ]:    3608551 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     369 [ -  + ][ #  # ]:    3608551 :     POSIX_ENSURE_REF(iov);
     370                 :    3608551 :     void *ptr = s2n_stuffer_raw_write(stuffer, size);
     371 [ #  # ][ +  + ]:    3608551 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
                 [ +  - ]
     372                 :            : 
     373                 :    3608551 :     size_t size_left = size, to_skip = offs;
     374         [ +  + ]:    3640006 :     for (size_t i = 0; i < iov_count; i++) {
     375         [ +  + ]:    3639913 :         if (to_skip >= iov[i].iov_len) {
     376                 :      31371 :             to_skip -= iov[i].iov_len;
     377                 :      31371 :             continue;
     378                 :      31371 :         }
     379                 :    3608542 :         size_t iov_len_op = iov[i].iov_len - to_skip;
     380 [ -  + ][ #  # ]:    3608542 :         POSIX_ENSURE_LTE(iov_len_op, UINT32_MAX);
     381                 :    3608542 :         uint32_t iov_len = (uint32_t) iov_len_op;
     382         [ +  + ]:    3608542 :         uint32_t iov_size_to_take = S2N_MIN(size_left, iov_len);
     383 [ -  + ][ #  # ]:    3608542 :         POSIX_ENSURE_REF(iov[i].iov_base);
     384 [ -  + ][ #  # ]:    3608542 :         POSIX_ENSURE_LT(to_skip, iov[i].iov_len);
     385 [ -  + ][ #  # ]:    3608542 :         POSIX_CHECKED_MEMCPY(ptr, ((uint8_t *) (iov[i].iov_base)) + to_skip, iov_size_to_take);
                 [ +  - ]
     386                 :    3608542 :         size_left -= iov_size_to_take;
     387         [ +  + ]:    3608542 :         if (size_left == 0) {
     388                 :    3608458 :             break;
     389                 :    3608458 :         }
     390                 :         84 :         ptr = (void *) ((uint8_t *) ptr + iov_size_to_take);
     391                 :         84 :         to_skip = 0;
     392                 :         84 :     }
     393                 :            : 
     394                 :    3608551 :     return S2N_SUCCESS;
     395                 :    3608551 : }
     396                 :            : 
     397                 :            : static int s2n_stuffer_copy_impl(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
     398                 :    7299568 : {
     399         [ -  + ]:    7299568 :     POSIX_GUARD(s2n_stuffer_skip_read(from, len));
     400         [ -  + ]:    7299568 :     POSIX_GUARD(s2n_stuffer_skip_write(to, len));
     401                 :            : 
     402         [ +  - ]:    7299568 :     uint8_t *from_ptr = (from->blob.data) ? (from->blob.data + from->read_cursor - len) : NULL;
     403         [ +  - ]:    7299568 :     uint8_t *to_ptr = (to->blob.data) ? (to->blob.data + to->write_cursor - len) : NULL;
     404                 :            : 
     405 [ #  # ][ -  + ]:    7299568 :     POSIX_CHECKED_MEMCPY(to_ptr, from_ptr, len);
                 [ +  + ]
     406                 :            : 
     407                 :    7299568 :     return S2N_SUCCESS;
     408                 :    7299568 : }
     409                 :            : 
     410                 :            : int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n)
     411                 :   61779722 : {
     412 [ -  + ][ +  + ]:   61779722 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     413         [ +  + ]:   61779722 :     if (s2n_stuffer_space_remaining(stuffer) < n) {
     414 [ +  + ][ +  - ]:    3508981 :         POSIX_ENSURE(stuffer->growable, S2N_ERR_STUFFER_IS_FULL);
     415                 :            :         /* Always grow a stuffer by at least 1k */
     416         [ +  + ]:    3491505 :         const uint32_t growth = S2N_MAX(n - s2n_stuffer_space_remaining(stuffer), S2N_MIN_STUFFER_GROWTH_IN_BYTES);
     417                 :    3491505 :         uint32_t new_size = 0;
     418         [ -  + ]:    3491505 :         POSIX_GUARD(s2n_add_overflow(stuffer->blob.size, growth, &new_size));
     419         [ -  + ]:    3491505 :         POSIX_GUARD(s2n_stuffer_resize(stuffer, new_size));
     420                 :    3491505 :     }
     421 [ -  + ][ +  + ]:   61762246 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     422                 :   61762246 :     return S2N_SUCCESS;
     423                 :   61762246 : }
     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                 :    7299568 : {
     430                 :    7299568 :     const uint32_t orig_read_cursor = from->read_cursor;
     431                 :    7299568 :     const uint32_t orig_write_cursor = to->write_cursor;
     432                 :            : 
     433         [ -  + ]:    7299568 :     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                 :    7299568 :     return S2N_SUCCESS;
     440                 :    7299568 : }
     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(&copy));
     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(&copy, data, data_size));
     470                 :        571 :     *stuffer = copy;
     471                 :        571 :     return S2N_SUCCESS;
     472                 :        571 : }

Generated by: LCOV version 1.14