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: 2025-11-15 08:28:27 Functions: 32 32 100.0 %
Branches: 248 456 54.4 %

           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                 :  590728794 : {
      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 [ +  + ][ +  - ]:  590728794 :     RESULT_ENSURE_REF(stuffer);
      32         [ +  + ]:  590728784 :     RESULT_GUARD(s2n_blob_validate(&stuffer->blob));
      33 [ #  # ][ -  + ]:  590728783 :     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 [ #  # ][ -  + ]:  590728783 :     RESULT_DEBUG_ENSURE(stuffer->high_water_mark <= stuffer->blob.size, S2N_ERR_SAFETY);
      37 [ +  - ][ +  + ]:  590728783 :     RESULT_DEBUG_ENSURE(stuffer->write_cursor <= stuffer->high_water_mark, S2N_ERR_SAFETY);
      38 [ +  - ][ +  + ]:  590728781 :     RESULT_DEBUG_ENSURE(stuffer->read_cursor <= stuffer->write_cursor, S2N_ERR_SAFETY);
      39                 :  590728780 :     return S2N_RESULT_OK;
      40                 :  590728781 : }
      41                 :            : 
      42                 :            : S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation)
      43                 :     377001 : {
      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 [ -  + ][ #  # ]:     377001 :     RESULT_ENSURE_REF(reservation);
      50                 :     377001 :     const struct s2n_stuffer_reservation reserve_obj = *reservation;
      51         [ +  + ]:     377001 :     RESULT_GUARD(s2n_stuffer_validate(reserve_obj.stuffer));
      52                 :     377000 :     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 [ -  + ][ #  # ]:     377000 :     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 [ +  + ][ +  - ]:     377000 :     RESULT_ENSURE_LTE(reserve_obj.write_cursor + reserve_obj.length, stuffer_obj.write_cursor);
      58 [ #  # ][ -  + ]:     376997 :     RESULT_ENSURE_GTE(reserve_obj.write_cursor, stuffer_obj.read_cursor);
      59                 :            : 
      60                 :     376997 :     return S2N_RESULT_OK;
      61                 :     376997 : }
      62                 :            : 
      63                 :            : /**
      64                 :            :  * Initialize a stuffer to reference some data `in`.
      65                 :            :  * 
      66                 :            :  * `stuffer` will not own the data, and the caller is responsible for ensuring that
      67                 :            :  * the data pointed to by `in` outlives `stuffer`.
      68                 :            :  */
      69                 :            : int s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in)
      70                 :   20569103 : {
      71 [ +  - ][ +  + ]:   20569103 :     POSIX_ENSURE_MUT(stuffer);
      72 [ +  + ][ +  + ]:   20569102 :     POSIX_PRECONDITION(s2n_blob_validate(in));
      73                 :   20569100 :     stuffer->blob = *in;
      74                 :   20569100 :     stuffer->read_cursor = 0;
      75                 :   20569100 :     stuffer->write_cursor = 0;
      76                 :   20569100 :     stuffer->high_water_mark = 0;
      77                 :   20569100 :     stuffer->alloced = 0;
      78                 :   20569100 :     stuffer->growable = 0;
      79                 :   20569100 :     stuffer->tainted = 0;
      80 [ -  + ][ +  + ]:   20569100 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
      81                 :   20569100 :     return S2N_SUCCESS;
      82                 :   20569100 : }
      83                 :            : 
      84                 :            : int s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in)
      85                 :     120395 : {
      86 [ -  + ][ #  # ]:     120395 :     POSIX_ENSURE_REF(in);
      87         [ -  + ]:     120395 :     POSIX_GUARD(s2n_stuffer_init(stuffer, in));
      88         [ -  + ]:     120395 :     POSIX_GUARD(s2n_stuffer_skip_write(stuffer, in->size));
      89                 :     120395 :     return S2N_SUCCESS;
      90                 :     120395 : }
      91                 :            : 
      92                 :            : int s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
      93                 :    7372688 : {
      94 [ -  + ][ #  # ]:    7372688 :     POSIX_ENSURE_REF(stuffer);
      95                 :    7372688 :     *stuffer = (struct s2n_stuffer){ 0 };
      96         [ -  + ]:    7372688 :     POSIX_GUARD(s2n_alloc(&stuffer->blob, size));
      97         [ -  + ]:    7372688 :     POSIX_GUARD(s2n_stuffer_init(stuffer, &stuffer->blob));
      98                 :            : 
      99                 :    7372688 :     stuffer->alloced = 1;
     100                 :            : 
     101 [ -  + ][ +  - ]:    7372688 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     102                 :    7372688 :     return S2N_SUCCESS;
     103                 :    7372688 : }
     104                 :            : 
     105                 :            : int s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size)
     106                 :    7348374 : {
     107         [ -  + ]:    7348374 :     POSIX_GUARD(s2n_stuffer_alloc(stuffer, size));
     108                 :            : 
     109                 :    7348374 :     stuffer->growable = 1;
     110                 :            : 
     111 [ -  + ][ +  - ]:    7348374 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     112                 :    7348374 :     return S2N_SUCCESS;
     113                 :    7348374 : }
     114                 :            : 
     115                 :            : int s2n_stuffer_free(struct s2n_stuffer *stuffer)
     116                 :    8375100 : {
     117 [ -  + ][ +  - ]:    8375100 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     118         [ +  + ]:    8375100 :     if (stuffer->alloced) {
     119         [ -  + ]:    4065209 :         POSIX_GUARD(s2n_free(&stuffer->blob));
     120                 :    4065209 :     }
     121                 :    8375100 :     *stuffer = (struct s2n_stuffer){ 0 };
     122                 :    8375100 :     return S2N_SUCCESS;
     123                 :    8375100 : }
     124                 :            : 
     125                 :            : int s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer)
     126                 :         10 : {
     127 [ -  + ][ +  - ]:         10 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     128         [ +  - ]:         10 :     if (stuffer->alloced) {
     129         [ -  + ]:         10 :         POSIX_GUARD(s2n_free_without_wipe(&stuffer->blob));
     130                 :         10 :     }
     131                 :         10 :     *stuffer = (struct s2n_stuffer){ 0 };
     132                 :         10 :     return S2N_SUCCESS;
     133                 :         10 : }
     134                 :            : 
     135                 :            : int s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size)
     136                 :   13848202 : {
     137 [ -  + ][ +  - ]:   13848202 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     138 [ #  # ][ -  + ]:   13848202 :     POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
     139 [ -  + ][ #  # ]:   13848202 :     POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
     140                 :            : 
     141         [ +  + ]:   13848202 :     if (size == stuffer->blob.size) {
     142                 :    6916834 :         return S2N_SUCCESS;
     143                 :    6916834 :     }
     144                 :            : 
     145         [ +  + ]:    6931368 :     if (size == 0) {
     146                 :    3310914 :         s2n_stuffer_wipe(stuffer);
     147                 :    3310914 :         return s2n_free(&stuffer->blob);
     148                 :    3310914 :     }
     149                 :            : 
     150         [ +  + ]:    3620454 :     if (size < stuffer->blob.size) {
     151 [ -  + ][ #  # ]:         75 :         POSIX_CHECKED_MEMSET(stuffer->blob.data + size, S2N_WIPE_PATTERN, (stuffer->blob.size - size));
                 [ +  - ]
     152         [ -  + ]:         75 :         if (stuffer->read_cursor > size) {
     153                 :          0 :             stuffer->read_cursor = size;
     154                 :          0 :         }
     155         [ -  + ]:         75 :         if (stuffer->write_cursor > size) {
     156                 :          0 :             stuffer->write_cursor = size;
     157                 :          0 :         }
     158         [ -  + ]:         75 :         if (stuffer->high_water_mark > size) {
     159                 :          0 :             stuffer->high_water_mark = size;
     160                 :          0 :         }
     161                 :         75 :         stuffer->blob.size = size;
     162 [ -  + ][ +  - ]:         75 :         POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     163                 :         75 :         return S2N_SUCCESS;
     164                 :         75 :     }
     165                 :            : 
     166         [ -  + ]:    3620379 :     POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
     167 [ -  + ][ +  - ]:    3620379 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     168                 :    3620379 :     return S2N_SUCCESS;
     169                 :    3620379 : }
     170                 :            : 
     171                 :            : int s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size)
     172                 :     863112 : {
     173 [ -  + ][ +  - ]:     863112 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     174         [ +  + ]:     863112 :     if (stuffer->blob.data == NULL) {
     175 [ -  + ][ #  # ]:      18182 :         POSIX_ENSURE(!stuffer->tainted, S2N_ERR_RESIZE_TAINTED_STUFFER);
     176 [ +  - ][ +  + ]:      18182 :         POSIX_ENSURE(stuffer->growable, S2N_ERR_RESIZE_STATIC_STUFFER);
     177         [ -  + ]:      18181 :         POSIX_GUARD(s2n_realloc(&stuffer->blob, size));
     178                 :      18181 :     }
     179 [ -  + ][ +  - ]:     863111 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     180                 :     863111 :     return S2N_SUCCESS;
     181                 :     863111 : }
     182                 :            : 
     183                 :            : /**
     184                 :            :  * Reset read and write progress.
     185                 :            :  * 
     186                 :            :  * This sets the read and write cursors to zero.
     187                 :            :  */
     188                 :            : int s2n_stuffer_rewrite(struct s2n_stuffer *stuffer)
     189                 :    4503785 : {
     190 [ -  + ][ +  - ]:    4503785 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     191                 :    4503785 :     stuffer->write_cursor = 0;
     192                 :    4503785 :     stuffer->read_cursor = 0;
     193 [ -  + ][ +  - ]:    4503785 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     194                 :    4503785 :     return S2N_SUCCESS;
     195                 :    4503785 : }
     196                 :            : 
     197                 :            : int s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size)
     198                 :     547082 : {
     199 [ -  + ][ +  - ]:     547082 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     200 [ +  + ][ +  - ]:     547082 :     POSIX_ENSURE(stuffer->read_cursor >= size, S2N_ERR_STUFFER_OUT_OF_DATA);
     201                 :     547077 :     stuffer->read_cursor -= size;
     202 [ -  + ][ +  - ]:     547077 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     203                 :     547077 :     return S2N_SUCCESS;
     204                 :     547077 : }
     205                 :            : 
     206                 :            : /**
     207                 :            :  * Reset read progress.
     208                 :            :  * 
     209                 :            :  * This sets the read cursor to zero.
     210                 :            :  */
     211                 :            : int s2n_stuffer_reread(struct s2n_stuffer *stuffer)
     212                 :    8992511 : {
     213 [ -  + ][ +  - ]:    8992511 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     214                 :    8992511 :     stuffer->read_cursor = 0;
     215                 :    8992511 :     return S2N_SUCCESS;
     216                 :    8992511 : }
     217                 :            : 
     218                 :            : int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t size)
     219                 :     517676 : {
     220 [ -  + ][ +  - ]:     517676 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     221                 :     517676 :     uint32_t wipe_size = MIN(size, stuffer->write_cursor);
     222                 :            : 
     223                 :     517676 :     stuffer->write_cursor -= wipe_size;
     224                 :     517676 :     stuffer->read_cursor = MIN(stuffer->read_cursor, stuffer->write_cursor);
     225 [ -  + ][ #  # ]:     517676 :     POSIX_CHECKED_MEMSET(stuffer->blob.data + stuffer->write_cursor, S2N_WIPE_PATTERN, wipe_size);
                 [ +  + ]
     226                 :            : 
     227 [ -  + ][ +  - ]:     517676 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     228                 :     517676 :     return S2N_SUCCESS;
     229                 :     517676 : }
     230                 :            : 
     231                 :            : bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer)
     232                 :     269510 : {
     233 [ +  - ][ +  + ]:     269510 :     return stuffer && (stuffer->read_cursor == stuffer->write_cursor) && !stuffer->tainted;
                 [ +  + ]
     234                 :     269510 : }
     235                 :            : 
     236                 :            : int s2n_stuffer_wipe(struct s2n_stuffer *stuffer)
     237                 :   41507388 : {
     238 [ -  + ][ +  - ]:   41507388 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     239         [ +  + ]:   41507388 :     if (!s2n_stuffer_is_wiped(stuffer)) {
     240 [ #  # ][ -  + ]:   10759713 :         POSIX_CHECKED_MEMSET(stuffer->blob.data, S2N_WIPE_PATTERN, stuffer->high_water_mark);
                 [ +  - ]
     241                 :   10759713 :     }
     242                 :            : 
     243                 :   41507388 :     stuffer->tainted = 0;
     244                 :   41507388 :     stuffer->write_cursor = 0;
     245                 :   41507388 :     stuffer->read_cursor = 0;
     246                 :   41507388 :     stuffer->high_water_mark = 0;
     247 [ -  + ][ +  - ]:   41507388 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     248                 :   41507388 :     return S2N_SUCCESS;
     249                 :   41507388 : }
     250                 :            : 
     251                 :            : int s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n)
     252                 :   36893564 : {
     253 [ -  + ][ +  - ]:   36893564 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     254 [ +  + ][ +  - ]:   36893564 :     POSIX_ENSURE(s2n_stuffer_data_available(stuffer) >= n, S2N_ERR_STUFFER_OUT_OF_DATA);
     255                 :            : 
     256                 :   36876895 :     stuffer->read_cursor += n;
     257                 :   36876895 :     return S2N_SUCCESS;
     258                 :   36893564 : }
     259                 :            : 
     260                 :            : void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len)
     261                 :    5073041 : {
     262         [ +  + ]:    5073041 :     PTR_GUARD_POSIX(s2n_stuffer_skip_read(stuffer, data_len));
     263                 :            : 
     264                 :    5073038 :     stuffer->tainted = 1;
     265                 :            : 
     266         [ +  - ]:    5073038 :     return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - data_len) : NULL;
     267                 :    5073041 : }
     268                 :            : 
     269                 :            : int s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
     270                 :     146342 : {
     271 [ -  + ][ #  # ]:     146342 :     POSIX_ENSURE_REF(out);
     272                 :            : 
     273                 :     146342 :     return s2n_stuffer_read_bytes(stuffer, out->data, out->size);
     274                 :     146342 : }
     275                 :            : 
     276                 :            : int s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out)
     277                 :     193852 : {
     278         [ -  + ]:     193852 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, out->size));
     279                 :            : 
     280         [ +  - ]:     193852 :     void *ptr = (stuffer->blob.data) ? (stuffer->blob.data + stuffer->read_cursor - out->size) : NULL;
     281 [ #  # ][ -  + ]:     193852 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, out->size), S2N_ERR_NULL);
                 [ +  - ]
     282                 :            : 
     283 [ -  + ][ #  # ]:     193852 :     POSIX_CHECKED_MEMCPY(out->data, ptr, out->size);
                 [ +  - ]
     284 [ -  + ][ #  # ]:     193852 :     POSIX_CHECKED_MEMSET(ptr, 0, out->size);
                 [ +  - ]
     285                 :            : 
     286                 :     193852 :     return S2N_SUCCESS;
     287                 :     193852 : }
     288                 :            : 
     289                 :            : int s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
     290                 :   23504201 : {
     291 [ +  - ][ +  + ]:   23504201 :     POSIX_ENSURE_REF(data);
     292 [ +  + ][ +  + ]:   23504199 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     293         [ +  + ]:   23504198 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
     294 [ -  + ][ #  # ]:   23487540 :     POSIX_ENSURE_REF(stuffer->blob.data);
     295                 :   23487540 :     void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
     296                 :            : 
     297 [ -  + ][ #  # ]:   23487540 :     POSIX_CHECKED_MEMCPY(data, ptr, size);
                 [ +  + ]
     298                 :            : 
     299                 :   23487540 :     return S2N_SUCCESS;
     300                 :   23487540 : }
     301                 :            : 
     302                 :            : int s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size)
     303                 :       7797 : {
     304         [ -  + ]:       7797 :     POSIX_GUARD(s2n_stuffer_skip_read(stuffer, size));
     305 [ -  + ][ #  # ]:       7797 :     POSIX_ENSURE_REF(stuffer->blob.data);
     306                 :       7797 :     void *ptr = stuffer->blob.data + stuffer->read_cursor - size;
     307                 :            : 
     308 [ -  + ][ #  # ]:       7797 :     POSIX_CHECKED_MEMCPY(data, ptr, size);
                 [ +  - ]
     309 [ -  + ][ #  # ]:       7797 :     POSIX_CHECKED_MEMSET(ptr, 0, size);
                 [ +  - ]
     310                 :            : 
     311                 :       7797 :     return S2N_SUCCESS;
     312                 :       7797 : }
     313                 :            : 
     314                 :            : int s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n)
     315                 :   69245424 : {
     316 [ -  + ][ +  + ]:   69245424 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     317         [ +  + ]:   69245424 :     POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, n));
     318                 :   69227948 :     stuffer->write_cursor += n;
     319                 :   69227948 :     stuffer->high_water_mark = MAX(stuffer->write_cursor, stuffer->high_water_mark);
     320 [ -  + ][ +  + ]:   69227948 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     321                 :   69227948 :     return S2N_SUCCESS;
     322                 :   69227948 : }
     323                 :            : 
     324                 :            : void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len)
     325                 :    7271993 : {
     326         [ +  + ]:    7271993 :     PTR_GUARD_POSIX(s2n_stuffer_skip_write(stuffer, data_len));
     327                 :            : 
     328                 :    7271992 :     stuffer->tainted = 1;
     329                 :            : 
     330         [ +  - ]:    7271992 :     return (stuffer->blob.data) ? (stuffer->blob.data + stuffer->write_cursor - data_len) : NULL;
     331                 :    7271993 : }
     332                 :            : 
     333                 :            : int s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in)
     334                 :     559049 : {
     335 [ +  + ][ +  + ]:     559049 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     336 [ -  + ][ +  - ]:     559047 :     POSIX_PRECONDITION(s2n_blob_validate(in));
     337                 :     559047 :     return s2n_stuffer_write_bytes(stuffer, in->data, in->size);
     338                 :     559047 : }
     339                 :            : 
     340                 :            : int s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *data, const uint32_t size)
     341                 :   37869717 : {
     342         [ +  + ]:   37869717 :     if (size == 0) {
     343                 :     124397 :         return S2N_SUCCESS;
     344                 :     124397 :     }
     345                 :            : 
     346 [ #  # ][ +  + ]:   37745320 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_SAFETY);
                 [ +  - ]
     347 [ -  + ][ +  + ]:   37745320 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     348         [ +  + ]:   37745320 :     POSIX_GUARD(s2n_stuffer_skip_write(stuffer, size));
     349                 :            : 
     350                 :   37727850 :     void *ptr = stuffer->blob.data + stuffer->write_cursor - size;
     351 [ #  # ][ +  + ]:   37727850 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
                 [ +  - ]
     352                 :            : 
     353         [ +  + ]:   37727850 :     if (ptr == data) {
     354 [ -  + ][ +  - ]:       8232 :         POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     355                 :       8232 :         return S2N_SUCCESS;
     356                 :       8232 :     }
     357                 :            : 
     358 [ -  + ][ #  # ]:   37719618 :     POSIX_CHECKED_MEMCPY(ptr, data, size);
                 [ +  + ]
     359                 :            : 
     360 [ -  + ][ +  + ]:   37719618 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     361                 :   37719618 :     return S2N_SUCCESS;
     362                 :   37719618 : }
     363                 :            : 
     364                 :            : int s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count, uint32_t offs,
     365                 :            :         uint32_t size)
     366                 :    3605903 : {
     367 [ -  + ][ +  - ]:    3605903 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     368 [ -  + ][ #  # ]:    3605903 :     POSIX_ENSURE_REF(iov);
     369                 :    3605903 :     void *ptr = s2n_stuffer_raw_write(stuffer, size);
     370 [ #  # ][ +  + ]:    3605903 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(ptr, size), S2N_ERR_NULL);
                 [ +  - ]
     371                 :            : 
     372                 :    3605903 :     size_t size_left = size, to_skip = offs;
     373         [ +  + ]:    3637358 :     for (size_t i = 0; i < iov_count; i++) {
     374         [ +  + ]:    3637265 :         if (to_skip >= iov[i].iov_len) {
     375                 :      31371 :             to_skip -= iov[i].iov_len;
     376                 :      31371 :             continue;
     377                 :      31371 :         }
     378                 :    3605894 :         size_t iov_len_op = iov[i].iov_len - to_skip;
     379 [ -  + ][ #  # ]:    3605894 :         POSIX_ENSURE_LTE(iov_len_op, UINT32_MAX);
     380                 :    3605894 :         uint32_t iov_len = (uint32_t) iov_len_op;
     381                 :    3605894 :         uint32_t iov_size_to_take = MIN(size_left, iov_len);
     382 [ -  + ][ #  # ]:    3605894 :         POSIX_ENSURE_REF(iov[i].iov_base);
     383 [ -  + ][ #  # ]:    3605894 :         POSIX_ENSURE_LT(to_skip, iov[i].iov_len);
     384 [ -  + ][ #  # ]:    3605894 :         POSIX_CHECKED_MEMCPY(ptr, ((uint8_t *) (iov[i].iov_base)) + to_skip, iov_size_to_take);
                 [ +  - ]
     385                 :    3605894 :         size_left -= iov_size_to_take;
     386         [ +  + ]:    3605894 :         if (size_left == 0) {
     387                 :    3605810 :             break;
     388                 :    3605810 :         }
     389                 :         84 :         ptr = (void *) ((uint8_t *) ptr + iov_size_to_take);
     390                 :         84 :         to_skip = 0;
     391                 :         84 :     }
     392                 :            : 
     393                 :    3605903 :     return S2N_SUCCESS;
     394                 :    3605903 : }
     395                 :            : 
     396                 :            : static int s2n_stuffer_copy_impl(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
     397                 :    7345210 : {
     398         [ -  + ]:    7345210 :     POSIX_GUARD(s2n_stuffer_skip_read(from, len));
     399         [ -  + ]:    7345210 :     POSIX_GUARD(s2n_stuffer_skip_write(to, len));
     400                 :            : 
     401         [ +  - ]:    7345210 :     uint8_t *from_ptr = (from->blob.data) ? (from->blob.data + from->read_cursor - len) : NULL;
     402         [ +  - ]:    7345210 :     uint8_t *to_ptr = (to->blob.data) ? (to->blob.data + to->write_cursor - len) : NULL;
     403                 :            : 
     404 [ #  # ][ -  + ]:    7345210 :     POSIX_CHECKED_MEMCPY(to_ptr, from_ptr, len);
                 [ +  + ]
     405                 :            : 
     406                 :    7345210 :     return S2N_SUCCESS;
     407                 :    7345210 : }
     408                 :            : 
     409                 :            : int s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n)
     410                 :   70198118 : {
     411 [ -  + ][ +  + ]:   70198118 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     412         [ +  + ]:   70198118 :     if (s2n_stuffer_space_remaining(stuffer) < n) {
     413 [ +  + ][ +  - ]:    3507743 :         POSIX_ENSURE(stuffer->growable, S2N_ERR_STUFFER_IS_FULL);
     414                 :            :         /* Always grow a stuffer by at least 1k */
     415                 :    3490266 :         const uint32_t growth = MAX(n - s2n_stuffer_space_remaining(stuffer), S2N_MIN_STUFFER_GROWTH_IN_BYTES);
     416                 :    3490266 :         uint32_t new_size = 0;
     417         [ -  + ]:    3490266 :         POSIX_GUARD(s2n_add_overflow(stuffer->blob.size, growth, &new_size));
     418         [ -  + ]:    3490266 :         POSIX_GUARD(s2n_stuffer_resize(stuffer, new_size));
     419                 :    3490266 :     }
     420 [ -  + ][ +  + ]:   70180641 :     POSIX_POSTCONDITION(s2n_stuffer_validate(stuffer));
     421                 :   70180641 :     return S2N_SUCCESS;
     422                 :   70180641 : }
     423                 :            : 
     424                 :            : /* Copies "len" bytes from "from" to "to".
     425                 :            :  * If the copy cannot succeed (i.e. there are either not enough bytes available, or there is not enough space to write them
     426                 :            :  * restore the old value of the stuffer */
     427                 :            : int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, const uint32_t len)
     428                 :    7345210 : {
     429                 :    7345210 :     const uint32_t orig_read_cursor = from->read_cursor;
     430                 :    7345210 :     const uint32_t orig_write_cursor = to->write_cursor;
     431                 :            : 
     432         [ -  + ]:    7345210 :     if (s2n_stuffer_copy_impl(from, to, len) < 0) {
     433                 :          0 :         from->read_cursor = orig_read_cursor;
     434                 :          0 :         to->write_cursor = orig_write_cursor;
     435                 :          0 :         S2N_ERROR_PRESERVE_ERRNO();
     436                 :          0 :     }
     437                 :            : 
     438                 :    7345210 :     return S2N_SUCCESS;
     439                 :    7345210 : }
     440                 :            : 
     441                 :            : int s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out)
     442                 :         23 : {
     443 [ -  + ][ +  - ]:         23 :     POSIX_PRECONDITION(s2n_stuffer_validate(stuffer));
     444 [ #  # ][ -  + ]:         23 :     POSIX_ENSURE_REF(out);
     445         [ -  + ]:         23 :     POSIX_GUARD(s2n_realloc(out, s2n_stuffer_data_available(stuffer)));
     446                 :            : 
     447         [ +  - ]:         23 :     if (s2n_stuffer_data_available(stuffer) > 0) {
     448 [ -  + ][ #  # ]:         23 :         POSIX_CHECKED_MEMCPY(out->data, stuffer->blob.data + stuffer->read_cursor, s2n_stuffer_data_available(stuffer));
                 [ +  - ]
     449                 :         23 :     }
     450                 :            : 
     451 [ -  + ][ +  - ]:         23 :     POSIX_POSTCONDITION(s2n_blob_validate(out));
     452                 :         23 :     return S2N_SUCCESS;
     453                 :         23 : }
     454                 :            : 
     455                 :            : int s2n_stuffer_shift(struct s2n_stuffer *stuffer)
     456                 :        508 : {
     457 [ +  - ][ +  + ]:        508 :     POSIX_ENSURE_REF(stuffer);
     458                 :        507 :     struct s2n_stuffer copy = *stuffer;
     459         [ -  + ]:        507 :     POSIX_GUARD(s2n_stuffer_rewrite(&copy));
     460                 :            : 
     461                 :        507 :     uint8_t *data = stuffer->blob.data;
     462                 :            :     /* Adding 0 to a NULL value is undefined behavior */
     463         [ +  + ]:        507 :     if (stuffer->read_cursor != 0) {
     464                 :        505 :         data += stuffer->read_cursor;
     465                 :        505 :     }
     466                 :            : 
     467                 :        507 :     uint32_t data_size = s2n_stuffer_data_available(stuffer);
     468         [ -  + ]:        507 :     POSIX_GUARD(s2n_stuffer_write_bytes(&copy, data, data_size));
     469                 :        507 :     *stuffer = copy;
     470                 :        507 :     return S2N_SUCCESS;
     471                 :        507 : }

Generated by: LCOV version 1.14