safe_math_test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*
  2. * Copyright 2021-2022 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. /*
  12. * Uncomment this if the fallback non-builtin overflow checking is to
  13. * be tested.
  14. */
  15. /*#define OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING*/
  16. #include "internal/nelem.h"
  17. #include "internal/safe_math.h"
  18. #include "testutil.h"
  19. /* Create the safe math instances we're interested in */
  20. OSSL_SAFE_MATH_SIGNED(int, int)
  21. OSSL_SAFE_MATH_UNSIGNED(uint, unsigned int)
  22. OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
  23. static const struct {
  24. int a, b;
  25. int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
  26. int neg_a_err, neg_b_err, abs_a_err, abs_b_err;
  27. } test_ints[] = { /* + - * / % /r -a -b |a||b| */
  28. { 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  29. { -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  30. { 1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  31. { -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  32. { 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  33. { -3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  34. { 2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  35. { -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  36. { INT_MAX, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  37. { INT_MAX, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
  38. { INT_MAX, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
  39. { INT_MAX - 3 , 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
  40. { INT_MIN, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 },
  41. { 1, INT_MIN, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 },
  42. { INT_MIN, 2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
  43. { 2, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
  44. { INT_MIN, -1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0 },
  45. { INT_MAX, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
  46. { INT_MIN, INT_MAX, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
  47. { 3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
  48. };
  49. static int test_int_ops(int n)
  50. {
  51. int err, r, s;
  52. const int a = test_ints[n].a, b = test_ints[n].b;
  53. err = 0;
  54. r = safe_add_int(a, b, &err);
  55. if (!TEST_int_eq(err, test_ints[n].sum_err)
  56. || (!err && !TEST_int_eq(r, a + b)))
  57. goto err;
  58. err = 0;
  59. r = safe_sub_int(a, b, &err);
  60. if (!TEST_int_eq(err, test_ints[n].sub_err)
  61. || (!err && !TEST_int_eq(r, a - b)))
  62. goto err;
  63. err = 0;
  64. r = safe_mul_int(a, b, &err);
  65. if (!TEST_int_eq(err, test_ints[n].mul_err)
  66. || (!err && !TEST_int_eq(r, a * b)))
  67. goto err;
  68. err = 0;
  69. r = safe_div_int(a, b, &err);
  70. if (!TEST_int_eq(err, test_ints[n].div_err)
  71. || (!err && !TEST_int_eq(r, a / b)))
  72. goto err;
  73. err = 0;
  74. r = safe_mod_int(a, b, &err);
  75. if (!TEST_int_eq(err, test_ints[n].mod_err)
  76. || (!err && !TEST_int_eq(r, a % b)))
  77. goto err;
  78. err = 0;
  79. r = safe_div_round_up_int(a, b, &err);
  80. if (!TEST_int_eq(err, test_ints[n].div_round_up_err))
  81. goto err;
  82. s = safe_mod_int(a, b, &err);
  83. s = safe_add_int(safe_div_int(a, b, &err), s != 0, &err);
  84. if (!err && !TEST_int_eq(r, s))
  85. goto err;
  86. err = 0;
  87. r = safe_neg_int(a, &err);
  88. if (!TEST_int_eq(err, test_ints[n].neg_a_err)
  89. || (!err && !TEST_int_eq(r, -a)))
  90. goto err;
  91. err = 0;
  92. r = safe_neg_int(b, &err);
  93. if (!TEST_int_eq(err, test_ints[n].neg_b_err)
  94. || (!err && !TEST_int_eq(r, -b)))
  95. goto err;
  96. err = 0;
  97. r = safe_abs_int(a, &err);
  98. if (!TEST_int_eq(err, test_ints[n].abs_a_err)
  99. || (!err && !TEST_int_eq(r, a < 0 ? -a : a)))
  100. goto err;
  101. err = 0;
  102. r = safe_abs_int(b, &err);
  103. if (!TEST_int_eq(err, test_ints[n].abs_b_err)
  104. || (!err && !TEST_int_eq(r, b < 0 ? -b : b)))
  105. goto err;
  106. return 1;
  107. err:
  108. TEST_info("a = %d b = %d r = %d err = %d", a, b, r, err);
  109. return 0;
  110. }
  111. static const struct {
  112. unsigned int a, b;
  113. int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
  114. } test_uints[] = { /* + - * / % /r */
  115. { 3, 1, 0, 0, 0, 0, 0, 0 },
  116. { 1, 3, 0, 1, 0, 0, 0, 0 },
  117. { UINT_MAX, 1, 1, 0, 0, 0, 0, 0 },
  118. { UINT_MAX, 2, 1, 0, 1, 0, 0, 0 },
  119. { UINT_MAX, 16, 1, 0, 1, 0, 0, 0 },
  120. { UINT_MAX - 13, 16, 1, 0, 1, 0, 0, 0 },
  121. { 1, UINT_MAX, 1, 1, 0, 0, 0, 0 },
  122. { 2, UINT_MAX, 1, 1, 1, 0, 0, 0 },
  123. { UINT_MAX, 0, 0, 0, 0, 1, 1, 1 },
  124. };
  125. static int test_uint_ops(int n)
  126. {
  127. int err;
  128. unsigned int r;
  129. const unsigned int a = test_uints[n].a, b = test_uints[n].b;
  130. err = 0;
  131. r = safe_add_uint(a, b, &err);
  132. if (!TEST_int_eq(err, test_uints[n].sum_err)
  133. || (!err && !TEST_uint_eq(r, a + b)))
  134. goto err;
  135. err = 0;
  136. r = safe_sub_uint(a, b, &err);
  137. if (!TEST_int_eq(err, test_uints[n].sub_err)
  138. || (!err && !TEST_uint_eq(r, a - b)))
  139. goto err;
  140. err = 0;
  141. r = safe_mul_uint(a, b, &err);
  142. if (!TEST_int_eq(err, test_uints[n].mul_err)
  143. || (!err && !TEST_uint_eq(r, a * b)))
  144. goto err;
  145. err = 0;
  146. r = safe_div_uint(a, b, &err);
  147. if (!TEST_int_eq(err, test_uints[n].div_err)
  148. || (!err && !TEST_uint_eq(r, a / b)))
  149. goto err;
  150. err = 0;
  151. r = safe_mod_uint(a, b, &err);
  152. if (!TEST_int_eq(err, test_uints[n].mod_err)
  153. || (!err && !TEST_uint_eq(r, a % b)))
  154. goto err;
  155. err = 0;
  156. r = safe_div_round_up_uint(a, b, &err);
  157. if (!TEST_int_eq(err, test_uints[n].div_round_up_err)
  158. || (!err && !TEST_uint_eq(r, a / b + (a % b != 0))))
  159. goto err;
  160. err = 0;
  161. r = safe_neg_uint(a, &err);
  162. if (!TEST_int_eq(err, a != 0) || (!err && !TEST_uint_eq(r, 0)))
  163. goto err;
  164. err = 0;
  165. r = safe_neg_uint(b, &err);
  166. if (!TEST_int_eq(err, b != 0) || (!err && !TEST_uint_eq(r, 0)))
  167. goto err;
  168. err = 0;
  169. r = safe_abs_uint(a, &err);
  170. if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, a))
  171. goto err;
  172. err = 0;
  173. r = safe_abs_uint(b, &err);
  174. if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, b))
  175. goto err;
  176. return 1;
  177. err:
  178. TEST_info("a = %u b = %u r = %u err = %d", a, b, r, err);
  179. return 0;
  180. }
  181. static const struct {
  182. size_t a, b;
  183. int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
  184. } test_size_ts[] = {
  185. { 3, 1, 0, 0, 0, 0, 0, 0 },
  186. { 1, 3, 0, 1, 0, 0, 0, 0 },
  187. { 36, 8, 0, 0, 0, 0, 0, 0 },
  188. { SIZE_MAX, 1, 1, 0, 0, 0, 0, 0 },
  189. { SIZE_MAX, 2, 1, 0, 1, 0, 0, 0 },
  190. { SIZE_MAX, 8, 1, 0, 1, 0, 0, 0 },
  191. { SIZE_MAX - 3, 8, 1, 0, 1, 0, 0, 0 },
  192. { 1, SIZE_MAX, 1, 1, 0, 0, 0, 0 },
  193. { 2, SIZE_MAX, 1, 1, 1, 0, 0, 0 },
  194. { 11, 0, 0, 0, 0, 1, 1, 1 },
  195. };
  196. static int test_size_t_ops(int n)
  197. {
  198. int err;
  199. size_t r;
  200. const size_t a = test_size_ts[n].a, b = test_size_ts[n].b;
  201. err = 0;
  202. r = safe_add_size_t(a, b, &err);
  203. if (!TEST_int_eq(err, test_size_ts[n].sum_err)
  204. || (!err && !TEST_size_t_eq(r, a + b)))
  205. goto err;
  206. err = 0;
  207. r = safe_sub_size_t(a, b, &err);
  208. if (!TEST_int_eq(err, test_size_ts[n].sub_err)
  209. || (!err && !TEST_size_t_eq(r, a - b)))
  210. goto err;
  211. err = 0;
  212. r = safe_mul_size_t(a, b, &err);
  213. if (!TEST_int_eq(err, test_size_ts[n].mul_err)
  214. || (!err && !TEST_size_t_eq(r, a * b)))
  215. goto err;
  216. err = 0;
  217. r = safe_div_size_t(a, b, &err);
  218. if (!TEST_int_eq(err, test_size_ts[n].div_err)
  219. || (!err && !TEST_size_t_eq(r, a / b)))
  220. goto err;
  221. err = 0;
  222. r = safe_mod_size_t(a, b, &err);
  223. if (!TEST_int_eq(err, test_size_ts[n].mod_err)
  224. || (!err && !TEST_size_t_eq(r, a % b)))
  225. goto err;
  226. err = 0;
  227. r = safe_div_round_up_size_t(a, b, &err);
  228. if (!TEST_int_eq(err, test_size_ts[n].div_round_up_err)
  229. || (!err && !TEST_size_t_eq(r, a / b + (a % b != 0))))
  230. goto err;
  231. err = 0;
  232. r = safe_neg_size_t(a, &err);
  233. if (!TEST_int_eq(err, a != 0) || (!err && !TEST_size_t_eq(r, 0)))
  234. goto err;
  235. err = 0;
  236. r = safe_neg_size_t(b, &err);
  237. if (!TEST_int_eq(err, b != 0) || (!err && !TEST_size_t_eq(r, 0)))
  238. goto err;
  239. err = 0;
  240. r = safe_abs_size_t(a, &err);
  241. if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, a))
  242. goto err;
  243. err = 0;
  244. r = safe_abs_size_t(b, &err);
  245. if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, b))
  246. goto err;
  247. return 1;
  248. err:
  249. TEST_info("a = %zu b = %zu r = %zu err = %d", a, b, r, err);
  250. return 0;
  251. }
  252. static const struct {
  253. int a, b, c;
  254. int err;
  255. } test_muldiv_ints[] = {
  256. { 3, 1, 2, 0 },
  257. { 1, 3, 2, 0 },
  258. { -3, 1, 2, 0 },
  259. { 1, 3, -2, 0 },
  260. { INT_MAX, INT_MAX, INT_MAX, 0 },
  261. { INT_MIN, INT_MIN, INT_MAX, 1 },
  262. { INT_MIN, INT_MIN, INT_MIN, 0 },
  263. { INT_MAX, 2, 4, 0 },
  264. { 8, INT_MAX, 4, 1 },
  265. { INT_MAX, 8, 4, 1 },
  266. { INT_MIN, 2, 4, 1 },
  267. { 8, INT_MIN, 4, 1 },
  268. { INT_MIN, 8, 4, 1 },
  269. { 3, 4, 0, 1 },
  270. };
  271. static int test_int_muldiv(int n)
  272. {
  273. int err = 0;
  274. int r, real = 0;
  275. const int a = test_muldiv_ints[n].a;
  276. const int b = test_muldiv_ints[n].b;
  277. const int c = test_muldiv_ints[n].c;
  278. r = safe_muldiv_int(a, b, c, &err);
  279. if (c != 0)
  280. real = (int)((int64_t)a * (int64_t)b / (int64_t)c);
  281. if (!TEST_int_eq(err, test_muldiv_ints[n].err)
  282. || (!err && !TEST_int_eq(r, real))) {
  283. TEST_info("%d * %d / %d r = %d err = %d", a, b, c, r, err);
  284. return 0;
  285. }
  286. return 1;
  287. }
  288. static const struct {
  289. unsigned int a, b, c;
  290. int err;
  291. } test_muldiv_uints[] = {
  292. { 3, 1, 2, 0 },
  293. { 1, 3, 2, 0 },
  294. { UINT_MAX, UINT_MAX, UINT_MAX, 0 },
  295. { UINT_MAX, 2, 4, 0 },
  296. { 8, UINT_MAX, 4, 1 },
  297. { UINT_MAX, 8, 4, 1 },
  298. { 3, 4, 0, 1 },
  299. };
  300. static int test_uint_muldiv(int n)
  301. {
  302. int err = 0;
  303. unsigned int r, real = 0;
  304. const unsigned int a = test_muldiv_uints[n].a;
  305. const unsigned int b = test_muldiv_uints[n].b;
  306. const unsigned int c = test_muldiv_uints[n].c;
  307. r = safe_muldiv_uint(a, b, c, &err);
  308. if (c != 0)
  309. real = (unsigned int)((uint64_t)a * (uint64_t)b / (uint64_t)c);
  310. if (!TEST_int_eq(err, test_muldiv_uints[n].err)
  311. || (!err && !TEST_uint_eq(r, real))) {
  312. TEST_info("%u * %u / %u r = %u err = %d", a, b, c, r, err);
  313. return 0;
  314. }
  315. return 1;
  316. }
  317. int setup_tests(void)
  318. {
  319. ADD_ALL_TESTS(test_int_ops, OSSL_NELEM(test_ints));
  320. ADD_ALL_TESTS(test_uint_ops, OSSL_NELEM(test_uints));
  321. ADD_ALL_TESTS(test_size_t_ops, OSSL_NELEM(test_size_ts));
  322. ADD_ALL_TESTS(test_int_muldiv, OSSL_NELEM(test_muldiv_ints));
  323. ADD_ALL_TESTS(test_uint_muldiv, OSSL_NELEM(test_muldiv_uints));
  324. return 1;
  325. }