s2n_ensure.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. #pragma once
  16. #define s2n_likely(x) __builtin_expect(!!(x), 1)
  17. #define s2n_unlikely(x) __builtin_expect(!!(x), 0)
  18. /**
  19. * s2n_ensure provides low-level safety check functionality
  20. *
  21. * This should only consumed directly by s2n_safety.
  22. *
  23. * Note: This module can be replaced by static analyzer implementation
  24. * to insert additional safety checks.
  25. */
  26. /**
  27. * Ensures `cond` is true, otherwise `action` will be performed
  28. */
  29. #define __S2N_ENSURE(cond, action) \
  30. do { \
  31. if (!(cond)) { \
  32. action; \
  33. } \
  34. } while (0)
  35. #define __S2N_ENSURE_LIKELY(cond, action) \
  36. do { \
  37. if (s2n_unlikely(!(cond))) { \
  38. action; \
  39. } \
  40. } while (0)
  41. #ifdef NDEBUG
  42. #define __S2N_ENSURE_DEBUG(cond, action) \
  43. do { \
  44. } while (0)
  45. #else
  46. #define __S2N_ENSURE_DEBUG(cond, action) __S2N_ENSURE_LIKELY((cond), action)
  47. #endif
  48. #define __S2N_ENSURE_PRECONDITION(result) (s2n_likely(s2n_result_is_ok(result)) ? S2N_RESULT_OK : S2N_RESULT_ERROR)
  49. #ifdef NDEBUG
  50. #define __S2N_ENSURE_POSTCONDITION(result) (S2N_RESULT_OK)
  51. #else
  52. #define __S2N_ENSURE_POSTCONDITION(result) (s2n_likely(s2n_result_is_ok(result)) ? S2N_RESULT_OK : S2N_RESULT_ERROR)
  53. #endif
  54. #define __S2N_ENSURE_SAFE_MEMCPY(d, s, n, guard) \
  55. do { \
  56. __typeof(n) __tmp_n = (n); \
  57. if (s2n_likely(__tmp_n)) { \
  58. void *r = s2n_ensure_memcpy_trace((d), (s), (__tmp_n)); \
  59. guard(r); \
  60. } \
  61. } while (0)
  62. #define __S2N_ENSURE_SAFE_MEMSET(d, c, n, guard) \
  63. do { \
  64. __typeof(n) __tmp_n = (n); \
  65. if (s2n_likely(__tmp_n)) { \
  66. __typeof(d) __tmp_d = (d); \
  67. guard(__tmp_d); \
  68. memset(__tmp_d, (c), __tmp_n); \
  69. } \
  70. } while (0)
  71. #if defined(S2N_DIAGNOSTICS_PUSH_SUPPORTED) && defined(S2N_DIAGNOSTICS_POP_SUPPORTED)
  72. #define __S2N_ENSURE_CHECKED_RETURN(v) \
  73. do { \
  74. _Pragma("GCC diagnostic push") \
  75. _Pragma("GCC diagnostic error \"-Wconversion\"") return v; \
  76. _Pragma("GCC diagnostic pop") \
  77. } while (0)
  78. #else
  79. #define __S2N_ENSURE_CHECKED_RETURN(v) return v
  80. #endif
  81. /**
  82. * `restrict` is a part of the c99 standard and will work with any C compiler. If you're trying to
  83. * compile with a C++ compiler `restrict` is invalid. However some C++ compilers support the behavior
  84. * of `restrict` using the `__restrict__` keyword. Therefore if the compiler supports `__restrict__`
  85. * use it.
  86. *
  87. * This is helpful for the benchmarks in tests/benchmark which use Google's Benchmark library and
  88. * are all written in C++.
  89. *
  90. * https://gcc.gnu.org/onlinedocs/gcc/Restricted-Pointers.html
  91. *
  92. */
  93. #if defined(S2N___RESTRICT__SUPPORTED)
  94. void *s2n_ensure_memcpy_trace(void *__restrict__ to, const void *__restrict__ from, size_t size);
  95. #else
  96. void *s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size);
  97. #endif
  98. /**
  99. * These macros should not be used in validate functions.
  100. * All validate functions are also used in assumptions for CBMC proofs,
  101. * which should not contain __CPROVER_*_ok primitives. The use of these primitives
  102. * in assumptions may lead to spurious results.
  103. * When the code is being verified using CBMC, these properties are formally verified;
  104. * When the code is built in debug mode, they are checked as much as possible using assertions.
  105. * When the code is built in production mode, non-fatal properties are not checked.
  106. * Violations of these properties are undefined behaviour.
  107. */
  108. #ifdef CBMC
  109. #define S2N_MEM_IS_READABLE_CHECK(base, len) (((len) == 0) || __CPROVER_r_ok((base), (len)))
  110. #define S2N_MEM_IS_WRITABLE_CHECK(base, len) (((len) == 0) || __CPROVER_w_ok((base), (len)))
  111. #else
  112. /* the C runtime does not give a way to check these properties,
  113. * but we can at least check for nullness. */
  114. #define S2N_MEM_IS_READABLE_CHECK(base, len) (((len) == 0) || (base) != NULL)
  115. #define S2N_MEM_IS_WRITABLE_CHECK(base, len) (((len) == 0) || (base) != NULL)
  116. #endif /* CBMC */
  117. /**
  118. * These macros can safely be used in validate functions.
  119. */
  120. #define S2N_MEM_IS_READABLE(base, len) (((len) == 0) || (base) != NULL)
  121. #define S2N_MEM_IS_WRITABLE(base, len) (((len) == 0) || (base) != NULL)
  122. #define S2N_OBJECT_PTR_IS_READABLE(ptr) ((ptr) != NULL)
  123. #define S2N_OBJECT_PTR_IS_WRITABLE(ptr) ((ptr) != NULL)
  124. #define S2N_IMPLIES(a, b) (!(a) || (b))
  125. /**
  126. * If and only if (iff) is a biconditional logical connective between statements a and b.
  127. * Equivalent to (S2N_IMPLIES(a, b) && S2N_IMPLIES(b, a)).
  128. */
  129. #define S2N_IFF(a, b) (!!(a) == !!(b))
  130. /**
  131. * These macros are used to specify code contracts in CBMC proofs.
  132. * Define function contracts.
  133. * When the code is being verified using CBMC, these contracts are formally verified;
  134. * When the code is built in production mode, contracts are not checked.
  135. * Violations of the function contracts are undefined behaviour.
  136. */
  137. #ifdef CBMC
  138. #define CONTRACT_ASSIGNS(...) __CPROVER_assigns(__VA_ARGS__)
  139. #define CONTRACT_ASSIGNS_ERR(...) CONTRACT_ASSIGNS(__VA_ARGS__, _s2n_debug_info, s2n_errno)
  140. #define CONTRACT_REQUIRES(...) __CPROVER_requires(__VA_ARGS__)
  141. #define CONTRACT_ENSURES(...) __CPROVER_ensures(__VA_ARGS__)
  142. #define CONTRACT_INVARIANT(...) __CPROVER_loop_invariant(__VA_ARGS__)
  143. #define CONTRACT_RETURN_VALUE (__CPROVER_return_value)
  144. #else
  145. #define CONTRACT_ASSIGNS(...)
  146. #define CONTRACT_ASSIGNS_ERR(...)
  147. #define CONTRACT_REQUIRES(...)
  148. #define CONTRACT_ENSURES(...)
  149. #define CONTRACT_INVARIANT(...)
  150. #define CONTRACT_RETURN_VALUE
  151. #endif