s2n_result.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. * The goal of s2n_result is to provide a strongly-typed error
  17. * signal value, which provides the compiler with enough information
  18. * to catch bugs.
  19. *
  20. * Historically, s2n has used int to signal errors. This has caused a few issues:
  21. *
  22. * ## GUARD in a function returning integer types
  23. *
  24. * There is no compiler error if `GUARD(nested_call());` is used in a function
  25. * that is meant to return integer type - not a error signal.
  26. *
  27. * ```c
  28. * uint8_t s2n_answer_to_the_ultimate_question() {
  29. * POSIX_GUARD(s2n_sleep_for_years(7500000));
  30. * return 42;
  31. * }
  32. * ```
  33. *
  34. * In this function we intended to return a `uint8_t` but used a
  35. * `GUARD` which will return -1 if the call fails. This can lead to
  36. * very subtle bugs.
  37. *
  38. * ## `GUARD`ing a function returning any integer type
  39. *
  40. * There is no compiler error if `GUARD(nested_call());` is used
  41. * on a function that doesn't actually return an error signal
  42. *
  43. * ```c
  44. * int s2n_deep_thought() {
  45. * POSIX_GUARD(s2n_answer_to_the_ultimate_question());
  46. * return 0;
  47. * }
  48. * ```
  49. *
  50. * In this function we intended guard against a failure of
  51. * `s2n_answer_to_the_ultimate_question` but that function doesn't
  52. * actually return an error signal. Again, this can lead to sublte
  53. * bugs.
  54. *
  55. * ## Ignored error signals
  56. *
  57. * Without the `warn_unused_result` function attribute, the compiler
  58. * provides no warning when forgetting to `GUARD` a function. Missing
  59. * a `GUARD` can lead to subtle bugs.
  60. *
  61. * ```c
  62. * int s2n_answer_to_the_ultimate_question() {
  63. * s2n_sleep_for_years(7500000); // <- THIS SHOULD BE GUARDED!!!
  64. * return 42;
  65. * }
  66. * ```
  67. *
  68. * # Solution
  69. *
  70. * s2n_result provides a newtype declaration, which is popular in
  71. * languages like [Haskell](https://wiki.haskell.org/Newtype) and
  72. * [Rust](https://doc.rust-lang.org/rust-by-example/generics/new_types.html).
  73. *
  74. * Functions that return S2N_RESULT are automatically marked with the
  75. * `warn_unused_result` attribute, which ensures they are GUARDed.
  76. */
  77. #include "utils/s2n_result.h"
  78. #include <stdbool.h>
  79. #include "api/s2n.h"
  80. /* returns true when the result is S2N_RESULT_OK */
  81. inline bool s2n_result_is_ok(s2n_result result)
  82. {
  83. return result.__error_signal == S2N_SUCCESS;
  84. }
  85. /* returns true when the result is S2N_RESULT_ERROR */
  86. inline bool s2n_result_is_error(s2n_result result)
  87. {
  88. return result.__error_signal == S2N_FAILURE;
  89. }
  90. /* ignores the returned result of a function */
  91. inline void s2n_result_ignore(s2n_result result)
  92. {
  93. /* noop */
  94. }