LCOV - code coverage report
Current view: top level - aws-c-common/source - error.c (source / functions) Hit Total Coverage
Test: all_fuzz.info Lines: 6 163 3.7 %
Date: 2021-04-23 16:28:21 Functions: 1 14 7.1 %

          Line data    Source code
       1             : /**
       2             :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3             :  * SPDX-License-Identifier: Apache-2.0.
       4             :  */
       5             : 
       6             : #include <aws/common/error.h>
       7             : 
       8             : #include <aws/common/common.h>
       9             : 
      10             : #include <errno.h>
      11             : #include <stdio.h>
      12             : #include <stdlib.h>
      13             : 
      14             : static AWS_THREAD_LOCAL int tl_last_error = 0;
      15             : 
      16             : static aws_error_handler_fn *s_global_handler = NULL;
      17             : static void *s_global_error_context = NULL;
      18             : 
      19             : static AWS_THREAD_LOCAL aws_error_handler_fn *tl_thread_handler = NULL;
      20             : AWS_THREAD_LOCAL void *tl_thread_handler_context = NULL;
      21             : 
      22             : /* Since slot size is 00000100 00000000, to divide, we need to shift right by 10
      23             :  * bits to find the slot, and to find the modulus, we use a binary and with
      24             :  * 00000011 11111111 to find the index in that slot.
      25             :  */
      26           0 : #define SLOT_MASK (AWS_ERROR_ENUM_STRIDE - 1)
      27             : 
      28             : static const int MAX_ERROR_CODE = AWS_ERROR_ENUM_STRIDE * AWS_PACKAGE_SLOTS;
      29             : 
      30             : static const struct aws_error_info_list *volatile ERROR_SLOTS[AWS_PACKAGE_SLOTS] = {0};
      31             : 
      32           0 : int aws_last_error(void) {
      33           0 :     return tl_last_error;
      34           0 : }
      35             : 
      36           0 : static const struct aws_error_info *get_error_by_code(int err) {
      37           0 :     if (err >= MAX_ERROR_CODE || err < 0) {
      38           0 :         return NULL;
      39           0 :     }
      40           0 : 
      41           0 :     uint32_t slot_index = (uint32_t)err >> AWS_ERROR_ENUM_STRIDE_BITS;
      42           0 :     uint32_t error_index = (uint32_t)err & SLOT_MASK;
      43           0 : 
      44           0 :     const struct aws_error_info_list *error_slot = ERROR_SLOTS[slot_index];
      45           0 : 
      46           0 :     if (!error_slot || error_index >= error_slot->count) {
      47           0 :         return NULL;
      48           0 :     }
      49           0 : 
      50           0 :     return &error_slot->error_list[error_index];
      51           0 : }
      52             : 
      53           0 : const char *aws_error_str(int err) {
      54           0 :     const struct aws_error_info *error_info = get_error_by_code(err);
      55           0 : 
      56           0 :     if (error_info) {
      57           0 :         return error_info->error_str;
      58           0 :     }
      59           0 : 
      60           0 :     return "Unknown Error Code";
      61           0 : }
      62             : 
      63           0 : const char *aws_error_name(int err) {
      64           0 :     const struct aws_error_info *error_info = get_error_by_code(err);
      65           0 : 
      66           0 :     if (error_info) {
      67           0 :         return error_info->literal_name;
      68           0 :     }
      69           0 : 
      70           0 :     return "Unknown Error Code";
      71           0 : }
      72             : 
      73           0 : const char *aws_error_lib_name(int err) {
      74           0 :     const struct aws_error_info *error_info = get_error_by_code(err);
      75           0 : 
      76           0 :     if (error_info) {
      77           0 :         return error_info->lib_name;
      78           0 :     }
      79           0 : 
      80           0 :     return "Unknown Error Code";
      81           0 : }
      82             : 
      83           0 : const char *aws_error_debug_str(int err) {
      84           0 :     const struct aws_error_info *error_info = get_error_by_code(err);
      85           0 : 
      86           0 :     if (error_info) {
      87           0 :         return error_info->formatted_name;
      88           0 :     }
      89           0 : 
      90           0 :     return "Unknown Error Code";
      91           0 : }
      92             : 
      93      534552 : void aws_raise_error_private(int err) {
      94      534552 :     tl_last_error = err;
      95      534552 : 
      96      534552 :     if (tl_thread_handler) {
      97           0 :         tl_thread_handler(tl_last_error, tl_thread_handler_context);
      98      534552 :     } else if (s_global_handler) {
      99           0 :         s_global_handler(tl_last_error, s_global_error_context);
     100           0 :     }
     101      534552 : }
     102             : 
     103           0 : void aws_reset_error(void) {
     104           0 :     tl_last_error = 0;
     105           0 : }
     106             : 
     107           0 : void aws_restore_error(int err) {
     108           0 :     tl_last_error = err;
     109           0 : }
     110             : 
     111           0 : aws_error_handler_fn *aws_set_global_error_handler_fn(aws_error_handler_fn *handler, void *ctx) {
     112           0 :     aws_error_handler_fn *old_handler = s_global_handler;
     113           0 :     s_global_handler = handler;
     114           0 :     s_global_error_context = ctx;
     115           0 : 
     116           0 :     return old_handler;
     117           0 : }
     118             : 
     119           0 : aws_error_handler_fn *aws_set_thread_local_error_handler_fn(aws_error_handler_fn *handler, void *ctx) {
     120           0 :     aws_error_handler_fn *old_handler = tl_thread_handler;
     121           0 :     tl_thread_handler = handler;
     122           0 :     tl_thread_handler_context = ctx;
     123           0 : 
     124           0 :     return old_handler;
     125           0 : }
     126             : 
     127           0 : void aws_register_error_info(const struct aws_error_info_list *error_info) {
     128           0 :     /*
     129           0 :      * We're not so worried about these asserts being removed in an NDEBUG build
     130           0 :      * - we'll either segfault immediately (for the first two) or for the count
     131           0 :      * assert, the registration will be ineffective.
     132           0 :      */
     133           0 :     AWS_FATAL_ASSERT(error_info);
     134           0 :     AWS_FATAL_ASSERT(error_info->error_list);
     135           0 :     AWS_FATAL_ASSERT(error_info->count);
     136           0 : 
     137           0 :     const int min_range = error_info->error_list[0].error_code;
     138           0 :     const int slot_index = min_range >> AWS_ERROR_ENUM_STRIDE_BITS;
     139           0 : 
     140           0 :     if (slot_index >= AWS_PACKAGE_SLOTS || slot_index < 0) {
     141           0 :         /* This is an NDEBUG build apparently. Kill the process rather than
     142           0 :          * corrupting heap. */
     143           0 :         fprintf(stderr, "Bad error slot index %d\n", slot_index);
     144           0 :         AWS_FATAL_ASSERT(false);
     145           0 :     }
     146           0 : 
     147           0 : #if DEBUG_BUILD
     148           0 :     /* Assert that error info entries are in the right order. */
     149           0 :     for (int i = 1; i < error_info->count; ++i) {
     150           0 :         const int expected_code = min_range + i;
     151           0 :         const struct aws_error_info *info = &error_info->error_list[i];
     152           0 :         if (info->error_code != expected_code) {
     153           0 :             if (info->error_code) {
     154           0 :                 fprintf(stderr, "Error %s is at wrong index of error info list.\n", info->literal_name);
     155           0 :             } else {
     156           0 :                 fprintf(stderr, "Error %d is missing from error info list.\n", expected_code);
     157           0 :             }
     158           0 :             AWS_FATAL_ASSERT(0);
     159           0 :         }
     160           0 :     }
     161           0 : #endif /* DEBUG_BUILD */
     162           0 : 
     163           0 :     ERROR_SLOTS[slot_index] = error_info;
     164           0 : }
     165             : 
     166           0 : void aws_unregister_error_info(const struct aws_error_info_list *error_info) {
     167           0 :     AWS_FATAL_ASSERT(error_info);
     168           0 :     AWS_FATAL_ASSERT(error_info->error_list);
     169           0 :     AWS_FATAL_ASSERT(error_info->count);
     170           0 : 
     171           0 :     const int min_range = error_info->error_list[0].error_code;
     172           0 :     const int slot_index = min_range >> AWS_ERROR_ENUM_STRIDE_BITS;
     173           0 : 
     174           0 :     if (slot_index >= AWS_PACKAGE_SLOTS || slot_index < 0) {
     175           0 :         /* This is an NDEBUG build apparently. Kill the process rather than
     176           0 :          * corrupting heap. */
     177           0 :         fprintf(stderr, "Bad error slot index %d\n", slot_index);
     178           0 :         AWS_FATAL_ASSERT(0);
     179           0 :     }
     180           0 : 
     181           0 :     ERROR_SLOTS[slot_index] = NULL;
     182           0 : }
     183             : 
     184           0 : int aws_translate_and_raise_io_error(int error_no) {
     185           0 :     switch (error_no) {
     186           0 :         case EINVAL:
     187           0 :             return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
     188           0 :         case ESPIPE:
     189           0 :             return aws_raise_error(AWS_ERROR_STREAM_UNSEEKABLE);
     190           0 :         case EPERM:
     191           0 :         case EACCES:
     192           0 :             return aws_raise_error(AWS_ERROR_NO_PERMISSION);
     193           0 :         case EISDIR:
     194           0 :         case ENAMETOOLONG:
     195           0 :         case ENOENT:
     196           0 :             return aws_raise_error(AWS_ERROR_FILE_INVALID_PATH);
     197           0 :         case ENFILE:
     198           0 :             return aws_raise_error(AWS_ERROR_MAX_FDS_EXCEEDED);
     199           0 :         case ENOMEM:
     200           0 :             return aws_raise_error(AWS_ERROR_OOM);
     201           0 :         case ENOSPC:
     202           0 :             return aws_raise_error(AWS_ERROR_NO_SPACE);
     203           0 :         default:
     204           0 :             return aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
     205           0 :     }
     206           0 : }

Generated by: LCOV version 1.13