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