LCOV - code coverage report
Current view: top level - utils - s2n_rfc5952.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 67 67 100.0 %
Date: 2025-08-15 07:28:39 Functions: 1 1 100.0 %
Branches: 35 42 83.3 %

           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 "utils/s2n_rfc5952.h"
      17                 :            : 
      18                 :            : #include <stdio.h>
      19                 :            : #include <sys/socket.h>
      20                 :            : #include <sys/types.h>
      21                 :            : 
      22                 :            : #include "error/s2n_errno.h"
      23                 :            : #include "utils/s2n_safety.h"
      24                 :            : 
      25                 :            : static uint8_t dec[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
      26                 :            : static uint8_t hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
      27                 :            : 
      28                 :            : S2N_RESULT s2n_inet_ntop(int af, const void *addr, struct s2n_blob *dst)
      29                 :         12 : {
      30                 :         12 :     const uint8_t *bytes = addr;
      31                 :         12 :     uint8_t *cursor = dst->data;
      32                 :            : 
      33         [ +  + ]:         12 :     if (af == AF_INET) {
      34 [ #  # ][ -  + ]:          4 :         RESULT_ENSURE(dst->size >= sizeof("111.222.333.444"), S2N_ERR_SIZE_MISMATCH);
      35                 :            : 
      36         [ +  + ]:         20 :         for (int i = 0; i < 4; i++) {
      37         [ +  + ]:         16 :             if (bytes[i] / 100) {
      38                 :         11 :                 *cursor++ = dec[bytes[i] / 100];
      39                 :         11 :             }
      40         [ +  + ]:         16 :             if (bytes[i] >= 10) {
      41                 :         11 :                 *cursor++ = dec[(bytes[i] % 100) / 10];
      42                 :         11 :             }
      43                 :         16 :             *cursor++ = dec[(bytes[i] % 10)];
      44                 :         16 :             *cursor++ = '.';
      45                 :         16 :         }
      46                 :            : 
      47                 :          4 :         *--cursor = '\0';
      48                 :            : 
      49                 :          4 :         return S2N_RESULT_OK;
      50                 :          4 :     }
      51                 :            : 
      52         [ +  + ]:          8 :     if (af == AF_INET6) {
      53 [ #  # ][ -  + ]:          7 :         RESULT_ENSURE(dst->size >= sizeof("1111:2222:3333:4444:5555:6666:7777:8888"), S2N_ERR_SIZE_MISMATCH);
      54                 :            : 
      55                 :            :         /* See Section 4 of RFC5952 for the rules we are going to follow here
      56                 :            :          *
      57                 :            :          * Here's the general algorithm:
      58                 :            :          *
      59                 :            :          *   1/ Treat the bytes as 8 16-bit fields
      60                 :            :          *   2/ Find the longest run of 16-bit fields.
      61                 :            :          *   3/ or if there are two or more equal length longest runs, go with the left-most run
      62                 :            :          *   4/ Make that run ::
      63                 :            :          *   5/ Print the remaining 16-bit fields in lowercase hex, no leading zeroes
      64                 :            :          */
      65                 :            : 
      66                 :          7 :         uint16_t octets[8] = { 0 };
      67                 :            : 
      68                 :          7 :         int longest_run_start = 0;
      69                 :          7 :         int longest_run_length = 0;
      70                 :          7 :         int current_run_length = 0;
      71                 :            : 
      72                 :            :         /* 2001:db8::1:0:0:1 */
      73                 :            : 
      74                 :            :         /* Find the longest run of zeroes */
      75         [ +  + ]:         63 :         for (int i = 0; i < 8; i++) {
      76                 :         56 :             octets[i] = (bytes[i * 2] << 8) + bytes[(i * 2) + 1];
      77                 :            : 
      78         [ +  + ]:         56 :             if (octets[i]) {
      79                 :         20 :                 current_run_length = 0;
      80                 :         36 :             } else {
      81                 :         36 :                 current_run_length++;
      82                 :         36 :             }
      83                 :            : 
      84         [ +  + ]:         56 :             if (current_run_length > longest_run_length) {
      85                 :         34 :                 longest_run_length = current_run_length;
      86                 :         34 :                 longest_run_start = (i - current_run_length) + 1;
      87                 :         34 :             }
      88                 :         56 :         }
      89                 :            : 
      90         [ +  + ]:         36 :         for (int i = 0; i < 8; i++) {
      91 [ +  + ][ +  + ]:         29 :             if (i == longest_run_start && longest_run_length > 1) {
      92         [ +  + ]:          6 :                 if (i == 0) {
      93                 :          3 :                     *cursor++ = ':';
      94                 :          3 :                 }
      95                 :            : 
      96         [ +  + ]:          6 :                 if (longest_run_length == 8) {
      97                 :          1 :                     *cursor++ = ':';
      98                 :          1 :                 }
      99                 :            : 
     100                 :          6 :                 i += longest_run_length - 1;
     101                 :            : 
     102                 :         23 :             } else {
     103                 :         23 :                 uint8_t nibbles[4] = { (octets[i] & 0xF000) >> 12,
     104                 :         23 :                     (octets[i] & 0x0F00) >> 8,
     105                 :         23 :                     (octets[i] & 0x00F0) >> 4,
     106                 :         23 :                     (octets[i] & 0x000F) };
     107                 :            : 
     108                 :            :                 /* Skip up to three leading zeroes */
     109                 :         23 :                 int j = 0;
     110         [ +  + ]:         72 :                 for (j = 0; j < 3; j++) {
     111         [ +  + ]:         57 :                     if (nibbles[j]) {
     112                 :          8 :                         break;
     113                 :          8 :                     }
     114                 :         57 :                 }
     115                 :            : 
     116         [ +  + ]:         66 :                 for (; j < 4; j++) {
     117                 :         43 :                     *cursor++ = hex[nibbles[j]];
     118                 :         43 :                 }
     119                 :         23 :             }
     120                 :            : 
     121                 :         29 :             *cursor++ = ':';
     122                 :         29 :         }
     123                 :            : 
     124                 :          7 :         *--cursor = '\0';
     125                 :            : 
     126                 :          7 :         return S2N_RESULT_OK;
     127                 :          7 :     }
     128                 :            : 
     129         [ +  - ]:          1 :     RESULT_BAIL(S2N_ERR_INVALID_ARGUMENT);
     130                 :          1 : }

Generated by: LCOV version 1.14