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

Generated by: LCOV version 1.14